前言
ElasticSearch支持地理空间数据查询、搜索,提供geo_point
、geo_shape
两种地理数据类型。
geo_point
用于描述一个或多个地理坐标点,主要用于周边位置查询、边界内搜索点、聚合多个范围内的点等功能。
geo_shape
用于描述点线面等多种地理数据,使用GeoJson标准格式描述,可以对这些地理数据做相交、不相交、包含等等地理关系的判断与计算。
新增索引
PUT /my_locations
{"mappings": {"properties": {"name": {"type": "text"}}}
}
PUT后边紧跟的就是需要创建的索引名:my_locations
。mappings
中设置了一个属性name
,为text
类型。
更新geo类型的mappings
新增两个字段,location
字段类型为geo_point
,polygon
字段类型为geo_shape
。
PUT
后边紧跟索引名my_locations
,加_mapping
表示在操作mappings。
PUT /my_locations/_mapping
{"properties": {"name": {"type": "text"},"location": {"type": "geo_point"},"polygon": {"type": "geo_shape"}}
}
查询修改后的索引
GET my_locations/_mapping
{"my_locations":"mappings":"properties":"location":"type": "geo_point" }, "name":"type": "text" }, "polygon":"type": "geo_shape" } } } }
}
注意不要在请求体里的body
里填{}
,会报错。
新增geo数据
固有格式就是/索引名/_doc/id
,表示添加数据。geo_point
支持普通经纬度数组、WKT
、geohash
格式的地理数据。
三种类型的经纬度格式都是经度在前,纬度在后。
新增经纬度数组类型的地理坐标点数据:
POST /my_locations/_doc/1
{"name": "喜茶","location": [113.947539,22.530122]
}
新增WKT
类型的地理坐标点数据:
POST my_locations/_doc/2
{"name": "喜茶2","location": "POINT(113.947539 22.530122)"
}
新增geohash
类型的地理坐标点数据:
POST my_locations/_doc/3
{"name": "喜茶geohash","location": "ws100vqp6p"
}
新增另一个地点
POST my_locations/_doc/4
{"name": "平安银行","location": [113.945805,22.530055]
}
距离查询
传入一个坐标原点和相应的距离范围,来搜索范围内是否存在坐标点:
GET my_locations/_search
{"query": {"bool": {"must": {"match_all": {}},"filter": {"geo_distance": {"distance": "500m","location": [113.948769,22.530063]}}}}
}
其中距离单位参考:https://www.elastic.co/guide/en/elasticsearch/reference/current/api-conventions.html#distance-units
常见的公里为km
,米为m
,默认是米。
聚合查询
定义一个原点和一组距离范围桶,聚合评估每个文档值与原点的距离。
GET my_locations/_search?size=0&filter_path=aggregations
{"aggs": {"data_around_city": {"geo_distance": {"unit": "m","field": "location","origin": "113.94823,22.530143","ranges": [{"to": 100},{"from": 100,"to": 300},{"from": 600,"to": 1000},{"from": 1000}]}}}
}
地理多边形内的点
传入一个多边形来判断多边形范围内是否有坐标点,使用within
方法表示内部。
GET my_locations/_search
{"query": {"bool": {"must": {"match_all": {}},"filter": {"geo_shape": {"location": {"shape": {"type": "polygon","relation": "within","coordinates": [[[113.942373,22.531399],[113.955111,22.531432],[113.953261,22.524538],[113.940451,22.525991]]]}}}}}}
}
新增面数据
es支持的另一种地理类型字段为geo_shape
,包括点、线、多线、面、多面等常见地理类型数据。支持GeoJson
和WKT
两种标准的地理数据格式。
为第一个喜茶新增多边形的GeoJson
数据:
POST my_locations/_doc/1
{"name": "喜茶","location": [113.947539,22.530122],"polygon": {"type": "envelope","coordinates": [[113.947248,22.530295],[113.94776,22.529753]]}
}
为第二个喜茶新增WKT
数据
POST my_locations/_doc/2
{"name": "喜茶2","location": "POINT(113.947539 22.530122)","polygon": "POLYGON ((113.947305 22.530055, 113.947682 22.530047, 113.947718 22.529788, 113.947341 22.529842, 113.947305 22.530055)) "
}
通过点判断落面
判断传入的点落在是否被包含(contains
)在相应的多边形内:
GET my_locations/_search
{"query": {"bool": {"must": {"match_all": {}},"filter": {"geo_shape": {"polygon": {"shape": {"type": "point","coordinates": [113.947305,22.530055]},"relation": "contains"}}}}}
}
判断面相交
GET my_locations/_search
{"query": {"bool": {"must": {"match_all": {}},"filter": {"geo_shape": {"polygon": {"shape": {"type": "polygon","relation": "intersects","coordinates": [[[113.947522,22.530091],[113.948169,22.529966],[113.948187,22.529695],[113.94754,22.529707]]]}}}}}}
}
参考
- Elasticsearch:Geo Point 和 Geo Shape 查询解释
- Elasticsearch地理空间之geo_shape
- ES地理范围查询第一讲:Java操作地理位置信息(geo_point)
- Elasticsearch 之(53) Java API 基于geo_shape根据坐标查找 坐标落在店铺范围的店铺
- Geo queries
- 百度地图坐标拾取系统
- 在线经纬度转geohash
- # 百度地图 geohash 可视化工具