Geohash grid aggregations
The geohash_grid aggregation groups documents into grid cells based on their geohash value. Each cell is labeled with its geohash string, and the precision parameter controls cell size—lower precision values produce fewer, larger cells, while higher values produce many smaller cells. You can aggregate documents on geo_point or geo_shape fields. A geo_point is placed in exactly one cell, while a geo_shape is counted in every cell it intersects.
Precision values range from 1 to 12. High-precision requests can consume significant memory and produce large responses because they generate many buckets. Filter to a small geographic area before using high precision values.
Parameters
The geohash_grid aggregation takes the following parameters.
| Parameter | Required/Optional | Data type | Description |
|---|---|---|---|
field | Required | String | The field to aggregate on. Must be mapped as geo_point or geo_shape. |
precision | Optional | Integer or String | The geohash length controlling cell size. Valid integer values are 1–12. You can also specify an approximate distance (for example, 1km or 10m), and OpenSearch selects the precision level whose cells do not exceed that size. Default is 5. |
bounds | Optional | Object | A bounding box that restricts which points are considered. Only points within the box are aggregated. Accepts all geo_point formats. |
size | Optional | Integer | The maximum number of buckets to return. When there are more buckets than size, buckets with the highest document counts are returned. Default is 10000. |
shard_size | Optional | Integer | The maximum number of buckets returned from each shard. Default is max(10, size × number of shards). |
Example: Low-precision grid
The following example groups ecommerce customer locations into geohash cells at precision 4 (approximately 39 km × 19.5 km):
GET /opensearch_dashboards_sample_data_ecommerce/_search
{
"size": 0,
"aggs": {
"geo_hash": {
"geohash_grid": {
"field": "geoip.location",
"precision": 4
}
}
}
}
Example: High-precision grid with bounding box filter
When zooming into a specific region, first filter documents to that area before requesting high precision. The following example uses a geo_bounding_box query to narrow to the New York City area, then aggregates at precision 7 (approximately 153 m × 152 m):
GET /opensearch_dashboards_sample_data_ecommerce/_search
{
"size": 0,
"aggs": {
"zoomed_in": {
"filter": {
"geo_bounding_box": {
"geoip.location": {
"top_left": "41.0, -74.5",
"bottom_right": "40.5, -73.5"
}
}
},
"aggs": {
"detailed_grid": {
"geohash_grid": {
"field": "geoip.location",
"precision": 7
}
}
}
}
}
}
Example response
The following response corresponds to the high-precision example:
{
"took": 23,
"timed_out": false,
"terminated_early": true,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 4675,
"relation": "eq"
},
"max_score": null,
"hits": []
},
"aggregations": {
"zoomed_in": {
"doc_count": 896,
"detailed_grid": {
"buckets": [
{
"key": "dr72h56",
"doc_count": 747
},
{
"key": "dr5rs14",
"doc_count": 149
}
]
}
}
}
}
Response body fields
The following table lists the response body fields.
| Field | Data type | Description |
|---|---|---|
buckets | Array | The grid cell buckets, ordered by doc_count descending. |
buckets.key | String | The geohash string identifying the cell. |
buckets.doc_count | Integer | The number of documents (or geoshape intersections) in this cell. |
You can use a returned geohash key as both the top_left and bottom_right of a geo_bounding_box query to zoom into that cell at a higher precision. Client-side geohash libraries (such as ngeohash for JavaScript) can decode bucket keys into lat/lon bounding boxes for map rendering.
Aggregating geoshapes
To run an aggregation on a geoshape field, first create an index and map the location field as a geo_shape:
PUT /national_parks
{
"mappings": {
"properties": {
"location": {
"type": "geo_shape"
}
}
}
}
Next, index some documents into the national_parks index:
PUT /national_parks/_doc/1
{
"name": "Yellowstone National Park",
"location":
{"type": "envelope","coordinates": [ [-111.15, 45.12], [-109.83, 44.12] ]}
}
PUT /national_parks/_doc/2
{
"name": "Yosemite National Park",
"location":
{"type": "envelope","coordinates": [ [-120.23, 38.16], [-119.05, 37.45] ]}
}
PUT /national_parks/_doc/3
{
"name": "Death Valley National Park",
"location":
{"type": "envelope","coordinates": [ [-117.34, 37.01], [-116.38, 36.25] ]}
}
You can run an aggregation on the location field as follows:
GET /national_parks/_search
{
"aggregations": {
"grouped": {
"geohash_grid": {
"field": "location",
"precision": 1
}
}
}
}
A geoshape can appear in multiple buckets when it spans more than one grid cell:
Response
{
"took" : 24,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "national_parks",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"name" : "Yellowstone National Park",
"location" : {
"type" : "envelope",
"coordinates" : [
[
-111.15,
45.12
],
[
-109.83,
44.12
]
]
}
}
},
{
"_index" : "national_parks",
"_id" : "2",
"_score" : 1.0,
"_source" : {
"name" : "Yosemite National Park",
"location" : {
"type" : "envelope",
"coordinates" : [
[
-120.23,
38.16
],
[
-119.05,
37.45
]
]
}
}
},
{
"_index" : "national_parks",
"_id" : "3",
"_score" : 1.0,
"_source" : {
"name" : "Death Valley National Park",
"location" : {
"type" : "envelope",
"coordinates" : [
[
-117.34,
37.01
],
[
-116.38,
36.25
]
]
}
}
}
]
},
"aggregations" : {
"grouped" : {
"buckets" : [
{
"key" : "9",
"doc_count" : 3
},
{
"key" : "c",
"doc_count" : 1
}
]
}
}
}
OpenSearch supports geoshape aggregation through the API but not in OpenSearch Dashboards visualizations.
Geohash precision
The following table lists the approximate cell dimensions at each precision level. Cell dimensions vary with latitude; the values shown represent the widest case at the equator.
| Precision / geohash length | Latitude bits | Longitude bits | Latitude error | Longitude error | Cell height | Cell width |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | ±23 | ±23 | 4992.6 km | 5009.4 km |
| 2 | 5 | 5 | ±2.8 | ±5.6 | 624.1 km | 1252.3 km |
| 3 | 7 | 8 | ±0.70 | ±0.70 | 156 km | 156.5 km |
| 4 | 10 | 10 | ±0.087 | ±0.18 | 19.5 km | 39.1 km |
| 5 | 12 | 13 | ±0.022 | ±0.022 | 4.9 km | 4.9 km |
| 6 | 15 | 15 | ±0.0027 | ±0.0055 | 609.4 m | 1.2 km |
| 7 | 17 | 18 | ±0.00068 | ±0.00068 | 152.5 m | 152.9 m |
| 8 | 20 | 20 | ±0.00086 | ±0.000172 | 19 m | 38.2 m |
| 9 | 22 | 23 | ±0.000021 | ±0.000021 | 4.8 m | 4.8 m |
| 10 | 25 | 25 | ±0.00000268 | ±0.00000536 | 59.5 cm | 1.2 m |
| 11 | 27 | 28 | ±0.00000067 | ±0.00000067 | 14.9 cm | 14.9 cm |
| 12 | 30 | 30 | ±0.00000008 | ±0.00000017 | 1.9 cm | 3.7 cm |