【问题标题】:In elasticsearch, how to group results by location proximity?在elasticsearch中,如何按位置接近度对结果进行分组?
【发布时间】:2014-02-28 13:35:24
【问题描述】:

我有一堆带有位置字段的文档,对于具有给定坐标的给定搜索查询,我想根据它们的位置是否在给定坐标的 25 英里范围内对结果进行分组。但是,在每个组中,我希望结果不是按位置接近度排序的。有什么优雅的方法可以做到这一点?

例如,假设我有以下文件:

[
  { id: "1", price: 13.5, coords: $c1 },
  { id: "2", price: 10, coords: $c2 },
  { id: "3", price: 15, coords: $c3 },
  { id: "4", price: 5, coords: $c4 },
  { id: "5", price: 1, coords: $c5 },
]

其中 $c1、$c2、$c3 距离 $c 不到 25 英里,而 $c4、$c5 距离 $c 超过 25 英里。接近$c的顺序是$c3, $c2, $c1, $c5, $c4。在处理按价格从低到高排序的查询时,我想返回为

[
  [
    { id: "2", price: 10, coords: $c2 },
    { id: "1", price: 13.5, coords: $c1 },
    { id: "3", price: 15, coords: $c3 },
  ],
  [
    { id: "5", price: 1, coords: $c5 },
    { id: "4", price: 5, coords: $c4 },
  ]
]

【问题讨论】:

  • 如果您发布一些示例文档以及您尝试完成此操作的任何查询,这可能会有所帮助。
  • @mconlin 示例已添加。谢谢!

标签: elasticsearch


【解决方案1】:

要以这种方式对结果进行分组,您可以使用聚合(或 1.0 之前的方面) - 特别是地理距离聚合。这将为您计算每组中的结果数( 25 英里)。然后,要检索每个组中的匹配项,请将地理距离过滤器与您的原始查询一起使用。

在排序时,你应该可以使用类似的东西

{
    "sort" : [
        { "price" : {"order" : "asc"}}
    ],
    "query" : {
        ...
    }
}

要在单个 API 调用中实现此目的,您可以尝试多搜索 API。这是 _msearch 端点,将采用以下内容:

GET _msearch
{}
{
  "sort": [
    {
      "price": {
        "order": "asc"
      }
    }
  ],
  "query": {
    "filtered": {
      "query": {
        "match_all": {}
      },
      "filter": {
        "geo_distance_range" : {
            "from" : "0mi",
            "to" : "25mi"
            "pin.location" : {
                "lat" : $c_lat,
                "lon" : $c_long
            }
        }
      }
    }
  }
}
{}
{
  "sort": [
    {
      "price": {
        "order": "asc"
      }
    }
  ],
  "query": {
    "filtered": {
      "query": {
        "match_all": {}
      },
      "filter": {
        "geo_distance_range" : {
            "from" : "25mi"
            "pin.location" : {
                "lat" : $c_lat,
                "lon" : $c_long
            }
        }
      }
    }
  }
}

记下每个查询之前的空标题 ({})。我使用 Sense 对此进行了测试,但在解析失败时遇到了一些问题 - 在发送之前使用 Ctrl+I 取消缩进 JSON。

这会返回一个响应数组,每个查询一个 - 每个响应等效于使用 Search API 的相应查询的结果。

如果您的用例始终显示所有结果,则第二种方法是合适的,并且可以满足单个 API 调用的要求。但是,如果您想单独显示结果组,第一种方法可能更有效,因为您不会检索未使用的结果。

如果此解决方案不能满足您的需求,请在问题中添加更多细节,我会再考虑!

链接:

【讨论】:

  • 我在问题中添加了一个示例。理想情况下,如果可能的话,我希望通过一次调用 elasticsearch 来做到这一点。否则,我总是可以先通过 25 英里的过滤器进行另一个查询,这是一个不太优雅的解决方案。
  • 您可以使用多重搜索 API (elasticsearch.org/guide/en/elasticsearch/reference/current/…) 这将允许您在一次调用中进行两种搜索。
  • 谢谢@Akshay - 很好的发现!我已经对此进行了测试并更新了答案。
  • 谢谢!只是想知道,这可以很好地与分页集成吗?
  • 有趣的问题!分页通常由查询中的“from”和“size”参数处理(分别默认为 0 和 10) - 因此需要再次调用多个 API。如果您的目标确实是尝试在单个调用中执行此操作,则必须在客户端处理分页(并确保在两个查询中将 size 参数设置得足够高,以便在其中获得完整的结果集单次通话)。
猜你喜欢
  • 2011-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-15
  • 2012-09-19
  • 2010-10-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多