阅读本文需要先了解function_score的相关知识,请看 ElasticSearch - function_score详解
1. 数据准备
首先准备数据和索引,在ES
插入三条数据,其中title
是text
类型,like
是integer
类型(代表点赞量)。
{ "title": "ES 入门", "like": 2 }
{ "title": "ES 进阶", "like": 5 }
{ "title": "ES 最高难度", "like": 10 }
2. function_score (field_value_factor)示例
2.1 普通查询
先使用一般的query
,查看普通的查询的评分会是如何:
GET 127.0.0.1/mytest/doc/_search
{
"query": {
"match": {
"title": "ES"
}
}
}
"hits": [
{
"_score": 0.2876821,
"_source": { "title": "ES 入门", "like": 2 }
},
{
"_score": 0.20309238,
"_source": { "title": "ES 进阶", "like": 5 }
},
{
"_score": 0.16540512,
"_source": { "title": "ES 最高难度", "like": 10 }
}
]
2.2 function_score查询(field_value_factor)
2.2.1 field_value_factor
使用function_score
的field_value_factor
改变_score
,将old_score
乘上like
的值。
{
"query": {
"function_score": {
"query": {
"match": {
"title": "ES"
}
},
"field_value_factor": {
"field": "like"
}
}
}
}
"hits": [
{
"_score": 1.6540513, //原本是0.16540512
"_source": { "title": "ES 最高难度", "like": 10 }
},
{
"_score": 1.0154619, //原本是0.20309238
"_source": { "title": "ES 进阶", "like": 5 }
},
{
"_score": 0.5753642, //原本是0.2876821
"_source": { "title": "ES 入门", "like": 2 }
}
]
本来 "ES最高难度
" 的score
是0.16540512
,经过field_value_factor
的改变,乘上了那个文档中的like
值(10
)之后,新的score
变为 1.6540513
2.2.2 max_boost
加上max_boost
,限制field_value_factor
的最大加强score
。
GET 127.0.0.1/mytest/doc/_search
{
"query": {
"function_score": {
"query": {
"match": {
"title": "ES"
}
},
"field_value_factor": {
"field": "like"
},
"max_boost": 3
}
}
}
"hits": [
{
"_score": 0.6092771, //原本是0.20309238
"_source": { "title": "ES 进阶", "like": 5 }
},
{
"_score": 0.5753642, //原本是0.2876821
"_source": { "title": "ES 入门", "like": 2 }
},
{
"_score": 0.49621537, //原本是0.16540512
"_source": { "title": "ES 最高难度", "like": 10 }
}
]
可以看到“ES入门”
的加强score是2,在max_boost
限制裡,所以不受影响。而“ES进阶”
和“ES最高难度”
的field_value_factor
函数产生的加强score因为超过max_boost的限制,所以被设为3
。
2.2.3 field_value_factor中还支持 modifier、factor 参数
有时候线性的计算new_score = old_score * like
值的效果并不是那麽好,field_value_factor
中还支持 modifier
、factor
参数,可以改变like值对old_score
的影响。
modifier参数支持的值:
-
none
: new_score = old_score * like值默认状态就是
none
,线性。
-
log1p
: new_score = old_score * log(1 + like值)最常用,可以让like值字段的评分曲线更平滑。
-
log2p
: new_score = old_score * log(2 + like值) -
ln
: new_score = old_score * ln(like值) -
ln1p
: new_score = old_score * ln(1 + like值) -
ln2p
: new_score = old_score * ln(2 + like值) -
square
: 计算平方 -
sqrt
: 计算平方根 -
reciprocal
: 计算倒数
factor参数:
factor
作为一个调节用的参数,没有modifier
那麽强大会改变整个曲线,他仅改变一些常量值,设置factor>1会
提昇效果,factor<1
会降低效果。假设modifier
是log1p
,那麽加入了factor
的公式就是new_score = old_score * log(1 + factor * like值)
。
对刚刚的例子加上 modifier
、factor
参数的查询语句如下:
GET 127.0.0.1/mytest/doc/_search
{
"query": {
"function_score": {
"query": {
"match": {
"title": "ES"
}
},
"field_value_factor": {
"field": "like",
"modifier": "log1p",
"factor": 2
}
}
}
}
2.2.4 boost_mode
就算加上了modifier
,但是 “全文评分 与 field_value_factor
函数值乘积” 的效果可能还是太大,我们可以通过参数boost_mode
来决定 old_score
和 加强score
合併的方法。
- 如果将
boost_mode
改成sum
,可以大幅弱化最终效果,特别是使用一个较小的factor
时; - 加入了
boost_mode=sum
、且factor=0.1
的公式变为new_score = old_score + log(1 + 0.1 * like值)
;
对刚刚的例子加上max_boost
参数的查询语句如下:
GET 127.0.0.1/mytest/doc/_search
{
"query": {
"function_score": {
"query": {
"match": {
"title": "ES"
}
},
"field_value_factor": {
"field": "like",
"modifier": "log1p",
"factor": 0.1
},
"boost_mode": "sum"
}
}
}