ES评分这一块主要依靠function_score
,它可以改变查询返回文档的分数。通常计算得分代价比较大,它可以对已经过滤的文档进行评分。function_score
中需要定义一个 query 以及一个或多个计算查询的得到文档得分的函数。只有一个计算得分函数的示例如下:
GET localhost:9200/index-name/_search?pretty
{
"query": {
"function_score": {
"query": { "match_all": {} },
"boost": "5",
// random_score 就是一种随机计算得分的函数
"random_score": {},
"boost_mode":"multiply"
}
}
}
在function_score
中提供几种计算得分的函数:
script_score
:可以在内部包裹额外的query语句,可以选择使用文档中其他数字属性值来计算自定义评分;weight
:可以将得分和weight
字段值相乘,有时可能会希望这样做,因为对特定查询设置的提升值(即boost
设置的值)进行了归一化,而对于此得分函数却没有,数字值是float类型;random_score
:根据_uid
的hash值生成得分,并带有一个变化的seed
,如果不指定seed
的值,则使用当前时间戳;field_value_factor
:可以使用文档中的字段来人为影响得分,和script_score
函数相似,但它可以避免脚本开销。如果被用于一个多值字段,那只有该字段的第一个值会被用来计算,其他的值不会用于计算;- decay functions:衰减函数,可以随着文档距离给定值(数值类型,表示原点)的距离进行评分,需要指定参与评分的每个字段的
origin
(标识中心值)和scale
(衰减的速率)。
下面的是示例文档结构:
"_source": {
"id": 1724933159515744,
"propertyId": 1724930759808608,
"name": "测试文档",
"categoryIds": [
10000046,
10000001,
10000000
],
"subject": null,
"status": -1,
"description": "这仅仅是一个测试评分的文档",
"shopId": 1587726129258720
}
以上面的文档为示例,脚本如下:
// 1. script_score 函数计算得分
GET localhost:9200/index-name/_search?pretty
{
"query": {
"function_score": {
"query": {
"match": {
"name": "门"
}
},
"boost": "1",
"script_score": {
"script": {
// 这个字段主要用于自定义变量,有必要的话需要定义
"params": {
"paramA": 2,
"paramB": 10
},
// 使用文档中各自 status 字段的平方作为评分
"inline": "Math.pow(doc['status'].value, params.paramA) + params.paramB"
}
}
}
}
}
// 2. weight 函数计算得分
GET localhost:9200/index-name/_search?pretty
{
"query": {
"function_score": {
"query": {
"match": {
"name": "门"
}
},
"boost": "1",
// 可以调整该参数大小观察最终得分的变化
"weight": 2
}
}
}
// 3. random_score 函数计算得分
GET localhost:9200/index-name/_search?pretty
{
"query": {
"function_score": {
"query": { "match_all": {} },
"boost": "5",
// random_score 就是一种随机计算得分的函数,使用 _uid 的hash值打分,携带一个 seed 变量
"random_score": {},
"boost_mode":"multiply"
}
}
}
// 4. field_value_factor 函数计算得分
GET localhost:9200/index-name/_search?pretty
{
"query": {
"function_score": {
// 使用 字段值 影响打分,最终得分为 sqrt(1.2 * doc['categoryIds'].value)
"field_value_factor": {
// categoryIds 是一个数组,取数组中的第一个值进行计算
"field": "categoryIds",
// 影响因子
"factor": 1.2,
// 计算方式选择开根号
"modifier": "sqrt",
"missing": 1
},
"boost": "1"
}
}
}
// 5. 衰减函数 计算得分
GET localhost:9200/index-name/_search?pretty
{
"query": {
"function_score": {
// 选用高斯(还有线性和)衰减函数
"gauss": {
"status": {
"origin": 80,
"scale": 5,
"offset": 1,
"decay" : 0.5
}
}
}
}
}
注:
1.field_value_factor
函数中
field
:从文档中提取出来参与计算评分的字段;factor
:(可选),标识从文档中提取字段的影响因子,默认为1;modifier
:用于提取的字段如何参与评分,可选行为有:none
:不对该字段做任何评分行为(默认);log
:使用 log 进行对数计算,取10为底;log1p
:对提取的字段加1后取对数,取10为底;log2p
:同上,加2取对数,取10为底;ln
:同上,取 e 为底;ln1p
:同上,加1并取 e 为底;ln2p
:同上,加2并取 e 为底;square
:直接平方;sqrt
:开根号;reciprocal
:取倒数
missing
:如果提取的字段在文档中不存在,则使用missing
提供的值替代field
指定的字段值进行计算;
上述modifier
的几种行为务必注意一些算术异常,比如log
和ln
以及reciprocal
函数不能对0进行计算,如果出现就会出现算术异常,可以适当使用log1p
来替换使用或者直接过滤掉这部分为0的数据。
2.衰减函数Decay functions中
- 衰减函数:本身包含线性(
linear
)、指数(exp
)、高斯(gauss
)三种衰减函数可选; origin
:表示给定的中心值,即原点,必须和提取的字段本身类型一致,如上述类型提取文档的status
字段为数值类型,那原点也必须为数值,对于Date类型的字段支持使用now
作为变量使用;scale
:表示衰减函数的衰减速率,其实origin
+offset
=decay
。对于地理类型geo
可以定义为数值+单位
的形式(如2m
、5km
,默认单位为m
),对于Date
类型,可以定义为1h
、2d
等等形式(默认单位为毫秒);offset
:可选参数,如果定义了该参数,衰减函数将会只计算那些离原点origin
的距离大于该值的文档进行评分,默认为0;decay
:定义了衰减函数如何按比例给定的距离对文档进行评分,如果未定义decay
,则距离标尺上的文档将获得0.5分。
关于具体的使用参见文档Supported decay functions。