通过文本匹配和到一个点的距离对文档进行评分
Scoring documents by both textual match and distance to a point
我有一个包含 "shops" 列表的 ElasticSearch 索引。
我想允许客户通过 geo_distance
(因此,搜索一个点并找到该位置附近的商店)和文本匹配来搜索这些商店,例如商店名称/地址的匹配。
我希望获得符合这两个条件的 之一的结果,并且我希望这些结果的顺序是两者的组合。文本匹配越强,越接近搜索点,结果就越高。 (显然,将有一个公式可以将这两者结合起来,这需要进行调整,但不要太担心那部分)。
我的问题/我尝试过的方法:
geo_distance
是 filter
,而不是 query
,因此我无法在请求的 query
部分合并两者。
我 可以 使用匹配名称或位置的 bool => should
过滤器(而不是查询)。这给了我想要的结果,但顺序不对。
我还可以将 _geo_distance
作为 sort
子句的一部分,这样越接近该点的文档排名越高。
我还没有弄清楚的是,在进行文本匹配时,我将如何获取 ElasticSearch 为文档提供的 "regular" _score
,并将其与 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
作为评分函数,或者它是否可能。
任何指点将不胜感激。
我正在使用 ElasticSearch v1.4,但如果需要我可以升级。
but I'm not sure you can do geo_distance as a score function, and I don't know how to have multi_match_result score as a score function, or if it's even possible.
你不能真正按照你要求的方式去做,但你可以很容易地做你想做的事。对于更简单的情况,您只需使用普通查询即可获得评分。
过滤器的问题在于它们是 yes/no 个问题,因此如果您在 function_score
中使用它们,那么它要么提高分数,要么不提高分数。您可能想要的是随着与原点距离的增加而降低分数。正是 yes/no 的性质阻止了它们对分数的影响。匹配过滤器所暗示的相关性没有任何改进——这只是意味着它是答案的一部分,但说它应该更接近 top/bottom 结果是没有意义的。
这是 Decay function score 的帮助所在。它适用于数字、date
s,以及——这里最有用的——geo_point
s。除了它接受的数据类型之外,它还可以使用高斯、指数或线性衰减函数进行衰减。你想选的那个真的是随意的,你应该给选出最好的那一个"experience"。我建议从 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
直接相关,因为一旦距离 scale
距离 scale
origin
(+/- offset
)。在上面的 my 示例中,origin
中的任何 5km
将获得 origin
.
中任何分数的一半
再次注意,不同类型的衰减函数会改变评分的形状。
I'd like the order of these results to be a combination of both.
这是 bool
/ should
复合查询的目的。您会根据每场比赛获得分数提高的 OR 行为。结合上面的内容,你会想要这样的东西:
{
"query": {
"bool": {
"should": [
{
"multi_match": { ... }
},
{
"function_score": {
"functions": [
"gauss": {
"my_geo_point_field": {
"origin": "0, 1",
"scale": "5km",
"offset": "500m",
"decay": 0.5
}
}
]
}
}
]
}
}
}
注意:如果添加 must
,则 should
行为会从字面 OR 类行为(至少 1 个必须匹配)变为完全可选的行为(none 必须匹配)。
I'm working with ElasticSearch v1.4, but I can upgrade if necessary.
从 Elasticsearch 2.0 开始,每个过滤器都是一个查询,每个查询也是一个过滤器。唯一的区别是它所使用的 context 。这不会改变我在这里的答案,但除了我接下来要说的内容之外,它可能会在将来对您有所帮助。
Geo-related performance increased dramatically in ES 2.2+。您应该升级(并重新创建与地理相关的索引)以利用这些更改。 ES 5.0 也会有类似的好处!
我有一个包含 "shops" 列表的 ElasticSearch 索引。
我想允许客户通过 geo_distance
(因此,搜索一个点并找到该位置附近的商店)和文本匹配来搜索这些商店,例如商店名称/地址的匹配。
我希望获得符合这两个条件的 之一的结果,并且我希望这些结果的顺序是两者的组合。文本匹配越强,越接近搜索点,结果就越高。 (显然,将有一个公式可以将这两者结合起来,这需要进行调整,但不要太担心那部分)。
我的问题/我尝试过的方法:
geo_distance
是filter
,而不是query
,因此我无法在请求的query
部分合并两者。我 可以 使用匹配名称或位置的
bool => should
过滤器(而不是查询)。这给了我想要的结果,但顺序不对。我还可以将
_geo_distance
作为sort
子句的一部分,这样越接近该点的文档排名越高。
我还没有弄清楚的是,在进行文本匹配时,我将如何获取 ElasticSearch 为文档提供的 "regular" _score
,并将其与 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
作为评分函数,或者它是否可能。
任何指点将不胜感激。
我正在使用 ElasticSearch v1.4,但如果需要我可以升级。
but I'm not sure you can do geo_distance as a score function, and I don't know how to have multi_match_result score as a score function, or if it's even possible.
你不能真正按照你要求的方式去做,但你可以很容易地做你想做的事。对于更简单的情况,您只需使用普通查询即可获得评分。
过滤器的问题在于它们是 yes/no 个问题,因此如果您在 function_score
中使用它们,那么它要么提高分数,要么不提高分数。您可能想要的是随着与原点距离的增加而降低分数。正是 yes/no 的性质阻止了它们对分数的影响。匹配过滤器所暗示的相关性没有任何改进——这只是意味着它是答案的一部分,但说它应该更接近 top/bottom 结果是没有意义的。
这是 Decay function score 的帮助所在。它适用于数字、date
s,以及——这里最有用的——geo_point
s。除了它接受的数据类型之外,它还可以使用高斯、指数或线性衰减函数进行衰减。你想选的那个真的是随意的,你应该给选出最好的那一个"experience"。我建议从 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
直接相关,因为一旦距离 scale
距离 scale
origin
(+/- offset
)。在上面的 my 示例中,origin
中的任何 5km
将获得 origin
.
再次注意,不同类型的衰减函数会改变评分的形状。
I'd like the order of these results to be a combination of both.
这是 bool
/ should
复合查询的目的。您会根据每场比赛获得分数提高的 OR 行为。结合上面的内容,你会想要这样的东西:
{
"query": {
"bool": {
"should": [
{
"multi_match": { ... }
},
{
"function_score": {
"functions": [
"gauss": {
"my_geo_point_field": {
"origin": "0, 1",
"scale": "5km",
"offset": "500m",
"decay": 0.5
}
}
]
}
}
]
}
}
}
注意:如果添加 must
,则 should
行为会从字面 OR 类行为(至少 1 个必须匹配)变为完全可选的行为(none 必须匹配)。
I'm working with ElasticSearch v1.4, but I can upgrade if necessary.
从 Elasticsearch 2.0 开始,每个过滤器都是一个查询,每个查询也是一个过滤器。唯一的区别是它所使用的 context 。这不会改变我在这里的答案,但除了我接下来要说的内容之外,它可能会在将来对您有所帮助。
Geo-related performance increased dramatically in ES 2.2+。您应该升级(并重新创建与地理相关的索引)以利用这些更改。 ES 5.0 也会有类似的好处!