ElasticSearch 越新的记录越靠前,字段值越大的越靠前

使用ElasticSearch自带的function_score 查询

按受欢迎度提升权重

设想有个网站供用户发布博客并且可以让他们为自己喜欢的博客点赞,我们希望将更受欢迎的博客放在搜索结果列表中相对较上的位置,同时全文搜索的评分仍然作为相关度的主要排序依据,可以简单的通过存储每个博客的点赞数来实现它:

PUT /blogposts/post/1
{
  "title":   "About popularity",
  "content": "In this post we will talk about...",
  "votes":   6
}

在搜索时,可以将 function_score 查询与 field_value_factor 结合使用,即将点赞数与全文相关度评分结合:

GET /blogposts/post/_search
{
  "query": {
    "function_score": { (1)
      "query": { (2)
        "multi_match": {
          "query":    "popularity",
          "fields": [ "title", "content" ]
        }
      },
      "field_value_factor": { (3)
        "field": "votes" (4)
      }
    }
  }
}
  1. function_score 查询将主查询和函数包括在内。

  2. 主查询优先执行。

  3. field_value_factor 函数会被应用到每个与主 query 匹配的文档。

  4. 每个文档的 votes 字段都 必须 有值供 function_score 计算。如果 没有 文档的 votes 字段有值,那么就 必须 使用 {ref}/query-dsl-function-score-query.html#function-field-value-factor[missing 属性] 提供的默认值来进行评分计算。

在前面示例中,每个文档的最终评分 _score 都做了如下修改:

new_score = old_score * number_of_votes

然而这并不会带来出人意料的好结果,全文评分 _score 通常处于 0 到 10 之间,如下图 受欢迎度的线性关系基于 _score 的原始值 2.0 中,有 10 个赞的博客会掩盖掉全文评分,而 0 个赞的博客的评分会被置为 0 。

Linear popularity based on an original `_score` of `2.0`
Figure 3. 受欢迎度的线性关系基于 _score 的原始值 2.0

modifier

一种融入受欢迎度更好方式是用 modifier 平滑 votes 的值。换句话说,我们希望最开始的一些赞更重要,但是其重要性会随着数字的增加而降低。 0 个赞与 1 个赞的区别应该比 10 个赞与 11 个赞的区别大很多。

对于上述情况,典型的 modifier 应用是使用 log1p 参数值,公式如下:

new_score = old_score * log(1 + number_of_votes)

log 对数函数使 votes 赞字段的评分曲线更平滑,如图 受欢迎度的对数关系基于 _score 的原始值 2.0 :

 

posted @ 2021-01-15 14:22  赵米饭  阅读(260)  评论(0)    收藏  举报