Geo distance aggregation #
A multi-bucket aggregation like
range, but buckets are
distance rings around a geo_point origin. It answers “how many
things are near me?” — counts per radius band in a single request,
no matter how many rings you declare.
How it works #
Every document’s point is measured against the origin with the
haversine formula on a spherical Earth (mean radius 6,371,008.8 m —
within ~0.5 % of the WGS-84 ellipsoid). The origin accepts either a
"lat,lon" string or a { "lat": …, "lon": … } object; an origin
that parses to nothing yields zero buckets.
Each range then places the document: from is inclusive, to is
exclusive, both in metres. Ranges are checked independently, so
overlapping ranges double-count a document, and every declared range
produces exactly one bucket — in declaration order, empty ones
included. A bucket without an explicit key is named "{from}-{to}"
with * for the unbounded side (*-500000, 500000-*). Nested
sub-aggregations run per ring over that ring’s documents.
Examples #
Ring the Beijing area origin at 500 km:
Two places fall inside 500 km, thirteen beyond — matching the
geo_distance query answer:
{
...
"aggregations": {
"by_distance": {
"buckets": [
{ "key": "*-500000", "doc_count": 2 },
{ "key": "500000-*", "doc_count": 13 }
]
}
}
}
Use cases #
- Radius reporting. “Stores within 50 km / 50–200 km / beyond” as one request — the classic store-locator bands.
- Delivery-zone coverage. Ring a warehouse origin and nest a
sumper ring to weigh each zone’s demand, not just count it. - Local-vs-remote splits. Any near/far comparison around a fixed point: users near an event, sensors near a fault line.
- Query faceting. Combine with a
geo_bounding_boxquery so the rings summarize only the mapped viewport.
Parameters for geo_distance
#
field
(Required, string)geo_pointfield you wish to aggregate.origin
(Required, object){ "lat": …, "lon": … }center point (a"lat,lon"string is also accepted).ranges
(Required, object array) Buckets with optionalfrom/toin metres (frominclusive,toexclusive);keynames a bucket.aggs
(Optional, object) Nested sub-aggregations, computed per ring.
Distances are always computed and reported in metres; the unit
and distance_type parameters are not accepted.
Related #
range— the same bucketing over plain numeric fieldsgeohash_grid,geotile_grid— grid-shaped geo bucketinggeo_distancequery — filter to one radius instead of counting bandsgeo_centroid— where inside a ring the points actually sit