Elasticsearch 基于地理位置的搜索查询

         ES为用户提供了基于地理位置的搜索功能。它主要支持两种类型的地理查询:一种是地理点(geo_point),即经纬度查询,另一种是地理形状查询(geo_shape),即支持点,线,圆形和多边形等查询。

        从实用性来说,地理点(即geo_point)数据类型的使用更多一些,对于geo_point字段类型的查询方式有三种,分别为geo_distance查询(圆形区域查询),geo_bounding_box查询(矩形区域查询)和geo_polygon查询(多边形区域查询)。

1.geo_distance圆形区域查询

geo_distance需要指定一个坐标点,在指定该点距离的范围后,ES可查询到以该点为中心,距离为半径的圆形区域的数据。

1.1 查询的DSL

GET index_school/_search
{
  "_source": [                        // 只返回部分字段
    "name",
    "latitude",
    "longitude",
    "devideNo",
    "time"
    ], 
  "query": {
    "geo_distance":{
      "distance": "5km",             // 距离范围(半径)为5km
      "location":{                   //中心点经纬度
        "lat": "18.231472",
        "lon": "109.502083"
      }
    }
  }
}

1.2 java实现

SearchRequest request = new SearchRequest(tableName);
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
boolQuery.filter(QueryBuilders.geoDistanceQuery("location")                //指定索引字段
.distance(inputDTO.getDistance())                                          //距离中心点范围(半径)
.point(18.231472,109.502083));                                             //中心点
request.source().query(boolQuery).size(10000).trackTotalHits(true);
SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);

2.geo_bounding_box矩形区域查询

geo_bounding_box查询提供的是矩形内的搜索,需要提供左上角和右下角的顶点坐标。

2.1 查询的DSL

GET index_school/_search
{
  "_source": [                        
    "name",
    "latitude",
    "longitude",
    "devideNo",
    "time"
    ], 
  "query": {
    "geo_bounding_box":{
      "location":{   
        "top_left":{                          //设置左上角顶点坐标
           "lat": "18.431472",
           "lon": "109.502083"
        },
        "bottom_right":{                      //设置右下角顶点坐标
           "lat": "18.231472",
           "lon": "109.202083"
        }
      }
    }
  }
}

2.2 java实现

SearchRequest request = new SearchRequest(tableName);
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
boolQuery.filter(QueryBuilders.geoBoundingBoxQuery("location")             //指定索引字段
.setCorners(inputDTO.getYMax(), inputDTO.getXMin(),                        //构造矩形
                    inputDTO.getYMin(), inputDTO.getXMax()));
request.source().query(boolQuery).size(10000).trackTotalHits(true);
SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);

3.geo_polygon多边形区域查询

geo_polygon比geo_bounding_box提供的地理范围功能更加灵活,它支持灵活多变的多边形内数据查询,使用该查询需要提供多边形所有顶点的坐标。

3.1 查询的DSL

GET index_school/_search
{
  "query": {
    "geo_polygon":{
      "location":{   
        "points":[
          {
           "lat": "20.219935",
           "lon":  "109.700590"
          },
          {
           "lat": "20.118963",
           "lon":  "109.865898"
          },
          {
           "lat": "20.148887",
           "lon":  "110.1842848"
          },
          {
           "lat": "20.355594",
           "lon":  "111.097193"
          },
          {
           "lat": "20.295775",
           "lon":  "111.791273"
          }
        ]
      }
    }
  }
}

3.2 java实现

String AREA_POINTS =
            "109.70059057645672,20.219935185668575," +
            "109.86589885747735,20.11896383759739," +
            "110.18428481460053,20.148887724639927," +
            "111.09719394252089,20.355594505110506," +
            "111.79127352756524,20.295775199436054," +
            "111.44955008175484,19.864326194135216," +
            "110.65937420024187,18.52295323361459," +
            "109.76478316052932,17.989118493905913," +
            "109.57997296428381,17.95228226006386";
SearchRequest request = new SearchRequest(tableName);
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
List<GeoPoint> points = new ArrayList<>();
String[] strings = AREA_POINTS.split(",");
for (int i = 0; i < strings.length; i = i + 2) {
    points.add(new GeoPoint(Double.valueOf(strings[i + 1]), Double.valueOf(strings[i])));
}
boolQuery.filter(QueryBuilders.geoPolygonQuery("location",points));
request.source().query(boolQuery).size(10000).trackTotalHits(true);
SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

潇潇雨歇_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值