通过文本匹配和到点的距离对文档进行评分

Posted

技术标签:

【中文标题】通过文本匹配和到点的距离对文档进行评分【英文标题】:Scoring documents by both textual match and distance to a point 【发布时间】:2016-10-27 04:32:03 【问题描述】:

我有一个包含“商店”列表的 ElasticSearch 索引。

我想让客户通过geo_distance(因此,搜索一个点并找到该位置附近的商店)和文本匹配(例如商店名称/地址的匹配)来搜索这些商店。

我希望获得与这两个条件中的任一个相匹配的结果,并且我希望这些结果的顺序是两者的组合。文本匹配越强,越接近搜索点,结果越高。 (显然,将有一个将这两者结合起来的公式,这需要调整,还不太担心那部分)。

我的问题/我尝试过的:

geo_distancefilter,而不是 query,所以我不能在请求的 query 部分将两者结合起来。

可以使用匹配名称或位置的bool => should 过滤器(而不是查询)。这给了我想要的结果,但不是按顺序排列的。

我还可以将_geo_distance 作为sort 子句的一部分,以便更接近该点的文档排名更高。

我还没有想到的是,在进行文本匹配时,我将如何采用 ElasticSearch 为文档提供的“常规”_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,但如有必要,我可以升级。

【问题讨论】:

+1 用于提供您的 Elasticsearch 版本并完全定义您的问题陈述和尝试的解决方案。 【参考方案1】:

但我不确定你是否可以将 geo_distance 作为得分函数,我不知道如何将 multi_match_result 得分作为得分函数,或者是否有可能。

你不能真正按照你要求的方式去做,但你可以很容易地做你想做的事。对于更简单的情况,您只需使用普通查询即可获得评分。

过滤器的问题在于它们是是/否问题,所以如果你在function_score 中使用它们,那么它要么会提高分数,要么不会。您可能想要的是随着与原点的距离增加而降低分数。是/否的性质完全阻止了他们影响分数。匹配过滤器暗示的相关性没有任何改进——它只是意味着它是答案的一部分,但说它应该更接近顶部/底部是没有意义的。

这就是Decay function score 提供帮助的地方。它适用于数字 dates 和 -- 最有帮助的 -- geo_points。除了它接受的数据类型之外,它还可以使用高斯、指数或线性衰减函数进行衰减。您要选择的那个是诚实任意的,您应该给选择最佳“体验”的那个。我建议从gauss 开始。

"function_score": 
  "functions": [
    "gauss": 
      "my_geo_point_field": 
        "origin": "0, 1",
        "scale": "5km",
        "offset": "500m",
        "decay": 0.5
      
    
  ]

注意originx, y 格式(由于标准GeoJSON),即longitude, latitude

每个值都会影响分数如何根据图表衰减(从文档中大量获取)。如果您使用0 的偏移量,那么一旦它不在原点完全,分数就会开始下降。有了偏移量,它就可以让一些缓冲区被认为是一样好的。

scale 直接与decay 相关联,因为一旦scaleorigin 相距(+/- @987654339 @)。在上面的 my 示例中,origin 中的任何 5km 都将获得 origin 中任何东西的一半分数。

同样,请注意不同类型的衰减函数会改变得分的形状。

我希望这些结果的顺序是两者的组合。

这就是 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 必须匹配)变为完全可选的行为(无必须匹配)。

我正在使用 ElasticSearch v1.4,但如有必要,我可以升级。

从 Elasticsearch 2.0 开始,每个过滤器都是一个查询,每个查询也是一个过滤器。唯一的区别是它使用的 context。这不会改变我在这里的答案,但除了我接下来要说的内容之外,它可能会在未来对你有所帮助。

Geo-related performance increased dramatically in ES 2.2+。您应该升级(并重新创建与地理相关的索引)以利用这些更改。 ES 5.0 也会有类似的好处!

【讨论】:

您,先生,是救生员。非常感谢 同上,我在 ES 1.6 中使用了名称搜索或基于嵌套对象中特定条件的最近位置的完全相同的用例,这可以满足我的需要。谢谢!

以上是关于通过文本匹配和到点的距离对文档进行评分的主要内容,如果未能解决你的问题,请参考以下文章

数字字段的 Lucene 自定义评分

术语与术语查询的评分不同

如何通过词向量技术来计算2个文档的相似度?

Elasticsearch系列(13)Query之全文查询

Lucene搜索流程(下)

Google App Engine Search API 自定义评分