Elasticsearch 关于GeoShape应用小结
特别注意:ES只有一种坐标系WGS84
ES GeoShape 一共提供了4中关系
- INTERSECTS 相交的
- DISJOINT 不相交的
- WITHIN 在。。内
- CONTAINS 包含
几种关系比较好理解
分类
· 点
· 线
· 圈
· 多边形
点
对于点类型的储存和查询相对简单不多赘述,可以使用范围查覆盖的点,也可以用点查在某个线、圈或多边形上
上代码:
Rest API
GET businessAreaShape/_search
{
"query": {
"bool": {
"should": [
{
"geo_shape": {
"s_location_circle": {
"shape": {
"type": "point",
"coordinates": [
116.311434,
39.909228
]
},
"relation": "contains"
},
"ignore_unmapped": false,
"boost": 1
}
},
{
"geo_shape": {
"s_location_polygon": {
"shape": {
"type": "point",
"coordinates": [
116.311434,
39.909228
]
},
"relation": "contains"
},
"ignore_unmapped": false,
"boost": 1
}
}
],
"adjust_pure_negative": true,
"boost": 1
}
},
"sort": [
{
"create_time": {
"order": "asc"
}
}
]
}
JAVA Hight Level API
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
PointBuilder pointBuilder = new PointBuilder(lng, lat);
GeoShapeQueryBuilder shapeQueryCirleBuilder = QueryBuilders.geoShapeQuery(ShopAnalyzeAnchorMapping.SHOP_POINT_FIELD_S_LOCATION_CIRCLE, pointBuilder).relation(ShapeRelation.CONTAINS);
boolQueryBuilder.should(shapeQueryCirleBuilder);
GeoShapeQueryBuilder shapeQueryPolygonBuilder = QueryBuilders.geoShapeQuery(ShopAnalyzeAnchorMapping.SHOP_POINT_FIELD_S_LOCATION_POLYGON, pointBuilder).relation(ShapeRelation.CONTAINS);
boolQueryBuilder.should(shapeQueryPolygonBuilder);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(boolQueryBuilder);
sourceBuilder.sort(ShopAnalyzeAnchorMapping.SHOP_POINT_FIELD_CREATE_TIME, SortOrder.ASC);
//只获取ID就足够了后续所有详细信息从数据库获取
sourceBuilder.fetchSource("k_anchor_id","");
SearchRequest searchRequest = new SearchRequest(ANCHOR_SHAPE);
searchRequest.source(sourceBuilder);
SearchResponse search = getRestHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
线
暂未涉及 值得注意的是计算距离需要指定方式,ES只有两种方式一是平面二是球型。
圈(CIRCLE)
圈主要有一个中心坐标和半径组成,可以根据半径排序,可根据关系查询。
上代码:
- mapping
"s_location_circle" : {
"type" : "geo_shape",
"strategy" : "recursive"
}
我是用的是ES 5.x版本高版本"strategy" : "recursive"将被弃用
- 插入
直接上JAVA,重点就是这个JSON
"s_location_circle":{
"coordinates":[116.55251722897378,39.98890616238562],
"type":"circle",
"radius":"600m"
}
- 查询
Rest API
GET businessAreaShape/_search
{
"query": {
"geo_shape": {
"s_location_circle": {
"shape": {
"type": "circle",
"radius": "600.0m",
"coordinates": [
116.55251722897378,
39.98890616238562
]
},
"relation": "contains"
},
"ignore_unmapped": false,
"boost": 1
}
}
}
JAVA Hight Level API
CircleBuilder circleBuilder = new CircleBuilder();
circleBuilder.center(lng, lat);
DistanceUnit.Distance distance = new DistanceUnit.Distance(range, DistanceUnit.METERS);
circleBuilder.radius(distance);
GeoShapeQueryBuilder shapeQueryBuilder = QueryBuilders.geoShapeQuery(ShopAnalyzeAnchorMapping.SHOP_POINT_FIELD_S_LOCATION_CIRCLE, circleBuilder).relation(ShapeRelation.CONTAINS);
多边形(POLYGON)
- 插入
"s_location_polygon":{"coordinates":[[[116.47311930720184,39.97367261625567],[116.46083817432645,39.97588286009428],[116.45497672470651,39.971177091927984],[116.46400149615897,39.96704145151183],[116.4741427350599,39.96811103788185],[116.47311930720184,39.97367261625567]]],"type":"polygon"}
- 查询
Rest API
GET businessAreaShape/_search
{
"query": {
"geo_shape": {
"s_location_polygon": {
"shape": {
"type": "polygon",
"orientation": "right",
"coordinates": [
[
[
116.47311930720184,
39.97367261625567
],
[
116.46083817432645,
39.97588286009428
],
[
116.45497672470651,
39.971177091927984
],
[
116.46400149615897,
39.96704145151183
],
[
116.4741427350599,
39.96811103788185
],
[
116.47311930720184,
39.97367261625567
]
]
]
},
"relation": "contains"
},
"ignore_unmapped": false,
"boost": 1
}
}
}
JAVA Hight Level API
//多边形
CoordinatesBuilder coordinatesBuilder = new CoordinatesBuilder();
List<Location> boundaryPoints = locationForm.getBoundaryPoints();
for (Location location : boundaryPoints) {
coordinatesBuilder.coordinate(location.getLng().doubleValue(), location.getLat().doubleValue());
}
PolygonBuilder polygonBuilder = new PolygonBuilder(coordinatesBuilder);
GeoShapeQueryBuilder shapeQueryBuilder = QueryBuilders.geoShapeQuery(ShopAnalyzeAnchorMapping.SHOP_POINT_FIELD_S_LOCATION_POLYGON, polygonBuilder).relation(ShapeRelation.CONTAINS);
目前实现的功能,
- 根据地图上画出的范围获取范围内的点位搜索;
- 根据点搜索在地图上画过并保存过的范围;
- 在地图上画范围保存是验证是否被某个范围完全包含,前提是相通的图形,不同图形不支持,也就是说圈只能判断是否有圈包含它,多边形只能判断是有多边形包含它。
目前使用经验分享于此,由于ES版本较低使用较新版本的同学可根据该版本API玩。