如何在 Elasticsearch 中查找包含给定点的多边形

Posted

技术标签:

【中文标题】如何在 Elasticsearch 中查找包含给定点的多边形【英文标题】:How to find polygons that contain a given point in Elasticsearch 【发布时间】:2020-03-11 23:33:51 【问题描述】:

我需要在包含大约 50k 地形多边形(在 ES 上存储为 geo_shape 多边形)的数据库上构建一个查询,我在其中给出一个点,它会返回包含该点的每个多边形。

我设法使用渗透查询(下面的示例)来做到这一点,但我在某处读到渗透查询不能很好地扩展。

有没有更有效的方法来实现这种行为?

使用渗透的示例:

Demo polygons

PUT geo_demo

  "mappings": 
    "properties": 
      "thepoly": 
        "type": "percolator"
      ,
      "thepoint": 
        "type": "geo_point"
      
    
  


#region 1 (red)
POST /geo_demo/_doc/1

  "thepoly": 
    "bool": 
      "must": 
        "match_all": 
      ,
      "filter": 
        "geo_polygon": 
          "thepoint": 
            "points": [
              "-23.573978,-46.664806",
              "-23.583978,-46.664806",
              "-23.583978,-46.658806",
              "-23.573978,-46.658806",
              "-23.573978,-46.664806"
            ]
          
        
      
    
  


#region 2 (green)
POST /geo_demo/_doc/2

  "thepoly": 
    "bool": 
      "must": 
        "match_all": 
      ,
      "filter": 
        "geo_polygon": 
          "thepoint": 
            "points": [
              "-23.579978,-46.664806",
              "-23.583978,-46.664806",
              "-23.583978,-46.652806",
              "-23.579978,-46.652806",
              "-23.579978,-46.664806"
            ]
          
        
      
    
  


#should match doc/1 only
GET /geo_demo/_search

  "query": 
    "percolate": 
      "field": "thepoly",
      "document": 
        "thepoint": "-23.577007,-46.661811"
      
    
  


#should match both doc/1 and doc/2
GET /geo_demo/_search

  "query": 
    "percolate": 
      "field": "thepoly",
      "document": 
        "thepoint": "-23.582002,-46.661811"
      
    
  


#should match doc/2 only
GET /geo_demo/_search

  "query": 
    "percolate": 
      "field": "thepoly",
      "document": 
        "thepoint": "-23.582041,-46.655717"
      
    
  


#should match none
GET /geo_demo/_search

  "query": 
    "percolate": 
      "field": "thepoly",
      "document": 
        "thepoint": "-23.576771,-46.655674"
      
    
  

【问题讨论】:

【参考方案1】:

你几乎不需要 elasticsearch,除非你有充分的理由。

对于 50K 多边形,您可以轻松地将它们保存在堆中,或者将每个多边形分解为 geohashes 列表。

你可以有一个以 geohash 作为键,多边形 id 作为值的堆内映射。

当您输入点时,您首先计算 geohash,然后使用 Map#get 检查该点在地图中或哪些多边形包含该点。

【讨论】:

这些多边形与其他可以组合起来进行复杂过滤的字段相关联。此外,我还有很多遗留代码要重用于过滤。这就是我的“强烈理由”哈哈 那么你可能想对其进行性能测试,在旧版本的 es 中多边形过滤器可能会很慢,但最新的 es 应该没问题。如果没有具体的性能目标,就很难谈论优化。 我能想到的最好的办法是像我描述的那样添加一个预检查阶段,这应该排除大多数输入文档,然后像你描述的那样将它们与 es 多边形渗透器匹配。跨度>

以上是关于如何在 Elasticsearch 中查找包含给定点的多边形的主要内容,如果未能解决你的问题,请参考以下文章

如何查找不包含给定字符串模式的文件?

Elasticsearch:运用 Elasticsearch 查找类似文档:more_like_this

Elasticsearch:运用 Elasticsearch 查找类似文档:more_like_this

如何查找范围是不是包含VBA中的合并单元格

Elasticsearch 通过另一个文档查找文档

使用 NEST 的 Elasticsearch:如何配置分析器来查找部分单词?