ElasticSearch Java API GEO操作(REST命令版)
/ 6 min read
Table of Contents
前言
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.94580499999999, 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 ] ] ] } } } } } }}