# 地理距离聚合(Geo Distance Aggregation)

在geo\_point字段上工作的多bucket聚合和概念上的工作非常类似于[range](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-range-aggregation.html)(范围)聚合.

用户可以定义原点的点和距离范围的集合。聚合计算每个文档值与原点的距离，并根据范围确定其所属的bucket(桶)（如果文档和原点之间的距离落在bucket(桶)的距离范围内，则文档属于bucket(桶) )

```
PUT /museums
{
    "mappings": {
        "doc": {
            "properties": {
                "location": {
                    "type": "geo_point"
                }
            }
        }
    }
}

POST /museums/doc/_bulk?refresh
{"index":{"_id":1}}
{"location": "52.374081,4.912350", "name": "NEMO Science Museum"}
{"index":{"_id":2}}
{"location": "52.369219,4.901618", "name": "Museum Het Rembrandthuis"}
{"index":{"_id":3}}
{"location": "52.371667,4.914722", "name": "Nederlands Scheepvaartmuseum"}
{"index":{"_id":4}}
{"location": "51.222900,4.405200", "name": "Letterenhuis"}
{"index":{"_id":5}}
{"location": "48.861111,2.336389", "name": "Musée du Louvre"}
{"index":{"_id":6}}
{"location": "48.860000,2.327000", "name": "Musée d'Orsay"}

POST /museums/_search?size=0
{
    "aggs" : {
        "rings_around_amsterdam" : {
            "geo_distance" : {
                "field" : "location",
                "origin" : "52.3760, 4.894",
                "ranges" : [
                    { "to" : 100000 },
                    { "from" : 100000, "to" : 300000 },
                    { "from" : 300000 }
                ]
            }
        }
    }
}
```

响应结果：

```
{
    ...
    "aggregations": {
        "rings_around_amsterdam" : {
            "buckets": [
                {
                    "key": "*-100000.0",
                    "from": 0.0,
                    "to": 100000.0,
                    "doc_count": 3
                },
                {
                    "key": "100000.0-300000.0",
                    "from": 100000.0,
                    "to": 300000.0,
                    "doc_count": 1
                },
                {
                    "key": "300000.0-*",
                    "from": 300000.0,
                    "doc_count": 2
                }
            ]
        }
    }
}
```

指定的字段必须是geo\_point类型（只能在映射中显式设置）。它还可以保存一个geo\_point字段的数组，在这种情况下，在聚合期间将考虑所有这些字段。原点可以接受geo\_point类型支持的所有格式:

* 对象格式：{ "lat" : 52.3760, "lon" : 4.894 }－ 这是最安全的格式，因为它是最明确的lat (纬度)& lon(经度)值
* 字符串格式："52.3760, 4.894"  － 第一个数值是lat(纬度)，第二个是lon(经度)
* 数组格式：\[4.894, 52.3760]  － 它基于GeoJson标准，第一个数字是lon(经度)，第二个数字是lat(纬度)

在默认情况下，距离单位是m(米)，但它也可以接受:mi(英里)，in(英寸)，yd(码)，km(公里)，cm(厘米)，毫米(毫米)

```
POST /museums/_search?size=0
{
    "aggs" : {
        "rings" : {
            "geo_distance" : {
                "field" : "location",
                "origin" : "52.3760, 4.894",
                "unit" : "km", ＃1
                "ranges" : [
                    { "to" : 100 },
                    { "from" : 100, "to" : 300 },
                    { "from" : 300 }
                ]
            }
        }
    }
}
```

＃1 距离将以公里计算

有两种距离计算模式：arc(默认) 和 plane， arc(电弧)计算模式是最准确的，plane模式是最快的，但是最不准确。当考虑搜索上下文是“narrow”,跨越较小的地理区域（约5km）可以用plane，plane将为非常大的区域（例如跨大陆搜索）的搜索返回更高的误差区间。距离计算类型可以使用distance\_type参数设置。

```
POST /museums/_search?size=0
{
    "aggs" : {
        "rings" : {
            "geo_distance" : {
                "field" : "location",
                "origin" : "52.3760, 4.894",
                "unit" : "km",
                "distance_type" : "plane",
                "ranges" : [
                    { "to" : 100 },
                    { "from" : 100, "to" : 300 },
                    { "from" : 300 }
                ]
            }
        }
    }
}
```

## Keyed Response <a href="#geodistanceaggregation-di-li-ju-li-ju-he-keyedresponse" id="geodistanceaggregation-di-li-ju-li-ju-he-keyedresponse"></a>

将keyed标志设置为true会将一个惟一的字符串键与每个bucket(桶)关联起来，并将范围作为散列而不是数组返回:

```
POST /museums/_search?size=0
{
    "aggs" : {
        "rings_around_amsterdam" : {
            "geo_distance" : {
                "field" : "location",
                "origin" : "52.3760, 4.894",
                "ranges" : [
                    { "to" : 100000 },
                    { "from" : 100000, "to" : 300000 },
                    { "from" : 300000 }
                ],
                "keyed": true
            }
        }
    }
}
```

返回结果：

```
{
    ...
    "aggregations": {
        "rings_around_amsterdam" : {
            "buckets": {
                "*-100000.0": {
                    "from": 0.0,
                    "to": 100000.0,
                    "doc_count": 3
                },
                "100000.0-300000.0": {
                    "from": 100000.0,
                    "to": 300000.0,
                    "doc_count": 1
                },
                "300000.0-*": {
                    "from": 300000.0,
                    "doc_count": 2
                }
            }
        }
    }
}
```

也可以为每个范围自定义key

```
POST /museums/_search?size=0
{
    "aggs" : {
        "rings_around_amsterdam" : {
            "geo_distance" : {
                "field" : "location",
                "origin" : "52.3760, 4.894",
                "ranges" : [
                    { "to" : 100000, "key": "first_ring" },
                    { "from" : 100000, "to" : 300000, "key": "second_ring" },
                    { "from" : 300000, "key": "third_ring" }
                ],
                "keyed": true
            }
        }
    }
}
```

返回结果：

```
{
    ...
    "aggregations": {
        "rings_around_amsterdam" : {
            "buckets": {
                "first_ring": {
                    "from": 0.0,
                    "to": 100000.0,
                    "doc_count": 3
                },
                "second_ring": {
                    "from": 100000.0,
                    "to": 300000.0,
                    "doc_count": 1
                },
                "third_ring": {
                    "from": 300000.0,
                    "doc_count": 2
                }
            }
        }
    }
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://xiaoxiami.gitbook.io/elasticsearch/ji-chu/36aggregationsju-he-fen-679029/362tong-ju540828-bucketaggregations/di-li-ju-li-ju-540828-geo-distance-aggregation.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
