2014-02-28 25 views
1

我有一堆带有位置字段的文档,并且对于给定的搜索查询与给定坐标,我想根据它们的位置是否在给定坐标的25英里范围内进行分组。然而,在每个组中,我希望结果不是按位置靠近排序的。有没有优雅的方式来做到这一点?在elasticsearch中,如何通过位置邻近来对结果进行分组?

作为一个例子,假设我有以下文件:

[ 
    { 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英里之内,$ 4,$ C5均超过25英里远从$ c。靠近$ 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 }, 
    ] 
] 
+0

,如果你发布一些例子doc和您曾经试图做到这一点任何疑问它可能会有所帮助。 – mconlin

+0

已添加@mconlin示例。谢谢! – dementrock

回答

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缩进。

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

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

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

链接:

+0

我给这个问题增加了一个例子。理想情况下,如果可能的话,我会在一次调用elasticsearch的时候这样做。否则,我总是可以首先使用<= 25英里的过滤器进行搜索,然后当结果进入最后一页时,使用> 25英里的过滤器执行另一个查询,这是一个不太优雅的解决方案。 – dementrock

+2

你可以使用多搜索API(http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-multi-search.html) 这将允许你做两个搜索一个电话。 – Akshay

+0

谢谢@Akshay - 很好找!我已经测试过并更新了答案。 –

相关问题