首页 > 解决方案 > 大半径的 Elasticsearch 地理距离查询优先级

问题描述

我有一个简单的 elasticsearch 7.4 索引,其中包含多个分配了地理位置坐标的机构。作为我的地理定位应用程序的用户,我将根据我当前的位置请求附近的所有 50 个机构。

这种方法的问题是当用户缩小地图(半径非常大)时,它将继续只接收地图一小部分中最近的设施。

我想通过某种优先级检索分散在整个地图中的其他结果,例如需要更高优先级的更知名的公司和合作伙伴。谷歌地图做了类似的事情,但我不确定在那里做了什么样的优先级。

使用 ES 实现这一目标的最佳方法是什么?

我当前的查询有点像这样:

GET /places/_search
{
   "size": 50,
   "query": {
      "bool": {
         "must": {
            "match_all": {}
         },
         "filter": {
            "geo_distance": {
               "distance": "10km",
               "coordinates": {
                  "lat": -2.000000,
                  "lon": -4.000000
               }
            }
         }
      }
   },
   "sort": [
      {
         "_geo_distance": {
            "coordinates": {
               "lat": -2.000000,
               "lon": -4.000000
            },
            "order": "asc",
            "unit": "m",
            "distance_type": "arc"
         }
      }
   ]
}

标签: elasticsearchgeospatial

解决方案


过去我遇到过类似的情况,我有 2 个字段 geo_coordinates 和一个产品的优先级,我必须使用这两个字段对产品进行排序,方法是对每个字段进行一些可配置的权重
使用功能分数查询,您可以重新定义弹性内部评分公式,而不仅仅是使用文本相关性排序,您可以要求弹性将 geo_distance 也包含在评分机制中,您可以在我使用的这种情况下使用差异函数linearfield_value_factor https://www.elastic.co/guide/en /elasticsearch/reference/5.6/query-dsl-function-score-query.html

POST geotest/_search
{
  "query": {
    "bool": {
      "must": [
        {
           "match_all": {}
        },
        {
          "function_score": {
            "min_score": 0.1,
            "functions": [
              {
                "weight": 1,//weight of coordinates
                "linear": {
                  "coor": {
                    "offset": "500m",
                    "origin": [
                      106.82,
                      -6.22425
                    ],
                    "scale": "500m"
                  }
                }
              },
              {
                "field_value_factor": {
                  "factor": 1,//weight of priority
                  "field": "priority",
                  "modifier": "log2p"
                }
              }
            ]
          }
        }
      ]
    }
  }
}

只需注意 field_value_factor 中的因子,它是一个对数函数,因此您需要相应地调整其值

[编辑]
要在距离 100m 和 10km 处获得相同的产品分数,您必须在原点周围定义一个区域,这可以通过offset https://www.elastic.co/guide/en/elasticsearch/reference/current/images完成/decay_2d.png
位于半径 内的所有产品offset将具有相同的分数,位于scale+offset半径内的产品将具有递减分数
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-function -score-query.html


推荐阅读