elasticsearch geo DSL 和API对比学习-矩形/多边形/距离/距离排序/距离分段聚合/geo_shape内含-相交-相离

直接上代码,包括多种geo相关查询===>>>矩形/多边形/距离/距离排序/距离分段聚合/geo_shape内含-相交-相离
@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class VehicleEntpApplicationTests {
    static {
        System.setProperty("es.set.netty.runtime.available.processors", "false");
    }

    @Autowired
    ElasticsearchTemplate elasticsearchTemplate;

    //"************************矩形************************"
    /* 
    GET /entp/entp_search
    {
        "post_filter": {
        "geo_bounding_box": {
            "geo": {
                "top_left": {
                    "lat": 31.73,
                            "lon": 104.1
                },
                "bottom_right": {
                    "lat": 10.01,
                            "lon": 141.12
                }
            }
        }
    }
    }
     */
    @Test
    public void boundingBoxQuery() throws Exception {
        GeoBoundingBoxQueryBuilder filterBuilder = QueryBuilders.geoBoundingBoxQuery("geo")
                .setCorners(new GeoPoint(31.73, 104.1), new GeoPoint(10.01, 141.12));
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withIndices("entp")
                .withTypes("entp")
                .withFilter(filterBuilder)
                .build();
        System.out.println(filterBuilder.toString());
        List<EntpResourceVO> vos = elasticsearchTemplate.queryForList(searchQuery, EntpResourceVO.class);
    }
    //"************************多边形************************"
    /*{
   "post_filter": {
      "geo_polygon": {
         "geo": {
            "points": [{
               "lat": 22,
               "lon": 88
            }, {
               "lat": 11,
               "lon": 111
            }, {
               "lat": 33,
               "lon": 133
            }]
         }
      }
   }
}*/

    @Test
    public void polygonQuery() throws Exception {
        List<GeoPoint> geoPoints = new ArrayList<>();
        geoPoints.add(new GeoPoint(11, 111));
        geoPoints.add(new GeoPoint(22, 88));
        geoPoints.add(new GeoPoint(33, 133));
        GeoPolygonQueryBuilder filterBuilder = QueryBuilders.geoPolygonQuery("geo", geoPoints);
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withIndices("entp")
                .withTypes("entp")
                .withFilter(filterBuilder)
                .build();
        System.out.println(filterBuilder.toString());
        List<EntpResourceVO> vos = elasticsearchTemplate.queryForList(searchQuery, EntpResourceVO.class);
    }

    //"************************距离排序************************"
    /*GET /entp/_search
{
   "from": 0,
   "size": 10,
   "query": {
      "match_phrase_prefix": {
         "entpAddr.chinese": {
            "query": "云南",
            "boost": 1.0
         }
      }
   },
   "sort": [{
      "_geo_distance": {
         "geo": [{
            "lat": 25.0,
            "lon": 102.0
         }],
         "unit": "km",
         "distance_type": "plane",
         "order": "asc"
      }
   }, {
      "_score": {
         "order": "desc"
      }
   }]
}*/
    @Test
    public void geoDistanceSortQuery() throws Exception {
        QueryBuilder query = QueryBuilders.matchPhrasePrefixQuery("entpAddr.chinese", "云南");
        GeoDistanceSortBuilder sortBuilder = SortBuilders
                .geoDistanceSort("geo", 25, 110)
                .unit(DistanceUnit.KILOMETERS)
                .order(SortOrder.ASC)
                .geoDistance(GeoDistance.PLANE);
        //elasticsearchTemplate的API不便获得到距离,需要用原生的transportClient
        SearchRequestBuilder requestBuilder = (elasticsearchTemplate.getClient())
                .prepareSearch("entp")
                .setTypes("entp")
                .setQuery(query)
                .setFrom(0)
                .setSize(10)
                .addSort(sortBuilder).addSort("_score", SortOrder.DESC);//先相关度再距离二级排序
        System.out.println(requestBuilder.toString());
        Arrays.stream(requestBuilder.get().getHits().getHits()).forEach(searchHit -> {
            BigDecimal bigDecimal = new BigDecimal((double) searchHit.getSortValues()[0]);
            double distance = bigDecimal.setScale(1, BigDecimal.ROUND_HALF_DOWN).doubleValue();
        });

    }

    //"************************距离查询************************"
    /*GET / entp / _search 
{
   "post_filter": {
      "geo_distance": {
         "distance": "1000km",
         "geo": {
            "lat": 30,
            "lon": 110
         }
      }
   }
}*/
    @Test
    public void geoDistanceQuery() throws Exception {
        GeoDistanceQueryBuilder filterBuilder = QueryBuilders.geoDistanceQuery("geo")
                .distance(1000, DistanceUnit.KILOMETERS)
                .point(30, 110);
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withIndices("entp")
                .withTypes("entp")
                .withFilter(filterBuilder)
                .build();
        System.out.println(filterBuilder.toString());
        List<EntpResourceVO> vos = elasticsearchTemplate.queryForList(searchQuery, EntpResourceVO.class);

    }
    //"************************分段聚合************************"
    /*
GET /entp/_search
{
  "size": 0,
  "aggs": {
    "groupCount": {
      "geo_distance": {
        "field": "geo",   
        "origin": {            //源坐标    
          "lat": 30,
          "lon": 110
        },
        "ranges": [                  //分段
          {"to" : 300},
          {
            "from": 300,
            "to": 600
          },
          {"from": 600}
        ],
        "unit": "km",               
        "distance_type": "arc"    //平面or球面  
      }
    }
  }
}*/

    @Test
    public void geoAggExample() throws Exception {

        GeoDistanceAggregationBuilder agg = AggregationBuilders.geoDistance("groupCount", new GeoPoint(30, 110))
                .field("geo")
                .addUnboundedTo("300KM以下", 300)
                .addRange("300-600KM", 300, 600)
                .addUnboundedFrom("600KM以上", 600)
                .distanceType(GeoDistance.ARC)
                .unit(DistanceUnit.KILOMETERS);
        SearchRequestBuilder requestBuilder = (elasticsearchTemplate.getClient())
                .prepareSearch("entp")
                .setTypes("entp")
                .addAggregation(agg)
                .setSize(0);
        System.out.println(requestBuilder.toString());
        InternalGeoDistance internalGeoDistance = requestBuilder.get().getAggregations().get("groupCount");
        List buckets = internalGeoDistance.getBuckets();
        buckets.forEach(o -> {
            long docCount = ((InternalRange.Bucket) o).getDocCount();
        });
    }

    //"************************geo_shape内含-相交-相离************************"
    /**/
    @Test
    public void geoShapeQuery() throws Exception {
        // 1.查询针对的不是普通的字段,而是一种特殊的图形数据,是多个geo_point组成的,
        // 2. 用该API可以计算点线面形状的输入与ES内的geo_shape类型的内含-相交-相离关系。
        // ShapeRelation.WITHIN内含 ShapeRelation.INTERSECTS相交 ShapeRelation.DISJOINT相离
        // 3.需要加入两个依赖
        /*.
        <dependency>
            <groupId>org.locationtech.jts</groupId>
            <artifactId>jts-core</artifactId>
            <version>1.16.1</version>
        </dependency>

        <dependency>
            <groupId>org.locationtech.spatial4j</groupId>
            <artifactId>spatial4j</artifactId>
            <version>0.7</version>
        </dependency>
        */
        //4.数据准备
        /*PUT /example
{
    "mappings": {
        "example": {
            "properties": {
                "myGeoShape": {
                    "type": "geo_shape"                    
                }
            }
        }
    }
}

POST /example/example
{
    "myGeoShape" : {
        "type" : "polygon",
        "coordinates" : [
            [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ]
        ]
    }
}*/
        //5.需求举例
        //点面,如电子围栏,机车(点输入)闯入电子围栏触发报警
        //ShapeBuilder pointBuilder = new PointBuilder(33, 111); 
        //线面,新修公路(线输入)线路计划合理性计算,尽量与较多的村庄相交或内含
        //ShapeBuilder pointBuilder = new LineStringBuilder(new CoordinatesBuilder().coordinate(11,22).coordinate(33,44));// 点面位置关系
        //面面,如汶川多个村庄(在ES中表现为多个坐标组成的多边形),地震震中(面输入)(x,y) r=100Km,计算波及的村庄
        ShapeBuilder circleBuilder = new CircleBuilder().center(100.0, 0.0).radius(100, DistanceUnit.KILOMETERS);
        GeoShapeQueryBuilder filterBuilder = QueryBuilders.geoShapeQuery("myGeoShape", circleBuilder).relation(ShapeRelation.WITHIN);
        SearchRequestBuilder requestBuilder = (elasticsearchTemplate.getClient())
                .prepareSearch("example")
                .setTypes("example")
                .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
                .setQuery(filterBuilder)
                .setFrom(0)
                .setSize(10);
        Arrays.stream(requestBuilder.get().getHits().getHits()).forEach(searchHit -> {
            Map<String, Object> source = searchHit.getSourceAsMap();
            System.out.println(source);
        });
    }
}

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值