Elasticsearch 关于GeoShape应用小结

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);

目前实现的功能,

  1. 根据地图上画出的范围获取范围内的点位搜索;
  2. 根据点搜索在地图上画过并保存过的范围;
  3. 在地图上画范围保存是验证是否被某个范围完全包含,前提是相通的图形,不同图形不支持,也就是说圈只能判断是否有圈包含它,多边形只能判断是有多边形包含它。

目前使用经验分享于此,由于ES版本较低使用较新版本的同学可根据该版本API玩。

上一篇:常用第三方接口,支付宝支付,微信支付,软著,IOS开发者账号


下一篇:java获得项目绝对路径