H3 datasets
Once a dataset is partitioned and indexed with fused.h3, any HTTP client can read it with GET /h3/query: a point, a bounding box, an H3 cell or a time window comes back as a Parquet file, without running a UDF. fused.h3.query() is a client of this endpoint.
A public dataset needs no credentials, so a browser page can call the endpoint directly. The AIS map loads every ship position report on screen this way, one /h3/query request per map tile.
Query a dataset
GET /h3/query
Scope: public or authorized. With no credentials, only a public dataset at a literal s3:// path whose files are publicly readable can be read (403 otherwise). With credentials, path resolves to your environment's own dataset, else to the public one.
Returns the matching rows as a Parquet file.
curl -G "https://www.fused.io/server/v1/h3/query" \
--data-urlencode "path=s3://fused-asset/data/ais/ais_week_h3_v2/" \
-d min_lng=-74.10 -d min_lat=40.55 -d max_lng=-73.90 -d max_lat=40.72 \
-d time_min=2024-07-03T12:00:00 -d time_max=2024-07-03T12:59:59 \
-d columns=MMSI -d columns=VesselName -d columns=BaseDateTime \
-d columns=LAT -d columns=LON -d columns=SOG \
-o harbor.parquet
This reads the 6,214 position reports in New York Harbor between 12:00 and 13:00 UTC on July 3, 2024, from the public AIS dataset.
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
path | string | Yes | The indexed dataset, as passed to fused.h3.index() |
min_lng, min_lat, max_lng, max_lat | number | No | A bounding box. Give all four. |
lat, lng | number | No | A point. Give both. |
cell | string | No | An H3 cell id as a hex string. Returns every row in that cell, or in its descendants when cell is coarser than the dataset. |
hex_min, hex_max | string | No | An inclusive range of raw H3 cell ids, each as a hex string |
time_min, time_max | string | No | An inclusive ISO datetime window. Omitted, the whole time range is read. |
partition | string | No | JSON object mapping a partition column to a value, or a list of values that any may match. See Filter by partition. |
partition_range | string | No | JSON object mapping a partition column to an inclusive [min, max], with null for an open end |
columns | string | No | A column to return. Repeat the parameter for several. Omitted, every column is returned. |
format | string | No | What to return. Leave it out to get the matching rows. Use stats or files to inspect a query without downloading any rows: stats returns JSON with the min and max of each column listed in columns (required with stats), for each row group (block of rows in a file) the query matches. See Stats format. files returns JSON listing the files the query would read, with their row counts. See Files format. |
max_row_groups | integer | No | Row groups per page, from 1 to 16,384. At most 4,096 when returning rows. Default 1,024. |
cursor | string | No | The cursor from the previous page. See Page through large results. |
Pass at most one spatial selector: the bounding box, the point, cell, or hex_min and hex_max. With none, the query reads the whole dataset, narrowed only by time and partition.
Filter by partition
partition and partition_range select folders written with partition_by in fused.h3.partition(), for example partition={"date": "2024-07-03"} or partition_range={"date": ["2024-07-01", "2024-07-07"]}. A folder must match every column named. A date column matches a folder whose period (YYYY, YYYY-MM or YYYY-MM-DD) overlaps the value or range.
Page through large results
A large result comes back one page at a time. When more remain, the response carries a cursor: the X-Fused-Next-Cursor header when returning rows, or the next_cursor field of the body for format=stats. Send it back as cursor, with the same query, until a response has none. format=files always answers in one page.
Stats format
format=stats returns JSON with min and max values per row group, without reading any rows. columns is required, and each column must be a number, date, timestamp or string column of the matched files, other than the H3 column. The body has h3_resolution, partitions (the folders of this page's row groups), next_cursor, and row_groups: parallel arrays h3_min and h3_max (hex strings), partition (an index into partitions) and stats ({column: {min: [...], max: [...]}}), one entry per row group.
Files format
format=files returns JSON describing the indexed files that overlap the query, without opening any. The body has level ("file"), h3_resolution (the resolution of the data cells), cell_resolution (the resolution of the H3 cells that name the files), cells (the H3 cell, in lowercase hex, that names each file) and row_counts: parallel arrays total (each file's rows in the matched folders) and window (only the rows in folders the time window overlaps). columns, max_row_groups and cursor are ignored. time_min and time_max narrow the answer only when the time column is a date partition column.
Errors
| Status | When |
|---|---|
400 | More than one spatial selector, an incomplete one (for example lat without lng), or an invalid cell id |
400 | time_min or time_max on a dataset with no time column |
400 | partition or partition_range that is not a JSON object, names a column that is not a partition column, or holds a value of the wrong type |
400 | max_row_groups above 4,096 when returning rows |
400 | format=stats with no columns, with the H3 column, with a column that no matched file has, or with a column type it cannot summarize |
400 | format=files selecting more than 2,048 folders |
400 | A malformed cursor, or one from a different query |
403 | No credentials, and path is not a public s3:// dataset |
404 | You can read no dataset at path |
409 | The dataset has never finished indexing, or the cursor predates a re-index |
422 | A name in columns is missing from the indexed files, max_row_groups is above 16,384, or (format=files) an indexed file is not named by an H3 cell |
See also
- H3 Data Retrieval Service: partition and index a dataset so it can be queried
- Working with H3: the H3 workflow end to end
fused.h3: the Python client for this endpoint