Skip to main content

函数算分 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)"
}
}
}
}
}
tip

在 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

如果您希望分数可重复,可以提供seedfield。然后,将根据该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 是字段值
tip

field_value_score 函数产生的分数必须是非负数,否则将发出弃用警告。

注意,取 0 的 log() 或负数的平方根是非法操作,会抛出异常。一定要限制使用范围过滤器的字段值以避免这种情况,或使用 log1pln1p

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"
}