Foursquare has updated how OS Places is accessed. Older versions of this guide queried
date-pinned files in a public S3 bucket; access now uses the Places Portal and an
authenticated Iceberg catalog. See Foursquare’s OS Places access documentation
for details.
Before you begin
Before running the queries in this guide, you need:- A Foursquare Places Portal account
- An access token created from the Access Data tab of the OS Places dataset
Connect to the Foursquare catalog
Keep your access token private. Start your ClickHouse client, then replace<YOUR_ACCESS_TOKEN> in the following query with your token:
Query
places_os table reflects Foursquare’s current
published release rather than a date-pinned Parquet release, so its rows and schema can
change over time. Queries without an ORDER BY clause may therefore return different
sample rows than the responses shown in this guide.
Verify the connection
Query one row from theplaces_os Iceberg table:
Query
Response
Explore the data
The sample row contains several null fields. Add filters to return a more complete row:Query
Response
DESCRIBE to inspect the table schema:
Query
Response
Load the data into ClickHouse
To persist the data, create a table onclickhouse-server or ClickHouse Cloud.
Create a MergeTree table with dictionary-encoded columns and materialized Web Mercator
coordinates:
Query
LowCardinality data type,
which stores repeated values with dictionary encoding. This representation can significantly
improve SELECT query performance.
The two UInt32 MATERIALIZED columns, mercator_x and mercator_y, map latitude and
longitude to the Web Mercator projection,
which makes it easier to segment the map into tiles:
longitude + 180shifts the longitude range from [-180, 180] to [0, 360].- Dividing by 360 normalizes the value to a range between 0 and 1.
- Multiplying by
0xFFFFFFFF, the maximum 32-bit unsigned integer, scales the normalized value to the full range of a 32-bit integer.
latitude + 90shifts the latitude range from [-90, 90] to [0, 180].- Dividing by 360 and multiplying by
piconverts the value to radians for the trigonometric functions. log(tan(...))applies the core Mercator projection formula.- Multiplying by
0xFFFFFFFFscales the result to the full 32-bit integer range.
MATERIALIZED makes ClickHouse calculate these values when data is inserted,
without requiring the source data to contain the columns.
The table is ordered by mortonEncode(mercator_x, mercator_y), which creates a Z-order
space-filling curve and organizes data by spatial proximity:
minmax indices further accelerate spatial filtering:
Query
unresolved_flags because it
is not needed by the local table and filters out rows without coordinates because they
cannot be placed on the map. Other nullable source values remain null in the local table.
Visualize the data
Foursquare’s access model has changed since these visualizations were created. The
original interactive Places view
predates the current access model and is linked for historical reference, but it may no
longer display Places data. The images below are retained as historical examples.