Browse Source

change 区域搜索

18339543638 4 năm trước cách đây
mục cha
commit
5c0cd80f88

+ 4 - 14
jetlinks-components/elasticsearch-component/src/main/java/org/jetlinks/community/elastic/search/geo/EsGeoFilter.java

@@ -2,6 +2,7 @@ package org.jetlinks.community.elastic.search.geo;
 
 import lombok.Data;
 import org.elasticsearch.common.geo.GeoPoint;
+import org.jetlinks.core.metadata.types.GeoShape;
 
 import java.util.ArrayList;
 import java.util.LinkedList;
@@ -17,21 +18,10 @@ import java.util.List;
 @Data
 public class EsGeoFilter {
     private String type;
-    private List<List<Double>> pointsStr;
+//    private List<List<Double>> pointsStr;
     private String fieldName;
 
-    private List<GeoPoint> points;
+    private GeoShape shape;
+//    private List<GeoPoint> points;
 
-    public void setPointsStr(List<List<Double>> pointsStr) {
-        this.pointsStr = pointsStr;
-        if(pointsStr!=null&&pointsStr.size()!=0){
-            List<GeoPoint> geoPoints = new LinkedList<>();
-            for (List<Double> pointStr : pointsStr) {
-                GeoPoint point = new GeoPoint();
-                point.reset(pointStr.get(1),pointStr.get(0));
-                geoPoints.add(point);
-            }
-            this.points=geoPoints;
-        }
-    }
 }

+ 58 - 20
jetlinks-components/elasticsearch-component/src/main/java/org/jetlinks/community/elastic/search/utils/QueryParamTranslator.java

@@ -2,26 +2,35 @@ package org.jetlinks.community.elastic.search.utils;
 
 import lombok.NonNull;
 import lombok.extern.slf4j.Slf4j;
+import org.elasticsearch.common.geo.ShapeRelation;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentType;
+import org.elasticsearch.common.xcontent.json.JsonXContent;
+import org.elasticsearch.common.xcontent.json.JsonXContentParser;
+import org.elasticsearch.geometry.LinearRing;
+import org.elasticsearch.geometry.MultiPolygon;
+import org.elasticsearch.geometry.Polygon;
 import org.elasticsearch.index.query.*;
 import org.elasticsearch.search.builder.SearchSourceBuilder;
 import org.elasticsearch.search.sort.SortOrder;
 import org.hswebframework.ezorm.core.param.QueryParam;
 import org.hswebframework.ezorm.core.param.Sort;
 import org.hswebframework.ezorm.core.param.Term;
+import org.hswebframework.web.exception.BusinessException;
 import org.jetlinks.community.elastic.search.geo.EsGeoFilter;
 import org.jetlinks.community.elastic.search.index.ElasticSearchIndexMetadata;
 import org.jetlinks.community.elastic.search.parser.DefaultLinkTypeParser;
 import org.jetlinks.core.metadata.DataType;
 import org.jetlinks.core.metadata.PropertyMetadata;
+import org.jetlinks.core.metadata.types.GeoShape;
 import org.springframework.util.StringUtils;
 
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.io.IOException;
+import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.function.BiConsumer;
 import java.util.function.Consumer;
+import java.util.stream.Collectors;
 
 /**
  * @author zhouhao
@@ -77,20 +86,6 @@ public class QueryParamTranslator {
 
 
     public static SearchSourceBuilder convertSearchSourceBuilder(QueryParam queryParam, ElasticSearchIndexMetadata metadata) {
-//        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
-//        if (queryParam.isPaging()) {
-//            sourceBuilder.from(queryParam.getPageIndex() * queryParam.getPageSize());
-//            sourceBuilder.size(queryParam.getPageSize());
-//        }
-//        for (Sort sort : queryParam.getSorts()) {
-//            if (!StringUtils.isEmpty(sort.getName())) {
-//                sourceBuilder.sort(sort.getName(), SortOrder.fromString(sort.getOrder()));
-//            }
-//        }
-//
-////        GeoPolygonQueryBuilder geoPolygonQueryBuilder = QueryBuilders.geoPolygonQuery();
-////        sourceBuilder.postFilter(geoPolygonQueryBuilder);
-//        return sourceBuilder.query(createQueryBuilder(queryParam,metadata));
         return convertSearchSourceBuilder(queryParam,null,metadata);
     }
 
@@ -107,10 +102,53 @@ public class QueryParamTranslator {
         }
        BoolQueryBuilder queryBuilder = (BoolQueryBuilder) createQueryBuilder(queryParam, metadata);
         if(filter!=null){
-            GeoPolygonQueryBuilder geoPolygonQueryBuilder = QueryBuilders.geoPolygonQuery(filter.getFieldName(),filter.getPoints());
-            queryBuilder.filter(geoPolygonQueryBuilder);
+            try {
+                GeoShape shape = filter.getShape();
+                GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery(filter.getFieldName(), compulsionCreateMultiPolygon(shape.getCoordinates()))
+                    .relation(ShapeRelation.WITHIN);
+                queryBuilder.filter(geoShapeQueryBuilder);
+            }catch (Exception e){
+                log.error("地图参数有误",e);
+                throw new BusinessException("地图参数有误");
+            }
+
         }
         return sourceBuilder.query(queryBuilder);
     }
 
+    private static MultiPolygon compulsionCreateMultiPolygon(List<Object>  coordinates){
+        ArrayList<Polygon> polygons = new ArrayList<>();
+        for (Object coordinate : coordinates) {
+            List<List<List<Double>>> polygonCoordinates= (List<List<List<Double>>>) coordinate;
+            polygons.add(createPolygon(polygonCoordinates));
+        }
+        return  new MultiPolygon(polygons);
+    }
+
+    private static MultiPolygon createMultiPolygon(List<List<List<List<Double>>>>  coordinates){
+        return  new MultiPolygon(coordinates.stream().map(QueryParamTranslator::createPolygon)
+            .collect(Collectors.toList()));
+    }
+
+
+    private static Polygon createPolygon(List<List<List<Double>>> polygonCoordinates){
+        return new Polygon(createLinearRing(polygonCoordinates.get(0)));
+    }
+
+    /**
+     * 根据坐标点获取LineRing(线环)
+     * @param coordinates
+     * @return
+     */
+    private static LinearRing createLinearRing(List<List<Double>>  coordinates){
+        double[] x = new double[coordinates.size()];
+        double[] y = new double[coordinates.size()];
+        for (int i = 0; i < coordinates.size(); i++) {
+            List<Double> coordinate = coordinates.get(i);
+            x[i]=coordinate.get(0);
+            y[i]=coordinate.get(1);
+        }
+        return new LinearRing(x,y);
+    }
+
 }

+ 2 - 2
jetlinks-core/src/main/java/org/jetlinks/core/metadata/types/GeoShape.java

@@ -24,7 +24,7 @@ public class GeoShape implements Serializable {
     private List<Object> coordinates;
 
     public enum Type {
-        Point,//点
+        point,//点
         MultiPoint, //多个点
         LineString,//线
         MultiLineString,//多条线
@@ -81,7 +81,7 @@ public class GeoShape implements Serializable {
 
     public static GeoShape fromPoint(GeoPoint point) {
         GeoShape shape = new GeoShape();
-        shape.type = Type.Point;
+        shape.type = Type.point;
         shape.coordinates = new ArrayList<>(Arrays.asList(point.getLon(), point.getLat()));
         return shape;
     }

+ 1 - 1
jetlinks-core/src/test/java/org/jetlinks/core/metadata/types/GeoShapeTypeTest.java

@@ -18,7 +18,7 @@ public class GeoShapeTypeTest {
         map.put("coordinates", Arrays.asList(56.123, 121.123));
         GeoShape shape = type.convert(map);
 
-        assertEquals(shape.getType(), GeoShape.Type.Point);
+        assertEquals(shape.getType(), GeoShape.Type.point);
         assertArrayEquals(shape.getCoordinates().toArray(), new Object[]{56.123, 121.123});
 
     }

+ 3 - 1
jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/configuration/GeoIndexInitialize.java

@@ -3,6 +3,7 @@ package org.jetlinks.community.device.configuration;
 import org.jetlinks.community.device.constant.GeoConstant;
 import org.jetlinks.community.elastic.search.index.DefaultElasticSearchIndexMetadata;
 import org.jetlinks.community.elastic.search.index.ElasticSearchIndexManager;
+import org.jetlinks.core.metadata.types.GeoShapeType;
 import org.jetlinks.core.metadata.types.GeoType;
 import org.jetlinks.core.metadata.types.StringType;
 import org.springframework.core.annotation.Order;
@@ -28,7 +29,8 @@ public class GeoIndexInitialize {
             .addProperty(GeoConstant.ES_DEVICE_NAME, new StringType())
             .addProperty(GeoConstant.ES_DEVICE_PRODUCT_ID,new StringType())
             .addProperty(GeoConstant.ES_DEVICE_PRODUCT_NAME, new StringType())
-            .addProperty(GeoConstant.ES_DEVICE_GEO_POINT, new GeoType()))
+            .addProperty(GeoConstant.ES_DEVICE_GEO_POINT, new GeoType())
+            .addProperty(GeoConstant.ES_DEVICE_GEO_JSON,new GeoShapeType()))
             .subscribe();
     }
 

+ 1 - 0
jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/constant/GeoConstant.java

@@ -13,4 +13,5 @@ public class GeoConstant {
     public static final String ES_DEVICE_PRODUCT_ID="productId";
     public static final String ES_DEVICE_PRODUCT_NAME="productName";
     public static final String ES_DEVICE_GEO_POINT="location";
+    public static final String ES_DEVICE_GEO_JSON="geoJson";
 }

+ 13 - 0
jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/dto/DeviceGeoDto.java

@@ -3,6 +3,10 @@ package org.jetlinks.community.device.dto;
 import lombok.Data;
 import org.jetlinks.community.device.entity.DeviceInstanceEntity;
 import org.jetlinks.core.metadata.types.GeoPoint;
+import org.jetlinks.core.metadata.types.GeoShape;
+
+import java.util.Arrays;
+
 /**
  * @author lifang
  * @version 1.0.0
@@ -21,6 +25,7 @@ public class DeviceGeoDto {
 
     private GeoPoint location;
 
+    private GeoShape geoJson;
     public static DeviceGeoDto of(DeviceInstanceEntity instanceEntity){
         DeviceGeoDto deviceGeo = new DeviceGeoDto();
         deviceGeo.setId(instanceEntity.getId());
@@ -30,4 +35,12 @@ public class DeviceGeoDto {
         deviceGeo.setLocation(instanceEntity.getLocation());
         return deviceGeo;
     }
+
+    public void setLocation(GeoPoint location) {
+        this.location = location;
+        GeoShape geoJson = new GeoShape();
+        geoJson.setType(GeoShape.Type.point);
+        geoJson.setCoordinates(Arrays.asList(location.getLon(),location.getLat()));
+        this.geoJson=geoJson;
+    }
 }

+ 1 - 1
jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/entity/DeviceInstanceEntity.java

@@ -212,7 +212,7 @@ public class DeviceInstanceEntity extends GenericEntity<String> implements Recor
             properties.put("objectId",this.getId());
 
             GeoJson.Feature feature = GeoJson.newFeature();
-            feature.setType("Point");
+            feature.setType("point");
             feature.setGeometry(GeoShape.of(this.getLocation()));
             feature.setProperties(properties);
 

+ 12 - 16
jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/DeviceInstanceController.java

@@ -871,34 +871,30 @@ public class DeviceInstanceController implements
      */
     @PostMapping("/geo/_query/{hasGeo}")
     public Mono<?> queryPageGeo(@RequestBody GeoRequestParam param, @PathVariable("hasGeo") boolean hasGeo) {
+        Mono<PagerResult<DeviceInstanceEntity>> resultMono = null;
         if(!hasGeo){
-//            /**
-//             * 没有查询区域
-//             */
+           /**
+            * 没有查询区域
+            */
             param.getQuery().setIncludes(CollectionUtil.newHashSet("id","name","location","productId","productName"));
             Term term = new Term();
             term.setColumn("location");
             term.setType(Term.Type.and);
             term.setTermType("notnull");
             param.getQuery().addTerm(term);
-            return instanceService.queryPager(param.getQuery())
-                .doOnNext(result->result.getData().forEach(DeviceInstanceEntity::toGeoJson)
-                ).map(result->
-                    Tuple.of(result,GeoJson.of(result.getData().stream().map(DeviceInstanceEntity::getGeoFeature)
-                        .filter(Objects::nonNull).collect(Collectors.toList()), "FeatureCollection"))
-                );
+            resultMono= instanceService.queryPager(param.getQuery());
         }else {
             /**
              * 查询区域
              * es查询
              */
-            return elasticSearchService
-                .queryPager(GeoIndexProvider.GEO,param.getQuery(),param.getFilter(),DeviceInstanceEntity.class)
-                .doOnNext(result->result.getData().forEach(DeviceInstanceEntity::toGeoJson))
-                .map(result->
-                    Tuple.of(result,GeoJson.of(result.getData().stream().map(DeviceInstanceEntity::getGeoFeature)
-                        .filter(Objects::nonNull).collect(Collectors.toList()), "FeatureCollection"))
-                );
+            resultMono= elasticSearchService
+                .queryPager(GeoIndexProvider.GEO,param.getQuery(),param.getFilter(),DeviceInstanceEntity.class);
         }
+        return resultMono .doOnNext(result->result.getData().forEach(DeviceInstanceEntity::toGeoJson))
+            .map(result->
+                Tuple.of(result,GeoJson.of(result.getData().stream().map(DeviceInstanceEntity::getGeoFeature)
+                    .filter(Objects::nonNull).collect(Collectors.toList()), "FeatureCollection"))
+            );
     }
 }

+ 5 - 2
jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/GeoController.java

@@ -7,6 +7,7 @@ import io.vavr.Tuple;
 import lombok.AllArgsConstructor;
 import org.hswebframework.web.api.crud.entity.QueryOperation;
 import org.hswebframework.web.api.crud.entity.QueryParamEntity;
+import org.hswebframework.web.api.crud.entity.TreeSupportEntity;
 import org.hswebframework.web.authorization.annotation.Authorize;
 import org.hswebframework.web.authorization.annotation.QueryAction;
 import org.hswebframework.web.authorization.annotation.Resource;
@@ -43,8 +44,10 @@ public class GeoController  implements ReactiveTreeServiceQueryController<GeoReg
     @QueryAction
     @QueryOperation(summary = "使用GET动态查询并返回树形结构以及geo集合信息")
     public Mono<?> findAllTreeTp2(@Parameter(hidden = true) QueryParamEntity paramEntity) {
-        return this.findAllChildrenTree(paramEntity)
-            .map(result->  Tuple.of(new HashSet<GeoRegionEntity>(result), GeoJson.of(result.stream().map(GeoRegionEntity::getRegion)
+
+        return this.findAllChildren(paramEntity)
+            .collectList()
+            .map(result->  Tuple.of(TreeSupportEntity.list2tree(result,GeoRegionEntity::setChildren), GeoJson.of(result.stream().map(GeoRegionEntity::getRegion)
                 .filter(Objects::nonNull).collect(Collectors.toList()), "FeatureCollection")));
     }