【问题标题】:Elasticsearch : Check if GeoPoint exists in the radius of multiple circlesElasticsearch:检查GeoPoint是否存在于多个圆的半径中
【发布时间】:2020-03-22 12:56:21
【问题描述】:

我的要求是检查一个特定的 geoPoint 是否落在圆的半径内。
我正在使用 geoShape : circle 来存储位置。我的文件如下:

PUT location_test/doc/1
    {
        "location" : {
            "type" : "circle",
            "coordinates" : [73.7769,18.5642],
          "radius": "10mi"
        }
    }

查询如下:

GET location_test/_search
    {
      "query": {
        "bool": {
          "must": [
            {
              "geo_shape": {
                "location": {
                  "shape": {
                    "type": "point",
                    "coordinates": [
                      73.877097,
                      18.455303
                    ],
                    "relation": "contains"
                  }
                }
              }
            }
          ]
        }
      }
    }

此查询非常适用于单个圆形地理形状。
但是现在我想检查一个特定的 geoPoint 是否落在多个圆的半径内。
我们能不能把我们的文件写成这样:

{
  "location": [
    {
      "type": "circle",
      "coordinates": [
        73.7769,
        18.5642
      ],
      "radius": "10mi"
    },
    {
      "type": "circle",
      "coordinates": [
        -118.240853,
        34.052997
      ],
      "radius": "10mi"
    }
  ]
}

并进行查询以检查 geoPoint 是否落在哪个圆圈中。
或者还有其他方法可以实现吗?

编辑 使用地理点数组对特定地理点的文档进行排序是一种好习惯吗?

Mapping :
    {
      "mappings": {
        "doc": {
          "properties": {
            "locationPoint": {
              "type": "geo_point"
            }
          }
        }
      }
    }

PUT location_test2/doc/1
{
  "locationPoint": ["34.075433, -118.307228","36.336356,-119.304597"]
}

PUT location_test2/doc/2
{
  "locationPoint": ["34.075433, -118.307228"]  
  }

GET location_test2/_search
{
  "sort": [
      {
      "_geo_distance": {
        "locationPoint": "34.075433, -118.307228",
        "order": "asc"
      }
    }
  ]
}

【问题讨论】:

    标签: elasticsearch


    【解决方案1】:

    您当然可以在一个文档中包含多个圆圈,并且如果 任何 个圆圈包含您的观点,则搜索仍然会匹配。为简洁起见折叠步骤:

    PUT location_test
    {"mappings":{"properties":{"location":{"type":"geo_shape","strategy":"recursive"}}}}
    

    加入你的圈子:

    PUT location_test/_doc/2
    {"location":[{"type":"circle","coordinates":[73.7769,18.5642],"radius":"10mi"},{"type":"circle","coordinates":[-118.240853,34.052997],"radius":"10mi"}]}
    

    与单个圆圈的查询相同。

    GET location_test/_search
    {"query":{"bool":{"must":[{"geo_shape":{"location":{"shape":{"type":"point","coordinates":[73.7769,18.5642],"relation":"contains"}}}}]}}}
    

    这会产生我们感兴趣的文档。与直觉相反但很好的一点是,如果您提供单个对象或对象列表,无关紧要。 ElasticSearch 无需更改映射即可处理两者。


    请注意,您的 circles 位于地球的两端:

    如果您意识到这一点并且像这样查询您的 locations 是有意义的,那么一切都很好。


    从性能的角度来看,请记住,圆圈表示为多边形

    其中,取决于您的 ES 版本,表示为一堆 triangles

    因此,您可能希望索引圆形多边形而不是圆形,以加快索引速度,甚至考虑将您的圆形合并到一组多边形(MultiPolygon)中,因为从外观上看,您的圆形列表代表 相关的几何形状。

    【讨论】:

    • 很好,我们可以从这些地理查询中加载地图吗?
    • 嗯?这些地图是使用 TurfJS 生成的——turfjs.org/docs/#circle。不能只是即插即用 ES 查询和响应,但它仍然非常方便。
    • @jzzfs 我已经编辑了问题,请您复习一次。
    • 当然——你可以这样排序。您可能已经知道,这里列出了更多选项elastic.co/guide/en/elasticsearch/reference/current/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多