ES为用户提供了基于地理位置的搜索功能。它主要支持两种类型的地理查询:一种是地理点(geo_point),即经纬度查询,另一种是地理形状查询(geo_shape),即支持点,线,圆形和多边形等查询。
从实用性来说,地理点(即geo_point)数据类型的使用更多一些,对于geo_point字段类型的查询方式有三种,分别为geo_distance查询(圆形区域查询),geo_bounding_box查询(矩形区域查询)和geo_polygon查询(多边形区域查询)。
geo_distance需要指定一个坐标点,在指定该点距离的范围后,ES可查询到以该点为中心,距离为半径的圆形区域的数据。
- GET index_school/_search
- {
- "_source": [ // 只返回部分字段
- "name",
- "latitude",
- "longitude",
- "devideNo",
- "time"
- ],
- "query": {
- "geo_distance":{
- "distance": "5km", // 距离范围(半径)为5km
- "location":{ //中心点经纬度
- "lat": "18.231472",
- "lon": "109.502083"
- }
- }
- }
- }
- 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);
geo_bounding_box查询提供的是矩形内的搜索,需要提供左上角和右下角的顶点坐标。
- 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"
- }
- }
- }
- }
- }
- 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);
geo_polygon比geo_bounding_box提供的地理范围功能更加灵活,它支持灵活多变的多边形内数据查询,使用该查询需要提供多边形所有顶点的坐标。
- 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"
- }
- ]
- }
- }
- }
- }
- 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
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);