在elasticsearch中,如何按位置接近分组结果?

时间:2014-02-28 13:35:25

标签: elasticsearch

我有一堆带有位置字段的文档,对于给定坐标的给定搜索查询,我想根据它们的位置是否在给定坐标的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 },
  ]
]

1 个答案:

答案 0 :(得分:2)

要以这种方式对结果进行分组,您可以使用聚合(或1.0之前的方面) - 特别是地理距离聚合。这将为您计算每组中的结果数(< = 25英里,> 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。

这将返回一个响应数组,每个查询一个 - 每个响应等同于使用搜索API的相应查询的结果。

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

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

链接: