一、概要
在使用ES进行搜索时,评分的控制是非常关键的。
而如何对搜索评分进行定制化控制,让其更符合我们想要的评分结果呢?
- 对boost参数进行控制
- 通过rescore对查询结果的评分进行二次控制
- 使用function_score作为终极武器对评分进行函数控制
二、对比&&选择
boost | rescore | function_score | |
---|---|---|---|
使用场景 | 在常规搜索中,经常使用boost进行评分的控制。 使用起来相对简单,但是控制度相对有限。 只能对单个字段进行控制,效果较为僵硬。 | 基于查询结果的二次查询方式对评分进行控制。 不会过多影响性能,可以解决大部分问题。 | 对评分进行函数控制,提供多种函数。 可以根据不同场景选择不同函数,解决多种评分需求。 但是会影响部分查询速率。 支持脚本形式自定义函数,作为终极解决方案。 |
三、应用实践
A、boost
1)概念
对于每次的查询可以使用boost参数来控制评分
2)实例
# 创建索引
PUT my_index
{
"mappings":{
"properties":{
"content":{
"type":"text"
}
}
}
}
}
# boost评分控制实例
POST /my_index/_search
{
"query":{
"bool":{
"should":[
{
"match":{
"content":{
"query":"文本A",
"boost":2
}
}
},
{
"match":{
"content":"文本B"
}
}
]
}
}
}
B、rescore
1)概念
Rescore可以帮助提高精度,方法是仅重新排序由query和 post_filter阶段返回的文档 ,基于已查询到的文档进行Rescore操作,而不会作用于全文文档。
2)参数
参数 | 解读 |
---|---|
query_weight | 原始查询权重 |
rescore_query_weight | rescore查询权重 |
score_mode | 原始查询与rescore查询评分合并方式
|
3)DSL
POST /_search
{
"query" : {
"match" : {
"message" : {
"operator" : "or",
"query" : "the quick brown"
}
}
},
"rescore" : {
"window_size" : 50,
"query" : {
"rescore_query" : {
"match_phrase" : {
"message" : {
"query" : "the quick brown",
"slop" : 2
}
}
},
"query_weight" : 0.7,
"rescore_query_weight" : 1.2,
"score_mode":"total"
}
}
}
C、function_score
1)概念
function_score是用于处理文档分值的特殊DSL,它会在查询结束后对每一个匹配的文档进行一系列的重打分操作,最后以生成的最终分数进行排序。
2)多种function解读
- weight:你将分数乘以锁提供的权重。boost在特定查询会被规范化,而weight永远不会,值是浮点类型
- random_score:生成一个在[0,1]之间的随机分数。
- field_value_factor:利用一个 字段值进行类似函数的计算,但是不用编写脚本,避免开销。
-
field
:指定字段名 -
modifier
将字段值进行加工,有以下的几个选项:none
:不处理log
:计算对数log1p
:先将字段值 +1,再计算对数log2p
:先将字段值 +2,再计算对数ln
:计算自然对数ln1p
:先将字段值 +1,再计算自然对数ln2p
:先将字段值 +2,再计算自然对数square
:计算平方sqrt
:计算平方根reciprocal
:计算倒数
factor
:对字段值进行预处理,乘以指定的数值(默认为 1)
-
- decay_functions:衰减函数,在给定范围区间内逐步衰减评分。
衰减函数(Decay Function)提供了一个更为复杂的公式,它描述了这样一种情况:对于一个字段,它有一个理想的值,而字段实际的值越偏离这个理想值(无论是增大还是减小),就越不符合期望。这个函数可以很好的应用于数值、日期和地理位置类型,由以下属性组成:
- 原点(
origin
):该字段最理想的值,这个值可以得到满分(1.0) - 偏移量(
offset
):与原点相差在偏移量之内的值也可以得到满分 - 衰减规模(
scale
):当值超出了原点到偏移量这段范围,它所得的分数就开始进行衰减了,衰减规模决定了这个分数衰减速度的快慢 -
衰减值(
decay
):该字段可以被接受的值(默认为 0.5),相当于一个分界点,具体的效果与衰减的模式有关
- 原点(
- script_score:可以自定义编写一个函数脚本,来自定义评分
3)参数
参数 | 解读 |
---|---|
score_mode | 函数计算影响字段的评分方式(效力于函数) multiply:分数相乘(默认) sum: 分数相加 avg:分数平均 first:第一个方法匹配过滤被应用 max:最大的分数 min:最小的分数 |
boost_mode | 函数分数与查询分数的计算方式(效力于最终的评分) multiply:查询分数*函数分数相乘(默认) replace:只使用函数的分数,忽略查询的分数 sum:查询分数和函数分数相加 avg:平均 max:取查询分数和函数分数中大的 min:取查询分数和函数分数中小的 |
min_score | 查询分数小于该参数的文档,不进入函数计算中。 |
4)实例
# field_value_factor实例
# 有一个商品索引,包含字段 销量sales和title商品名称。
# 需求是查询"雨伞"商品 并根据销量进行评分的排序 此时选择field_value_factor非常合适
# 该DSL表示查询雨伞对应的商品 并且对销量sales字段的评分进行square(平方)处理,这样可以使得销量越高的商品评分越高
POST /_search
{
"query": {
"function_score": {
"query": {
"match": {
"title": "雨伞"
}
},
"field_value_factor": {
"field": "sales",
"modifier": "square"
},
"boost_mode": "sum"
}
}
}
# decay_functions实例
# 需求为:文档发布时间在10天及10天前的文档,评分进行衰减越来越低。
# 该DSL表示查询 文档内容中包含"中国"的文档,并且文档发布时间在10天内评分正常,发布时间超过10天的文档,评分逐步衰减,发布时间越远的评分越低!
{
"query": {
"function_score": {
"query": {
"match": {
"content": "中国"
}
},
"gauss": {
"preview_time": {
"origin": "1628650247300",
"scale": "864000",
"offset": "8640000",
"decay": 0.5
}
}
}
}
}