一 序
本文属于极客时间Elasticsearch核心技术与实战学习笔记系列。
在使用Elasticsearch进行全文搜索的时候,默认是使用BM25计算的_score字段进行降序排序的。
- ES 默认会以文档的相关度算分进行排序
- 可以通过制定一个或者多个字段进行排序
- 使用相关性算分(score)排序,不能满足某些特定条件
- 无法针对相关度,对排序实现更多的控制
二 Function Score Query
Function Score Query
- 可以在查询结束后,对每一个匹配的文档进行一系列的重新算分,根据新生成的分数进行排序
提供了几种默认的计算分值的函数
- Weight:为每一个文档设置一个简单而不被规范化的权重
- Field Value Factor:使用该数值来修改_score,例如将 “热度” 和 “点赞数” 作为算分的参考因素
- Random Score:为每一个用户使用一个不同的,随机算分结果
2.1 demo按受欢迎度提升权重
- 希望能够将点赞多的 blog,放在搜索列表相对靠前的位置。同事搜索的评分,还是要作为排序的主要依据
- 新的算分 = 老的算分 * 投票数
- 投票数为 0
- 投票数很大时
数据准备:
PUT /blogs/_doc/1
{
"title": "About popularity",
"content": "In this post we will talk about...",
"votes": 0
}
PUT /blogs/_doc/2
{
"title": "About popularity",
"content": "In this post we will talk about...",
"votes": 100
}
PUT /blogs/_doc/3
{
"title": "About popularity",
"content": "In this post we will talk about...",
"votes": 1000000
}
其中数据的title,content 都是一样的,只是投票数差别很大。下面使用:field_value_factor:考虑到vote数量。
可以看到,票数高的分数遥遥领先。
2.2使用 Modifier 平滑曲线
再来看看field_value_factor内的一些参数
field
相乘的字段,该字段必须是数字类型。
factor
相乘的系数,可以自己调节相乘的系数
missing
定义字段缺省值
modifier
刚才的例子,差异性巨大,可以使用modifier修正字段值.下面是官网的介绍:
This table lists how field_value_factor
modifiers can be implemented through a script:
Modifier | Implementation in Script Score |
| - |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
可以看到,用了顺序不变,但是分数差距不大了。
当factor和modifier同时使用的时候,factor优先于modifier
2.3 Boost Mode 和 Max Boost
Boost Mode
- Multiply:算分和函数值的乘积
- Sum:算分和函数值的和
- Min/Max:算分与函数去 最小 / 最大值
- Replace:使用函数取代算分
Max Boost 可以将算分控制在一个最大值
当我们使用field_value_factor和functions内简单的weight无法满足业务的时候,可以使用Elasticsearch提供的Painless脚本来自定义排序函数,这个老师没有展开,感兴趣的看下官网的介绍吧。
2.4 一致性随机函数
可以让不同的人请求得到不同的排序结果,而同一个人请求可以得到相同的结果。
es 7.0 之后,参数有两个:
seed
指定随机的种子,相同的种子返回相同排序,每个种子会为每个文档生成一个0-1的随机数,改随机数就是random_score的返回值,可以和其他filter或者外部打分一起使用。
field
对于相同shard的相同field的值,产生的随机数一样,因此在使用的时候,尽量选择值不一样的field。