ElasticSearch地理距离查询

1 投票
1 回答
967 浏览
提问于 2025-04-18 02:29

我在Python中使用地理距离查询,代码是这样的:

{
  "query": {
    "filtered": {
      "query": {
        "match_all": {}
      },
      "filter": {
        "geo_distance": {
          "distance": "20miles",
          "location": {
            "lat": 51.512497,
            "lon": -0.052098
          }
        }
      }
    }
  }
} 

这个查询运行得很好。我的问题是,如何从文档中给“距离”赋值。我在每条记录的索引中有一个字段,像这样 distance: 50,我想把它用作地理距离查询中的距离值。我试过 "distance":doc['distance'].value,但没有成功。

1 个回答

3

普通的查询和过滤器并不支持在里面放脚本。

假设你已经存储了一个名为 locationgeo_point,然后你想用一个 脚本过滤器,使用 doc['field_name'].distanceInMiles(lat, lon) (而不是 distance(lat, lon),因为标准单位是 v1.0.0 开始):

{
  "filtered" : {
    "query" : { "match_all" : { } },
    "filter" : {
      "script" : {
        "script" :
          "doc['location'].distanceInMiles(lat, lon) < doc['distance'].value",
        "params" : {
          "lat" : 51.512497,
          "lon" : -0.052098
        }
      }
    }
  }
}

如果你正在运行一个使用之前标准单位 英里 的 Elasticsearch 实例(在 v1.0.0 之前),那么你可以使用普通的 distance 函数(或者如果你的 distance 单位已经是现在标准的 v1.0.0 开始):

{
  "filtered" : {
    "query" : { "match_all" : { } },
    "filter" : {
      "script" : {
        "script" :
          "doc['location'].distance(lat, lon) < doc['distance'].value",
        "params" : {
          "lat" : 51.512497,
          "lon" : -0.052098
        }
      }
    }
  }
}

注意:你可以在脚本中直接提供 latlon 的值来一次性执行,但脚本是被编译和缓存的,所以使用参数可以让脚本重复使用,从而在第一次使用后执行得更快。

如文档中所述,你可以通过在过滤器中添加 "_cache" : true 来缓存过滤器的结果,但默认情况下,过滤器的结果是 被缓存的。

撰写回答