地理查询
edit地理查询
editElasticsearch 支持两种类型的地理数据:
geo_point 字段,支持纬度/经度对,以及
geo_shape 字段,支持点、
线、圆、多边形、多多边形等。
本组中的查询包括:
-
geo_bounding_boxquery - 查找与指定矩形相交的地理形状或地理点的文档。
-
geo_distancequery - 查找位于中心点指定距离内的地理形状或地理点的文档。
-
geo_gridquery -
查找包含以下内容的文档:
- 与指定geohash相交的地理形状或地理点
- 与指定地图瓦片相交的地理形状或地理点
- 与指定H3 bin相交的地理点
-
geo_polygonquery - 查找与指定多边形相交的地理形状或地理点的文档。
-
geo_shapequery - 查找与指定地理形状相关的地理形状或地理点的文档。 可以指定的空间关系包括:相交、包含、被包含和不相交。
地理边界框查询
edit匹配与边界框相交的 geo_point 和 geo_shape 值。
示例
edit假设以下文档已被索引:
PUT /my_locations
{
"mappings": {
"properties": {
"pin": {
"properties": {
"location": {
"type": "geo_point"
}
}
}
}
}
}
PUT /my_locations/_doc/1
{
"pin": {
"location": {
"lat": 40.12,
"lon": -71.34
}
}
}
PUT /my_geoshapes
{
"mappings": {
"properties": {
"pin": {
"properties": {
"location": {
"type": "geo_shape"
}
}
}
}
}
}
PUT /my_geoshapes/_doc/1
{
"pin": {
"location": {
"type" : "polygon",
"coordinates" : [[[13.0 ,51.5], [15.0, 51.5], [15.0, 54.0], [13.0, 54.0], [13.0 ,51.5]]]
}
}
}
使用 geo_bounding_box 过滤器来匹配与边界框相交的 geo_point 值。要定义该框,请为两个对角提供地理点值。
GET my_locations/_search
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_bounding_box": {
"pin.location": {
"top_left": {
"lat": 40.73,
"lon": -74.1
},
"bottom_right": {
"lat": 40.01,
"lon": -71.12
}
}
}
}
}
}
}
使用相同的过滤器来匹配与边界框相交的 geo_shape 值:
GET my_geoshapes/_search
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_bounding_box": {
"pin.location": {
"top_left": {
"lat": 40.73,
"lon": -74.1
},
"bottom_right": {
"lat": 40.01,
"lon": -71.12
}
}
}
}
}
}
}
要匹配 geo_point 和 geo_shape 值,请搜索两个索引:
GET my_locations,my_geoshapes/_search
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_bounding_box": {
"pin.location": {
"top_left": {
"lat": 40.73,
"lon": -74.1
},
"bottom_right": {
"lat": 40.01,
"lon": -71.12
}
}
}
}
}
}
}
查询选项
edit| Option | Description |
|---|---|
|
可选的名称字段,用于标识过滤器 |
|
设置为 |
接受的格式
edit与geo_point类型可以接受不同的地理点表示方式类似,过滤器也可以接受这些表示方式:
经纬度作为属性
editGET my_locations/_search
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_bounding_box": {
"pin.location": {
"top_left": {
"lat": 40.73,
"lon": -74.1
},
"bottom_right": {
"lat": 40.01,
"lon": -71.12
}
}
}
}
}
}
}
经纬度作为数组
edit格式为 [lon, lat],注意,这里的经纬度顺序是为了符合 GeoJSON 的规范。
GET my_locations/_search
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_bounding_box": {
"pin.location": {
"top_left": [ -74.1, 40.73 ],
"bottom_right": [ -71.12, 40.01 ]
}
}
}
}
}
}
经纬度字符串
edit格式为 纬度,经度。
GET my_locations/_search
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_bounding_box": {
"pin.location": {
"top_left": "POINT (-74.1 40.73)",
"bottom_right": "POINT (-71.12 40.01)"
}
}
}
}
}
}
边界框作为熟知文本 (WKT)
editGET my_locations/_search
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_bounding_box": {
"pin.location": {
"wkt": "BBOX (-74.1, -71.12, 40.73, 40.01)"
}
}
}
}
}
}
Geohash
editGET my_locations/_search
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_bounding_box": {
"pin.location": {
"top_left": "dr5r9ydj2y73",
"bottom_right": "drj7teegpus6"
}
}
}
}
}
}
当使用geohashes来指定边界框的边缘时,geohashes被视为矩形。边界框的定义方式是,其左上角对应于top_left参数中指定的geohash的左上角,其右下角定义为bottom_right参数中指定的geohash的右下角。
为了指定一个与geohash整个区域匹配的边界框,可以在top_left和bottom_right参数中指定geohash:
GET my_locations/_search
{
"query": {
"geo_bounding_box": {
"pin.location": {
"top_left": "dr",
"bottom_right": "dr"
}
}
}
}
在这个例子中,geohash dr 将生成一个边界框查询,其左上角位于 45.0,-78.75,右下角位于 39.375,-67.5。
顶点
edit边界框的顶点可以通过top_left和bottom_right参数或top_right和bottom_left参数来设置。除了成对设置值外,还可以使用简单的名称top、left、bottom和right来分别设置值。
GET my_locations/_search
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_bounding_box": {
"pin.location": {
"top": 40.73,
"left": -74.1,
"bottom": 40.01,
"right": -71.12
}
}
}
}
}
}
每个文档的多位置
edit过滤器可以处理每个文档的多个位置/点。一旦单个位置/点匹配过滤器,文档将被包含在过滤器中
忽略未映射
edit当设置为true时,ignore_unmapped选项将忽略未映射的字段,并且不会匹配此查询的任何文档。这在查询可能具有不同映射的多个索引时非常有用。当设置为false(默认值)时,如果字段未映射,查询将抛出异常。
关于精度的说明
edit地理点具有有限的精度,并且在索引期间总是向下取整。 在查询期间,边界框的上边界向下取整, 而下边界则向上取整。因此,位于下边界(边界框的底部和左侧边缘)的点可能由于取整误差而未能进入边界框。同时,位于上边界(顶部和右侧边缘)的点可能会被查询选中,即使它们位于边缘稍微外侧。取整误差应小于4.20e-8度纬度和小于8.39e-8度经度,即使在赤道上,这也转化为小于1厘米的误差。
由于四舍五入,地理形状也具有有限的精度。地理形状沿边界框底部和左侧边缘的边缘可能与geo_bounding_box查询不匹配。稍微超出框顶部和右侧边缘的地理形状边缘可能仍然匹配查询。
地理距离查询
edit匹配 geo_point 和 geo_shape 值在给定地理点的一定距离内。
示例
edit假设以下文档已被索引:
PUT /my_locations
{
"mappings": {
"properties": {
"pin": {
"properties": {
"location": {
"type": "geo_point"
}
}
}
}
}
}
PUT /my_locations/_doc/1
{
"pin": {
"location": {
"lat": 40.12,
"lon": -71.34
}
}
}
PUT /my_geoshapes
{
"mappings": {
"properties": {
"pin": {
"properties": {
"location": {
"type": "geo_shape"
}
}
}
}
}
}
PUT /my_geoshapes/_doc/1
{
"pin": {
"location": {
"type" : "polygon",
"coordinates" : [[[13.0 ,51.5], [15.0, 51.5], [15.0, 54.0], [13.0, 54.0], [13.0 ,51.5]]]
}
}
}
使用 geo_distance 过滤器来匹配在指定距离内的另一个地理点附近的 geo_point 值:
GET /my_locations/_search
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_distance": {
"distance": "200km",
"pin.location": {
"lat": 40,
"lon": -70
}
}
}
}
}
}
使用相同的过滤器来匹配在给定距离内的geo_shape值:
GET my_geoshapes/_search
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_distance": {
"distance": "200km",
"pin.location": {
"lat": 40,
"lon": -70
}
}
}
}
}
}
要匹配 geo_point 和 geo_shape 值,请搜索两个索引:
GET my_locations,my_geoshapes/_search
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_distance": {
"distance": "200km",
"pin.location": {
"lat": 40,
"lon": -70
}
}
}
}
}
}
接受的格式
edit与geo_point类型可以接受不同的地理点表示方式类似,过滤器也可以接受这些表示方式:
经纬度作为属性
editGET /my_locations/_search
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_distance": {
"distance": "12km",
"pin.location": {
"lat": 40,
"lon": -70
}
}
}
}
}
}
经纬度作为数组
edit格式为 [lon, lat],注意,这里的经纬度顺序是为了符合 GeoJSON 的规范。
GET /my_locations/_search
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_distance": {
"distance": "12km",
"pin.location": [ -70, 40 ]
}
}
}
}
}
纬度经度作为WKT字符串
edit格式为 Well-Known Text。
GET /my_locations/_search
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_distance": {
"distance": "12km",
"pin.location": "POINT (-70 40)"
}
}
}
}
}
Geohash
editGET /my_locations/_search
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_distance": {
"distance": "12km",
"pin.location": "drm3btev3e86"
}
}
}
}
}
选项
edit以下是过滤器允许的选项:
|
|
以指定位置为中心的圆的半径。落入此圆内的点被认为是匹配的。 |
|
|
如何计算距离。可以是 |
|
|
可选的名称字段以标识查询 |
|
|
设置为 |
每个文档的多位置
editThe geo_distance 过滤器可以处理每个文档的多个位置/点。一旦单个位置/点匹配过滤器,文档将被包含在过滤器中。
忽略未映射
edit当设置为true时,ignore_unmapped选项将忽略未映射的字段,并且不会匹配此查询的任何文档。这在查询可能具有不同映射的多个索引时非常有用。当设置为false(默认值)时,如果字段未映射,查询将抛出异常。
地理网格查询
edit匹配与GeoGrid聚合中的网格单元相交的geo_point和geo_shape值。
该查询旨在通过提供存储桶的键来匹配位于地理网格聚合存储桶内的文档。对于geohash和geotile网格,该查询可用于geo_point和geo_shape字段。对于geo_hex网格,它只能用于geo_point字段。
示例
edit假设以下文档已被索引:
PUT /my_locations
{
"mappings": {
"properties": {
"location": {
"type": "geo_point"
}
}
}
}
PUT /my_locations/_doc/1?refresh
{
"location" : "POINT(4.912350 52.374081)",
"city": "Amsterdam",
"name": "NEMO Science Museum"
}
PUT /my_locations/_doc/2?refresh
{
"location" : "POINT(4.405200 51.222900)",
"city": "Antwerp",
"name": "Letterenhuis"
}
PUT /my_locations/_doc/3?refresh
{
"location" : "POINT(2.336389 48.861111)",
"city": "Paris",
"name": "Musée du Louvre"
}
geohash 网格
edit使用 geohash_grid 聚合,可以根据文档的 geohash 值对其进行分组:
GET /my_locations/_search
{
"size" : 0,
"aggs" : {
"grouped" : {
"geohash_grid" : {
"field" : "location",
"precision" : 2
}
}
}
}
{
"took" : 10,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"grouped" : {
"buckets" : [
{
"key" : "u1",
"doc_count" : 2
},
{
"key" : "u0",
"doc_count" : 1
}
]
}
}
}
我们可以通过执行一个geo_grid查询来提取其中一个存储桶中的文档,使用以下语法与存储桶键:
GET /my_locations/_search
{
"query": {
"geo_grid" :{
"location" : {
"geohash" : "u0"
}
}
}
}
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "my_locations",
"_id" : "3",
"_score" : 1.0,
"_source" : {
"location" : "POINT(2.336389 48.861111)",
"city" : "Paris",
"name" : "Musée du Louvre"
}
}
]
}
}
地理网格
edit使用 geotile_grid 聚合,可以根据文档的 geotile 值对其进行分组:
GET /my_locations/_search
{
"size" : 0,
"aggs" : {
"grouped" : {
"geotile_grid" : {
"field" : "location",
"precision" : 6
}
}
}
}
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"grouped" : {
"buckets" : [
{
"key" : "6/32/21",
"doc_count" : 2
},
{
"key" : "6/32/22",
"doc_count" : 1
}
]
}
}
}
我们可以通过执行一个geo_grid查询来提取其中一个存储桶中的文档,使用以下语法与存储桶键:
GET /my_locations/_search
{
"query": {
"geo_grid" :{
"location" : {
"geotile" : "6/32/22"
}
}
}
}
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "my_locations",
"_id" : "3",
"_score" : 1.0,
"_source" : {
"location" : "POINT(2.336389 48.861111)",
"city" : "Paris",
"name" : "Musée du Louvre"
}
}
]
}
}
geohex 网格
edit使用geohex_grid聚合,可以根据文档的geohex值对其进行分组:
GET /my_locations/_search
{
"size" : 0,
"aggs" : {
"grouped" : {
"geohex_grid" : {
"field" : "location",
"precision" : 1
}
}
}
}
{
"took" : 2,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"grouped" : {
"buckets" : [
{
"key" : "81197ffffffffff",
"doc_count" : 2
},
{
"key" : "811fbffffffffff",
"doc_count" : 1
}
]
}
}
}
我们可以通过执行一个geo_grid查询来提取其中一个存储桶中的文档,使用以下语法与存储桶键:
GET /my_locations/_search
{
"query": {
"geo_grid" :{
"location" : {
"geohex" : "811fbffffffffff"
}
}
}
}
{
"took" : 26,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "my_locations",
"_id" : "3",
"_score" : 1.0,
"_source" : {
"location" : "POINT(2.336389 48.861111)",
"city" : "Paris",
"name" : "Musée du Louvre"
}
}
]
}
}
地理多边形查询
edit在7.12中已弃用。
使用 Geoshape 代替,其中多边形在 GeoJSON 或 Well-Known Text (WKT) 中定义。
返回仅落在多边形点内的命中的查询。以下是一个示例:
GET /_search
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_polygon": {
"person.location": {
"points": [
{ "lat": 40, "lon": -70 },
{ "lat": 30, "lon": -80 },
{ "lat": 20, "lon": -90 }
]
}
}
}
}
}
}
查询选项
edit| Option | Description |
|---|---|
|
可选的名称字段,用于标识过滤器 |
|
设置为 |
允许的格式
edit经纬度作为数组
edit格式为 [lon, lat]
注意:这里的经纬度顺序必须符合GeoJSON规范。
GET /_search
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_polygon": {
"person.location": {
"points": [
[ -70, 40 ],
[ -80, 30 ],
[ -90, 20 ]
]
}
}
}
}
}
}
经纬度作为字符串
edit格式为 纬度,经度。
GET /_search
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_polygon": {
"person.location": {
"points": [
"40, -70",
"30, -80",
"20, -90"
]
}
}
}
}
}
}
Geohash
editGET /_search
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_polygon": {
"person.location": {
"points": [
"drn5x1g8cu2y",
"30, -80",
"20, -90"
]
}
}
}
}
}
}
geo_point 类型
edit查询需要在相关字段上设置geo_point类型。
忽略未映射
edit当设置为true时,ignore_unmapped选项将忽略未映射的字段,并且不会匹配此查询的任何文档。这在查询可能具有不同映射的多个索引时非常有用。当设置为false(默认值)时,如果字段未映射,查询将抛出异常。
地理形状查询
edit过滤使用 geo_shape 或
geo_point 类型索引的文档。
The geo_shape query uses the same index as
the geo_shape or geo_point mapping to find documents that have a shape that
is related to the query shape, using a specified
spatial relationship: either intersects,
contained, within or disjoint.
查询支持两种定义查询形状的方式,一种是通过提供完整的形状定义,另一种是通过引用预先在另一个索引中索引的形状名称。下面通过示例定义了这两种格式。
内联形状定义
edit类似于 geo_point 类型,geo_shape 查询使用
GeoJSON 来表示形状。
给定以下索引,其中位置作为geo_shape字段:
PUT /example
{
"mappings": {
"properties": {
"location": {
"type": "geo_shape"
}
}
}
}
POST /example/_doc?refresh
{
"name": "Wind & Wetter, Berlin, Germany",
"location": {
"type": "point",
"coordinates": [ 13.400544, 52.530286 ]
}
}
以下查询将使用Elasticsearch的envelope GeoJSON扩展来查找点:
GET /example/_search
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_shape": {
"location": {
"shape": {
"type": "envelope",
"coordinates": [ [ 13.0, 53.0 ], [ 14.0, 52.0 ] ]
},
"relation": "within"
}
}
}
}
}
}
上述查询同样可以在geo_point字段上进行查询。
PUT /example_points
{
"mappings": {
"properties": {
"location": {
"type": "geo_point"
}
}
}
}
PUT /example_points/_doc/1?refresh
{
"name": "Wind & Wetter, Berlin, Germany",
"location": [13.400544, 52.530286]
}
使用相同的查询,返回包含匹配的geo_point字段的文档。
GET /example_points/_search
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_shape": {
"location": {
"shape": {
"type": "envelope",
"coordinates": [ [ 13.0, 53.0 ], [ 14.0, 52.0 ] ]
},
"relation": "intersects"
}
}
}
}
}
}
{
"took" : 17,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "example_points",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"name": "Wind & Wetter, Berlin, Germany",
"location": [13.400544, 52.530286]
}
}
]
}
}
预索引形状
edit该查询还支持使用已在另一个索引中索引的形状。当你有一个预定义的形状列表,并且你想使用逻辑名称(例如新西兰)来引用该列表,而不是每次都提供坐标时,这特别有用。在这种情况下,只需提供:
-
id- 包含预索引形状的文档的ID。 -
index- 预索引形状所在的索引名称。默认为 shapes。 -
path- 指定为路径的字段,包含预索引形状。 默认为 shape。 -
routing- 如果需要,形状文档的路由。
以下是使用预索引形状的过滤器示例:
PUT /shapes
{
"mappings": {
"properties": {
"location": {
"type": "geo_shape"
}
}
}
}
PUT /shapes/_doc/deu
{
"location": {
"type": "envelope",
"coordinates" : [[13.0, 53.0], [14.0, 52.0]]
}
}
GET /example/_search
{
"query": {
"bool": {
"filter": {
"geo_shape": {
"location": {
"indexed_shape": {
"index": "shapes",
"id": "deu",
"path": "location"
}
}
}
}
}
}
}
空间关系
edit以下是搜索地理字段时可用的空间关系操作符的完整列表:
-
INTERSECTS- (默认)返回所有其geo_shape或geo_point字段与查询几何相交的文档。 -
DISJOINT- 返回所有其geo_shape或geo_point字段与查询几何没有任何共同点的文档。 -
WITHIN- 返回所有其geo_shape或geo_point字段在查询几何内的文档。不支持线几何。 -
CONTAINS- 返回所有其geo_shape或geo_point字段包含查询几何的文档。
忽略未映射
edit当设置为true时,ignore_unmapped选项将忽略未映射的字段,并且不会匹配此查询的任何文档。这在查询可能具有不同映射的多个索引时非常有用。当设置为false(默认值)时,如果字段未映射,查询将抛出异常。
注释
edit-
当数据以形状数组的形式索引在
geo_shape字段中时,这些数组被视为一个形状。因此,以下请求是等效的。
PUT /test/_doc/1
{
"location": [
{
"coordinates": [46.25,20.14],
"type": "point"
},
{
"coordinates": [47.49,19.04],
"type": "point"
}
]
}
PUT /test/_doc/1
{
"location":
{
"coordinates": [[46.25,20.14],[47.49,19.04]],
"type": "multipoint"
}
}
-
geo_shape查询假设geo_shape字段使用默认的orientation为RIGHT(逆时针)。请参阅 多边形方向。