elasticsearch geo DSL 和API对比学习-矩形多边形距离距离排序距离分段聚合geo

mac2026-05-11  1

直接上代码,包括多种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)