我有一个ElasticSearch索引,其中包含"商店"的列表。
我希望允许客户通过geo_distance
搜索这些商店(因此,搜索点并在该位置附近找到商店)和文本匹配,例如商店名称/地址上的匹配。
我希望获得与这两个标准的 相匹配的结果,并且我希望这些结果的顺序是两者的组合。文本匹配越强,越接近搜索点,结果越高。 (显然,这将是一个将这两者结合起来的公式,这需要调整,而不是太担心那部分)。
我的问题/我尝试过的事情:
geo_distance
是filter
,而不是query
,因此我无法在请求的query
部分进行组合。
我可以使用匹配名称或位置的bool => should
过滤器(而不是查询)。这给了我想要的结果,但没有按顺序。
我也可以将_geo_distance
作为sort
子句的一部分,以便更接近该点的文档排名更高。
我没想到的是我将如何选择"常规" _score
ElasticSearch在进行文本匹配时为文档提供,并将其与geo_distance
分数相结合。
通过在过滤器中进行文本匹配,它似乎不会影响文档的分数(这是有意义的)。而且我不知道如何将query
部分和geo_distance filter
中的文字匹配结合起来,以便OR
而不是AND
。
我想我最好的选择就是相当于:
{
function_score: {
query: { ... },
functions: [
{ geo_distance function },
{ multi_match_result score },
],
score_mode: 'multiply'
}
}
但我不确定你可以geo_distance
作为分数函数,而且我不知道如何将multi_match_result score
作为分数函数,或者如果它是&#39甚至可能。
任何指针都将非常感激。
我正在使用ElasticSearch v1.4,但我可以根据需要进行升级。
答案 0 :(得分:6)
但我不确定你可以将geo_distance作为分数函数,而且我不知道如何将multi_match_result分数作为分数函数,或者甚至可能。或者它是否可能。
你不能按照你要求的方式做到这一点,但你可以轻松地做你想做的事。对于更简单的情况,只需使用普通查询即可获得评分。
过滤器的问题在于它们是/否是问题,因此如果您在function_score
中使用它们,那么它可以提高分数,也可以不提高分数。您可能想要的是随着距离原点的距离增加而得分的降低。它是肯定/否定性质,阻止他们完全影响分数。通过匹配过滤器隐含的相关性没有任何改善 - 它只是意味着它是答案的一部分,但是说它应该更接近顶部/它没有意义结果就是这样。
这是Decay function score有帮助的地方。它适用于数字date
,以及 - 最有用的 - geo_point
。除了它接受的数据类型之外,它还可以使用高斯,指数或线性衰减函数进行衰减。你想要选择的那个是诚实的任意,你应该给那个选择最佳"体验"。我建议从gauss
开始。
"function_score": {
"functions": [
"gauss": {
"my_geo_point_field": {
"origin": "0, 1",
"scale": "5km",
"offset": "500m",
"decay": 0.5
}
}
]
}
请注意,origin
采用x, y
格式(由于标准GeoJSON),longitude, latitude
。
每个值都会影响分数如何根据图表衰减(从文档中批发)。如果您使用0
的偏移量,则一旦在原点 ,分数就会开始下降。通过偏移,它允许一些缓冲区被认为是一样好。
在scale
是直接与decay
,所述得分将由decay
值砍倒关联一旦scale
- 从远处的{{ 1}}(+/- origin
)。在上面示例中的我的中,来自offset
的任何5km
都会得到origin
上任意分数的一半。
再次注意,不同类型的衰变函数会改变评分的形状。
我希望这些结果的顺序是两者的结合。
这是origin
/ bool
复合查询的目的。根据每场比赛,您可以获得改进得分的OR行为。将此与上述相结合,您需要以下内容:
should
注意:如果添加{
"query": {
"bool": {
"should": [
{
"multi_match": { ... }
},
{
"function_score": {
"functions": [
"gauss": {
"my_geo_point_field": {
"origin": "0, 1",
"scale": "5km",
"offset": "500m",
"decay": 0.5
}
}
]
}
}
]
}
}
}
,则must
行为会从字面上的OR行为(至少1必须匹配)更改为完全可选行为(none必须匹配)。
我正在使用ElasticSearch v1.4,但我可以根据需要进行升级。
从Elasticsearch 2.0开始,每个过滤器都是一个查询,每个查询也都是一个过滤器。唯一的区别是它使用的上下文。这里没有改变我的答案,但它可以帮助你将来除了接下来我说的是什么。
Geo-related performance increased dramatically in ES 2.2+。您应该升级(并重新创建与地理相关的索引)以利用这些更改。 ES 5.0也会有类似的好处!