有时ES默认的评分规则并不能满足需求,时常会有在old_source的基础上根据某字段的值需要重新打分的需求场景,比如在相关度相差不大的情况下时间越进越靠前,或者评论数越多越靠前等等。此时需要重新打分。对此可以通过两种方式法来处理:
1、在创建索引的时候提高文档的权重,根据因素字段值来给文档设置boost.这种方式在lucene5之前有效,之后就无效了。不建议采用。
2、通过function_query来设置分数。
通过function_query来设置分数
线性提升
如在相关度相差不大的情况下,投票的数量越多排名越往前。可以采用简单的线性方式来处理:
GET /blogposts/post/_search
{
"query": {
"function_score": {
"query": {
"multi_match": {
"query": "popularity",
"fields": [ "title", "content" ]
}
},
"field_value_factor": {
"field": "votes",
"modifier": "log1p",
"factor": 2
}
}
}
}
其中
:
field:表示影响权重的字段例子中是votesmodifier:表示影响的规则修饰语 modifier 的值可以为:none (默认状态)log 、 log1p 、 log2p 、 ln 、 ln1p 、 ln2p 、 square 、 sqrt 以及 reciprocal。facror:表示影响因子。
new_score = old_score * log(1 + factor * number_of_votes)
factor 值大于 1 会提升效果, factor 值小于 1 会降低效果。
GET /blogposts/post/_search
{
"query": {
"function_score": {
"query": {
"multi_match": {
"query": "popularity",
"fields": [ "title", "content" ]
}
},
"field_value_factor": {
"field": "votes",
"modifier": "log1p",
"factor": 0.1
},
"boost_mode": "sum" ,
"max_boost": 1.5
}
}
}
boost_mode
multiply评分 _score 与函数值的积(默认)sum评分 _score 与函数值的和min评分 _score 与函数值间的较小值max评分 _score 与函数值间的较大值replace函数值替代评分 _score max_boost 设置最大的得分分值
引入模型函数来控制二次评分
origin:中心点 或字段可能的最佳值,落在原点 origin 上的文档评分 _score 为满分 1.0 。scale:衰减率,即一个文档从原点origin下落时,评分_score 改变的速度.(例如,每 £10 欧元或每 100 米)decay:从原点 origin 衰减到 scale 所得的评分 _score ,默认值为 0.5 。offset:以原点 origin 为中心点,为其设置一个非零的偏移量 offset 覆盖一个范围,而不只是单个原点。在范围 -offset <= origin <= +offset 内的所有评分 _score 都是 1.0 。
图 图 33 “衰减函数曲线” 中所有曲线的原点 origin
(即中心点)的值都是 40
, offset
是 5
,也就是在范围 40 - 5 <= value <= 40 + 5
内的所有值都会被当作原点 origin
处理——所有这些点的评分都是满分 1.0
。
在此范围之外,评分开始衰减,衰减率由 scale
值(此例中的值为 5
)和 衰减值 decay
(此例中为默认值 0.5
)共同决定。结果是所有三个曲线在 origin +/- (offset + scale)
处的评分都是 0.5
,即点 30
和 50
处。
linear
、 exp
和 gauss
(线性、指数和高斯)函数三者之间的区别在于范围( origin +/- (offset + scale)
)之外的曲线形状:
-
linear
线性函数是条直线,一旦直线与横轴 0 相交,所有其他值的评分都是0.0
。 -
exp
指数函数是先剧烈衰减然后变缓。 -
gauss
高斯函数是钟形的——它的衰减速率是先缓慢,然后变快,最后又放缓。
选择曲线的依据完全由期望评分 _score
的衰减速率来决定,即距原点 origin
的值。
回到我们的例子:用户希望租一个离伦敦市中心近( { "lat": 51.50, "lon": 0.12}
)且每晚不超过 £100 英镑的度假屋,而且与距离相比, 我们的用户对价格更为敏感,这样查询可以写成:
{
"query": {
"function_score": {
"functions": [
{
"gauss": {
"price": {
"origin": "0",
"scale": "20"
}
}
},
{
"gauss": {
"location": {
"origin": "11, 12",
"scale": "2km"
}
}
}
],
"query": {
"match": {
"properties": "balcony"
}
},
"score_mode": "multiply"
}
}
}
location 字段以地理坐标点 geo_point 映射。
price 字段是数值。
price 语句是 location 语句权重的两倍。
location 语句可以简单理解为:
以伦敦市中作为原点 origin 。
所有距原点 origin 2km 范围内的位置的评分是 1.0 。
距中心 5km ( offset + scale )的位置的评分是 0.5 。
weight 参数可以被用来调整每个语句的贡献度,权重 weight 的默认值是 1.0 。这个值会先与每个句子的评分相乘,然后再通过 score_mode 的设置方式合并。