函数算分 function_score
单函数样例
GET /_search
{
"query": {
"function_score": {
"query": { "match_all": {} },
"boost": "5",
"random_score": {},
"boost_mode":"multiply"
}
}
}
random_score 生成从 0 到但不包括 1 的均匀分布的浮点数,通常由于结果集打散。
组合多个函数
GET /_search
{
"query": {
"function_score": {
"query": { "match_all": {} },
"boost": "5",
"functions": [
{
"filter": { "match": { "test": "bar" } },
"random_score": {},
"weight": 23
},
{
"filter": { "match": { "test": "cat" } },
"weight": 42
}
],
"max_boost": 42,
"score_mode": "max",
"boost_mode": "multiply",
"min_score" : 42
}
}
}
boost : 对整体分数进行系数加权
weight : 过滤子句评分权重
首先,每个文档都根据定义的函数进行评分。参数 score_mode 指定如何组合这些分数:
score_mode | 说明 |
---|---|
multiply | 分数相乘(默认) |
sum | 分数求和 |
avg | 分数取平均值 |
first | 分数取匹配过滤器的第一个函数 |
max | 取最高分 |
min | 取最低分 |
内置函数
function_score 提供以下几种评分函数
- script_score
- weight
- random_score
- field_value_factor
- decay functions: gauss, linear, exp
script_score
script_score 函数允许您包装另一个查询并自定义它的评分,使用脚本表达式从文档中的其他数字字段值派生的计算(可选的)。这是一个简单的示例:
GET /_search
{
"query": {
"function_score": {
"query": {
"match": { "message": "elasticsearch" }
},
"script_score" : {
"script" : {
"source": "Math.log(2 + doc['likes'].value)"
}
}
}
}
}
在 Elasticsearch 中,所有文档得分都是正的 32 位浮点数。
如果 script_score 函数产生的分数精度更高,则会将其转换为最接近的 32 位浮点数。
同样,分数必须是非负数。否则,Elasticsearch 会返回一个错误。
脚本编译在缓存中进行以加快执行速度。如有必要可以考虑重用同一个脚本,并为其提供参数
GET /_search
{
"query": {
"function_score": {
"query": {
"match": { "message": "elasticsearch" }
},
"script_score" : {
"script" : {
"params": {
"a": 5,
"b": 1.2
},
"source": "params.a / Math.pow(params.b, doc['likes'].value)"
}
}
}
}
}
weight
权重分数允许您将分数乘以提供的权重。
"weight" : number
random_score
如果您希望分数可重复,可以提供seed
和field
。然后,将根据该seed、所考虑文档的最小字段值和基于索引名称和shardid计算的salt来计算最终得分,以便具有相同值但存储在不同索引中的文档获得不同的得分。请注意,位于同一shard内且字段值相同的文档将获得相同的分数,因此通常需要使用对所有文档具有唯一值的字段。一个好的默认选择可能是使用_seq_no
字段,其唯一的缺点是,如果文档被更新,分数将发生变化,因为更新操作也会更新_seq_n字段的值。
GET /_search
{
"query": {
"function_score": {
"random_score": {
"seed": 10,
"field": "_seq_no"
}
}
}
}
field_value_factor
field_value_factor 函数允许您使用文档中的字段来影响分数。它类似于使用 script_score 函数,但是,它避免了编写脚本的开销。如果用于多值字段,则只有该字段的第一个值用于计算。
假设你有一个数字类型字段 likes,并希望用这个字段影响文档的分数,这样做的例子如下
GET /_search
{
"query": {
"function_score": {
"field_value_factor": {
"field": "likes",
"factor": 1.2,
"modifier": "sqrt",
"missing": 1
}
}
}
}
这将转化为以下评分公式:sqrt(1.2 * doc['likes'].value)
field_value_factor 的函数选项:
参数 | 说明 |
---|---|
field | 要从文档中提取的字段。 |
factor | 与字段值相乘的可选因子,默认为 1。 |
modifier | 应用于字段值的修饰符可以是以下之一:none、log、log1p、log2p、ln、ln1p、ln2p、square、sqrt 或 reciprocal。默认为none。 |
Modifier 参数
Modifier | 含义 |
---|---|
none | 不要对字段值应用任何乘数 |
log | 取字段值的常用对数 |
log1p | 字段值加1,取常用对数 |
log2p | 字段值加2,取常用对数 |
ln | 取字段值的自然对数 |
ln1p | 字段值加1取自然对数 |
ln2p | 字段值加2取自然对数 |
square | 将字段值平方(乘以它本身) |
sqrt | 取字段值的平方根 |
reciprocal | 倒数字段值,类似于 1/x ,其中 x 是字段值 |
field_value_score 函数产生的分数必须是非负数,否则将发出弃用警告。
注意,取 0 的 log() 或负数的平方根是非法操作,会抛出异常。一定要限制使用范围过滤器的字段值以避免这种情况,或使用
log1p
和ln1p
decay
衰减函数(Decay Function)对于一个字段,它有一个理想的值,而字段实际的值越偏离这个理想值(无论是增大还是减小),就越不符合期望。
Decay Function 可用于数值、日期和地理位置类型。由以下属性组成:
- 原点(
origin
):该字段最理想的值,这个值可以得到满分(1.0) - 偏移量(
offset
):与原点相差在偏移量之内的值也可以得到满分 - 衰减规模(
scale
):当值超出了原点到偏移量这段范围,它所得的分数就开始进行衰减了,衰减规模决定了这个分数衰减速度的快慢 - 衰减值(
decay
):该字段可以被接受的值(默认为 0.5),相当于一个分界点,具体的效果与衰减的模式有关
例如我们想要买一样东西:
- 它的理想价格是 50 元,这个值为原点
- 但是我们不可能非 50 元就不买,而是会划定一个可接受的价格范围,例如 45-55 元,±5 就为偏移量
- 当价格超出了可接受的范围,就会让人觉得越来越不值。如果价格是 70 元,评价可能是不太想买,而如果价格是 200 元,评价则会是不可能会买,这就是由衰减规模和衰减值所组成的一条衰减曲线
或者如果我们想租一套房:
- 它的理想位置是公司附近,公司位置就是原点
- 如果离公司在 5km 以内,是我们可以接受的范围,在这个范围内我们不去考虑距离,而是更偏向于其他信息
- 当距离超过 5km 时,我们对这套房的评价就越来越低了,直到超出了某个范围就再也不会考虑了
使用样例 字段值介于 2013-09-12 和 2013-09-22 之间的文档的权重为 1.0,而距该日期 15 天的文档的权重为 0.5。
GET /_search
{
"query": {
"function_score": {
"gauss": {
"date": {
"origin": "2013-09-17",
"scale": "10d",
"offset": "5d",
"decay" : 0.5
}
}
}
}
}
DECAY_FUNCTION
衰减函数可以指定三种不同的模式:线性函数(linear)、以 e 为底的指数函数(Exp)和高斯函数(gauss),它们拥有不同的衰减曲线:
1. gauss
高斯函数,曲线特点:他的衰减速率是先缓慢,然后变快,最后又放缓。 计算公式:
计算以确保分数在距原点+-偏移量的距离范围内采用值衰减
2. exp
指数衰减,曲线特点:先剧烈衰减然后变缓。 计算公式:
再次计算参数以确保分数在距原点+-偏移量的距离范围内衰减值
3. linear
线性函数是条直线,一旦直线与横轴0相交,所有其他值的评分都是0,计算公式:
再次计算参数 s 以确保分数在距原点+-偏移量的距离范围内取值衰减
多值字段 Multi-values fields
如果用于计算衰减的字段包含多个值,默认情况下选择最接近原点的值来确定距离。这可以通过设置 multi_value_mode 来改变。
multi_value_mode | 含义 |
---|---|
min | 距离取最小距离值 |
max | 距离取最大距离值 |
avg | 距离是所有距离的的平均值 |
sum | 距离是所有距离的总和 |
例子
"DECAY_FUNCTION": {
"FIELD_NAME": {
"origin": ...,
"scale": ...
},
"multi_value_mode": "avg"
}