Elasticsearch function score query 自定义相关性得分
Elasticsearch function score query 得分方程查询
摘要
function_score将允许您修改由系统计算的匹配文档的相关性得分。例如,如果分数函数在计算上很费时,并且足以在过滤后的文档集上计算分数,则此功能很有用。
用户必须声明一个匹配项、一个或多个方程,这些函数为查询返回的每个文档计算一个新分数。
请求参数
函数名 |
score_mode 参数 |
boost_mode 参数 |
---|---|---|
max | 使用最高分 | 查询分数和功能分数的最大值 |
replace | 仅使用功能分数,查询分数将被忽略 | |
first | 具有匹配过滤器的第一个函数被应用 | |
multiply | 分数相乘(默认) | 查询分数和功能分数相乘(默认) |
avg | 分数是平均值 | 平均 |
sum | 分数相加 | 查询分数和功能分数相加 |
min | 使用最低分数 | 查询分数和功能分数的最小值 |
首先,通过定义的方程对每个文档评分。score_mode
指定如何组合计算出的分数。
由于分数可以处于不同的等级,并且由于有时希望函数对分数有不同的影响,因此可以使用用户定义的权重weight
来调整每个函数的分数。可以为每一个函数设置相应的权重,乘以相应的函数计算分数。如果没有其他任何函数声明的情况下给出权重,则权重充当仅返回权重的函数(lambda weight: weight
)。
如果"score_mode":"avg"
,则相关性得分是各个相关性得分的加权平均数。例如,如果两个函数返回得分1和2以及它们各自的权重是3和4,那么他们的分数将被组合为 (1*3+2*4)/(3+4)
而不是 (13+24)/2。
通过设置max_boost
参数,可以将计算得到的分数设置为不超过设定值。默认值为FLT_MAX
该参数boost_mode
定义,新计算的分数与查询分数合并。
默认情况下,修改分数不会更改匹配的文档。要排除不符合特定分数阈值的文档,min_score
可以将参数设置为所需分数阈值。意思是说,文档得分小于min_score
设定值的话,会被过滤掉。
score functions 计算分数的函数
script score 脚本函数
weight 权重
这种方程,是将原来的分数乘以权重,得到新的分数。
random 随机
random_score
,随机产生0,1
之间的值。默认情况下,它采用内部的Lucene的文档ID作为随机种子,这是非常有效的,但不幸的是不可再现的,因为文档可能通过合并重新编号分数。
如果你希望分数是可以复制的,可以提供seed和field。然后基于种子,所考虑文档的field的最小值,另外根据索引名称和分片ID计算的盐来计算最终分数,以便具有相同值的但存储在不同索引中的文档得到不同的结果分数。请注意,位于相同分片内具有相同的文档将获得相同的分数,因此通常希望使用对所有文档都具有唯一值的字段。一个好的默认选择是使用_seq_no字段,其唯一的缺点是,如果文档被更新,则分数会改变,因此更新操作也会更新_seq_no字段的值。
可以在不设置字段的情况下设置种子,但是已弃用该方法,因为这需要在_id
消耗大量内存的字段上加载字段数据。
Field Value factor
这个field_value_factor
方程允许您使用文档中的字段来影响得分。它类似于使用该script_score
函数,但是它避免了脚本编写的开销。如果用于多值字段,则在计算中仅使用该字段的第一个值。
例如,假设您有一个用数字likes
字段索引的文档,并希望通过该字段影响文档的分数,则示例如下所示:
下列命令等价于:sqrt(1.2 * doc['likes'].value)
GET /_search
{
"query": {
"function_score": {
"field_value_factor": {
"field": "likes",
"factor": 1.2,
"modifier": "sqrt",
"missing": 1
}
}
}
}
field_value_factor
有许多选项:
参数 | 含义 |
---|---|
modifier | 修改适用于该字段的值,可以是一个:none,log, log1p,log2p,ln,ln1p,ln2p,square,sqrt,或reciprocal。默认为none。 |
field | 要从文档中提取的字段。 |
factor | 字段值乘以的可选因子,默认为1。 |
修饰符 | 含义 |
---|---|
ln | 取字段值的自然对数。因为此函数将返回负值,并且如果将其用于0到1之间的值,则会导致错误,因此建议改用它ln1p。 |
reciprocal | 报答字段值,同1/x那里x是该字段的值 |
log1p | 将1加到字段值并取对数 |
sqrt | 取字段值的平方根 |
square | 对字段值求平方(乘以它本身) |
log | 取字段值的常用对数。因为此函数将返回负值,并且如果将其用于0到1之间的值,则会导致错误,因此建议改用它log1p。 |
ln1p | 将1加到栏位值并取自然对数 |
ln2p | 将2加到字段值上并取自然对数 |
log2p | 在字段值上加2并取公共对数 |
none | 不要对字段值应用任何乘数 |
missing
参数,如果文档没有指定的字段,则使用这个值。就像从文档中读取一样,修饰符和因数任然使用于它。
该field_value_score
函数产生的分数必须为非负数,否则将引发错误。的log
和ln
如果在所使用的值0和1之间一定要限制的字段的值与一系列过滤器,以避免这种情况,或使用改性剂会产生负值log1p和 ln1p。
请记住,将log()
设为0或负数的平方根是非法操作,并且将引发异常。为避免这种情况,请务必使用范围过滤器限制该字段的值,或使用 log1p
和ln1p
。
Decay function 衰减功能
衰减函数对文档进行评分,该函数的衰减取决于文档的数字字段值与用户给定原点的距离。这类似于范围查询,但具有平滑的边缘而不是框。
要在具有数字字段的查询上使用距离记分,用户必须为每个字段定义一个origin和scale。origin来定义从中心计算距离的“中心点”,scale来声明衰减率。
如果文档中缺少数字字段,该函数将返回1。
-
DECAY_FUNCTION
取值:linear
、exp
或gauss
-
FIELD_NAME
类型:数字,日期,地理位置
参数 | 含义 |
---|---|
origin | 用于计算距离的原点。对于数字字段,必须指定为数字;对于日期字段,必须指定为日期;对于地理字段,必须指定为地理点。地理位置和数字字段必填。对于日期字段,默认值为now 。原点支持日期数学(例如now-1h )。 |
decay | 该decay 参数定义如何在处给定的距离处对文档进行评分scale 。如果decay 未定义,则远处的文档 scale 得分为0.5。 |
offset | 如果offset 定义了,衰减函数将仅计算距离大于定义的文档的衰减函数 offset 。默认值为0。 |
scale | 所有类型均必需。定义到原点的距离+偏移,计算出的分数将等于该距离decay 。对于地理字段:可以定义为数字+单位(1km,12m,…)。默认单位是米。对于日期字段:可以定义为数字+单位(“ 1h”,“ 10d”,…。)。默认单位是毫秒。对于数字字段:任何数字。 |
DECAY_FUNCTION参数
参数 | 含义 |
---|---|
gauss | 正常衰减 |
exp | 指数衰减 |
linear | 线性衰减 |
如果用于计算衰减的字段包含多个值,则默认情况下将选择最接近原点的只来确定距离。用multi_value_mode来定义
参数值 | 含义 |
---|---|
min | 距离是最小距离 |
max | 距离是最大距离 |
sum | 距离是所有距离的总和 |
avg | 距离是平均距离 |
"DECAY_FUNCTION": {
"FIELD_NAME": {
"origin": "11, 12",
"scale": "2km",
"offset": "0km",
"decay": 0.33
},
"multi_value_mode": "avg"
}
使用场景
单个功能
GET /_search
{
"query": {
"function_score": {
"query": { "match_all": {} },
"boost": "5",
"random_score": {},
"boost_mode":"multiply"
}
}
}
组合几个功能
可以组合几个功能。在这种情况下,可以选择仅在文档与给定的过滤查询匹配时才应用功能
每个函数的过滤查询所产生的分数并不重要。
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
}
}
}
衰减功能使用示例
假设您正在寻找某个城镇的酒店。您的预算有限。另外,您希望酒店离市中心很近,因此酒店距离理想位置越远,您入住的可能性就越小。
您希望根据距市中心的距离以及价格来对与您的条件相匹配的查询结果(例如“酒店,南希,不吸烟者”)进行评分。
直观地讲,您想将市中心定义为起点,也许您愿意从酒店步行2公里到市中心。
在这种情况下,您的位置字段的来源为镇中心,范围为〜2km。
如果您的预算低,您可能更喜欢便宜的东西而不是昂贵的东西。对于价格字段,原点为0欧元,小数位数取决于您愿意支付的金额,例如20欧元。
在此示例中,字段可能被称为“价格”作为酒店价格,而“位置”则称为该酒店的坐标。
价格:
"gauss": {
"price": {
"origin": "0",
"scale": "20"
}
}
位置:
"gauss": {
"location": {
"origin": "11, 12",
"scale": "2km"
}
}
请求示例
GET /_search
{
"query": {
"function_score": {
"functions": [
{
"gauss": {
"price": {
"origin": "0",
"scale": "20"
}
}
},
{
"gauss": {
"location": {
"origin": "11, 12",
"scale": "2km"
}
}
}
],
"query": {
"match": {
"properties": "balcony"
}
},
"score_mode": "multiply"
}
}
}