elasticsearch 6.8ベースの地理的位置情報クエリー

24195 ワード

elasticsearch 6.8ベースの地理的位置情報クエリー


この文章は主に以下の構成がある.
  • esに基づいて類似の近隣の友人クエリー
  • を完了
  • esに基づいて、ある点のような面内または交差クエリ
  • を完了する.

    近所の友達の検索に似ています


    多くの人は関連する符号化ドキュメントしか必要としない可能性があります.また、ネット上にはcurlコマンドの操作がたくさんあるので、ここではプロジェクトの例を通じて近くの友人のクエリーを直接行うことができます.
  • mappingドキュメントの構築

    {
      "point": {
        "_all": {
          "enabled": false
        },
        "properties": {
          "id": {
            "type": "keyword"
          },
          "type": {
            "type": "keyword"
          },
          "location": {
            "type": "geo_point"
          }
        }
      }
    }
    
  • ついでjavaBean
    @Mapping(mappingPath = "/json/poi-mapping.json")
    @Document(
        indexName = "poi",
        type = "point",
        shards = 5,
        replicas = 0,
        refreshInterval = "1s",
        indexStoreType = "fs")
    @NoArgsConstructor
    @AllArgsConstructor
    @Getter
    @Setter
    public class GeoPointBean implements Serializable {
      private static final long serialVersionUID = 2084886055991558779L;
    
      @Id
      @JSONField(ordinal = 1)
      private String id;
    
      @JSONField(ordinal = 2)
      @Field(type = FieldType.Keyword)
      private String type;
    
      @GeoPointField
      @JSONField(ordinal = 3)
      private Object location;
    }
    
    私のところの様子に従ってmappingをつければいいので、プロジェクトの起動時に自動的に生成されます
  • アップロードデータ
    //  index  
    if (!esTemplate.indexExists(GeoPointBean.class)) {
        esTemplate.createIndex(GeoPointBean.class);
        esTemplate.putMapping(GeoPointBean.class);
    }
    List<IndexQuery> queries = new ArrayList<>();
    
    if (geoPointBeans.size() != geoPointDao.count()) {
        if (geoPointBeans.size() > 0) {
            for (GeoPointBean bean : geoPointBeans) {
                IndexQuery indexQuery =
                    new IndexQueryBuilder()
                    .withIndexName("poi")
                    .withType("point")
                    .withId(bean.getId())
                    .withObject(bean)
                    .build();
                queries.add(indexQuery);
                //  
                if (counter % 5000 == 0) {
                    try{
                        esTemplate.bulkIndex(queries);
                    }catch (Exception e){
                        log.error("error------->"+e.getMessage());
                    }
    
                    queries.clear();
                    log.info("bulkIndex counter : " + counter);
                }
                counter++;
            }
        }
        //  
        if (queries.size() > 0) {
            esTemplate.bulkIndex(queries);
            counter += queries.size();
        }
        esTemplate.refresh(GeoPointBean.class);
        log.info("bulkIndex  counter : " + counter);
    } else {
        counter = 1;
        log.info(" ");
    }
    

  • 近所の友達の検索を行います

    //  indices type 
    SearchRequestBuilder searchRequestBuilderPy = client.prepareSearch("poi").setTypes("point");
    BoolQueryBuilder boolQueryBuilderPy = QueryBuilders.boolQuery();
    GeoDistanceQueryBuilder matchQueryBuilderRegionPy =
    // 
    geoDistanceQuery("location")
    // 
    .point(point)
    // , 
    .distance(distance, DistanceUnit.METERS)
    // 
    .geoDistance(GeoDistance.ARC);
    boolQueryBuilderPy.must(matchQueryBuilderRegionPy);
    searchRequestBuilderPy.setQuery(boolQueryBuilderPy);
    SearchResponse response = searchRequestBuilderPy.execute().actionGet();
    
  • esに基づいて、ある点のような面内または交差クエリーを完了します。

    ちなみに、私が言及したこれを追加しないと発生する問題を併せて貼ります.発生した問題
    unsupported_operation_exception: CIRCLE geometry is not supported
    
    実はこの問題は、公式の例ではgeo_shapeタイプの例は単純な例にすぎず、円のサポートは追加されていない.このうち公式githubのissueでもこの点が言及されており、解決策:issueの出典:geo_shape query with circle does not work for legacy geo_shape field#49296実は公式サイトにも詳しい説明があります:出典
    Indexing approachedit
    GeoShape types are indexed by decomposing the shape into a triangular mesh and indexing each triangle as a 7 dimension point in a BKD tree. This provides near perfect spatial resolution (down to 1e-7 decimal degree precision) since all spatial relations are computed using an encoded vector representation of the original shape instead of a raster-grid representation as used by the Prefix trees indexing approach. Performance of the tessellator primarily depends on the number of vertices that define the polygon/multi-polygon. While this is the default indexing technique prefix trees can still be used by setting the tree or strategy parameters according to the appropriate Mapping Options. Note that these parameters are now deprecated and will be removed in a
    
    
  • ここでは、次のシナリオを示します.
    {
      "shape": {
        "_all": {
          "enabled": false
        },
        "properties": {
          "id": {
            "type": "keyword"
          },
          "geometry": {
            "type": "geo_shape",
              // tree strategy 
            "tree": "geohash",
            "strategy": "recursive"
          }
        }
      }
    }
    

    クエリのインタフェースは次のとおりです.
    SearchRequestBuilder searchRequestBuilderPy = client.prepareSearch("wkt").setTypes("shape");
    BoolQueryBuilder boolQueryBuilderPy = QueryBuilders.boolQuery();
    
    GeoShapeQueryBuilder matchQueryBuilderRegionPy = null;
    try {
        matchQueryBuilderRegionPy =
            geoIntersectionQuery(
            "geometry",
            // 
            new CircleBuilder()
            // 
            .center(point.getLon(), point.getLat())
            // 
            .radius(radius, DistanceUnit.METERS));
    } catch (IOException e) {
        e.printStackTrace();
    }