
自定义评分检索
- 1.自定义评分
- 2.为什么需要自定义评分
- 3.搜索结果相关度
- 4.影响相关度评分的查询子句
- 5.控制相关度评分的方法
-
- [5.1 Function Score Query](#5.1 Function Score Query)
-
- [5.1.1 基础查询部分](#5.1.1 基础查询部分)
- [5.1.2 评分函数部分(functions 数组)](#5.1.2 评分函数部分(functions 数组))
- [5.1.3 评分组合方式](#5.1.3 评分组合方式)
- [5.1.4 整体效果](#5.1.4 整体效果)
- [5.2 使用 Boosting Query](#5.2 使用 Boosting Query)
-
- [5.2.1 正向查询(positive)](#5.2.1 正向查询(positive))
- [5.2.2 负向查询(negative)](#5.2.2 负向查询(negative))
- [5.2.3 降权系数(negative_boost)](#5.2.3 降权系数(negative_boost))
- [5.3.4 工作流程](#5.3.4 工作流程)
- [5.2.5 与 bool 查询的区别](#5.2.5 与 bool 查询的区别)
- [5.2.6 典型应用场景](#5.2.6 典型应用场景)
- [5.2.7 参数注意事项](#5.2.7 参数注意事项)
- [5.2.8 性能考虑](#5.2.8 性能考虑)
- [5.3 使用 Script Score](#5.3 使用 Script Score)
- 6.相关度评分控制技巧
1.自定义评分
自定义评分(Score Customization
)是指通过编程方式修改或覆盖 Elasticsearch 默认的相关度评分算法,以满足特定业务需求的过程。
Elasticsearch 默认使用 TF-IDF
(在较新版本中使用 BM25
)算法计算文档相关性,但有时业务需求需要特殊的排序逻辑。
🚀 建议先看一下我的这几篇博文:
2.为什么需要自定义评分
- 业务特定需求:默认评分可能无法准确反映业务领域的相关性标准。
- 个性化排序:根据用户偏好、地理位置、时间敏感性等因素调整结果。
- 商业逻辑:如提升付费内容、促销商品的排名。
- 多维度排序:结合相关性、销量、评分、新鲜度等多个因素。
- 领域专业知识:某些领域有独特的价值评估标准。
3.搜索结果相关度
- 相关度(
_score
)是 Elasticsearch 判断文档与查询匹配程度的量化值。 - 自定义评分 不是替代相关度计算 ,而是在其基础上进行 调整或补充。
- 最终排序可以结合默认相关度和自定义评分因素。
4.影响相关度评分的查询子句
- 全文检索查询 :
match
、match_phrase
、multi_match
、query_string
- 词项级别查询 :
term
(通常不评分,但可通过参数启用)、terms
、fuzzy
- 复合查询 :
bool
(must
/should
)、dis_max
、constant_score
- 特殊查询 :
boosting
、function_score
、script_score
- 查询参数 :
boost
(可应用于任何查询)、tie_breaker
(在dis_max
中使用)
filter
和 must_not
被视为过滤器,不影响评分。其他查询子句会影响评分。
5.控制相关度评分的方法
接下来,我们就介绍一下 boosting
、function_score
、script_score
这几个特殊查询是如何影响评分的。
5.1 Function Score Query
json
{
"query": {
"function_score": {
"query": { "match": { "title": "手机" } },
"functions": [
{
"filter": { "term": { "brand": "苹果" } },
"weight": 2
},
{
"field_value_factor": {
"field": "sales",
"modifier": "log1p",
"factor": 0.1
}
},
{
"gauss": {
"date": {
"origin": "now",
"scale": "30d",
"offset": "7d",
"decay": 0.5
}
}
}
],
"score_mode": "sum",
"boost_mode": "multiply"
}
}
}
这段代码是一个 Elasticsearch 的 function_score
查询,用于对基础查询结果进行自定义评分调整。这是一个复合查询,主要包含:
- 基础查询(
match
查询) - 多个评分函数(
functions
数组) - 评分组合方式(
score_mode
和boost_mode
)
5.1.1 基础查询部分
json
"query": { "match": { "title": "手机" } }
- 这是基础查询,查找
title
字段包含 "手机
" 的文档。 - 这部分会先执行,产生初始的相关性评分(
_score
)。
5.1.2 评分函数部分(functions 数组)
第一个函数:品牌加权
json
{
"filter": { "term": { "brand": "苹果" } },
"weight": 2
}
- 作用 :对品牌为 "
苹果
" 的文档应用权重。 - 机制 :
- 先过滤出
brand
字段精确匹配 "苹果
" 的文档。 - 为这些文档的评分乘以权重因子 2。
- 先过滤出
- 效果:苹果品牌的产品会获得更高的排名。
第二个函数:销量因子
json
{
"field_value_factor": {
"field": "sales",
"modifier": "log1p",
"factor": 0.1
}
}
- 作用 :根据销量(
sales
字段)调整评分。 - 参数 :
field
:使用sales
字段的值。modifier
:应用log1p
函数(即log(1 + sales)
),防止极高销量值对评分影响过大。factor
:乘以0.1
的因子,减小影响程度。
- 效果:销量高的产品会获得一定提升,但不会完全主导排序。
第三个函数:时间衰减
json
{
"gauss": {
"date": {
"origin": "now",
"scale": "30d",
"offset": "7d",
"decay": 0.5
}
}
}
- 作用 :基于日期字段(
date
)实现时间衰减评分。 - 高斯衰减参数 :
origin
:当前时间("now"
)作为基准点。scale
:衰减范围为 30 30 30 天。offset
: 7 7 7 天内不衰减,保持完整评分。decay
:衰减到 0.5 0.5 0.5(在origin
+offset
+scale
时,得分为0.5*原始分
)。
- 效果 :较新的文档会获得更高评分,但 7 7 7 天内无差别,之后逐渐衰减。
5.1.3 评分组合方式
score_mode
json
"score_mode": "sum"
- 指定多个函数评分如何组合。
sum
表示将所有函数评分相加。- 其他可选值:
multiply
(乘 )、avg
(平均 )、max
(最大 )、min
(最小 )、first
(第一个函数)。
boost_mode
json
"boost_mode": "multiply"
- 指定函数评分如何与原始查询评分组合。
multiply
表示将函数评分与原始_score
相乘。- 其他可选值:
replace
(替换 )、sum
(相加 )、avg
(平均 )、max
(最大 )、min
(最小)。
5.1.4 整体效果
这个查询会:
- 首先找出所有标题包含 "
手机
" 的文档。 - 然后对这些文档进行评分调整:
- 如果是
苹果
品牌,评分×2
。 - 根据销量(
取对数后
)增加评分。 - 根据时间远近衰减评分(越新评分越高)。
- 如果是
- 将所有函数评分相加(
score_mode: sum
)。 - 最后将总函数评分与原始评分相乘(
boost_mode: multiply
)。 - 按最终评分排序返回结果。
这种查询非常适合电商搜索场景,可以同时考虑关键词相关性、品牌偏好、销量热度和新品时效性。
5.2 使用 Boosting Query
json
{
"query": {
"boosting": {
"positive": { "match": { "title": "手机" } },
"negative": { "term": { "brand": "山寨" } },
"negative_boost": 0.2
}
}
}
这段代码使用了 Elasticsearch 的 boosting
查询,它是一种特殊的复合查询,用于对匹配某些条件的文档进行降权而非完全排除。下面我将详细解释每个部分的含义和作用:
positive
:正向查询(必须匹配)negative
:负向查询(匹配则降权)negative_boost
:降权系数
5.2.1 正向查询(positive)
json
"positive": { "match": { "title": "手机" } }
- 这是一个标准的全文匹配查询。
- 会找出所有
title
字段包含 "手机
" 的文档。 - 这些文档都会被包含在最终结果中 (如果不匹配
negative
条件则保持原评分)。
5.2.2 负向查询(negative)
json
"negative": { "term": { "brand": "山寨" } }
- 这是一个精确匹配查询(
term query
)。 - 会找出
brand
字段精确等于 "山寨
" 的文档。 - 匹配
negative
查询的文档不会被排除,而是会被降权。
5.2.3 降权系数(negative_boost)
json
"negative_boost": 0.2
- 这是一个介于 0 0 0 和 1 1 1 之间的乘数因子。
- 对于 同时匹配 positive 和 negative 的文档:
最终评分 = 原始评分 × 0.2
- 对于 只匹配 positive 的文档:
保持原始评分不变
5.3.4 工作流程
- 首先执行
positive
查询,找出所有标题包含 "手机
" 的文档。 - 然后在这些文档中,找出品牌为 "
山寨
" 的文档。 - 对匹配
negative
条件的文档,将其评分乘以0.2
。 - 最后按调整后的评分排序返回结果。
5.2.5 与 bool 查询的区别
特性 | boosting 查询 | bool 查询( must_not ) |
---|---|---|
匹配 negative 的文档 |
仍会返回,但评分降低 | 完全排除 |
适用场景 | 需要展示但降权低质量内容 | 需要完全排除某些内容 |
评分影响 | 可控的降权(通过 negative_boost ) |
完全不影响评分(只是过滤) |
5.2.6 典型应用场景
- 降权低质量内容:如示例中的山寨品牌。
- 处理过时内容:降权旧文章但不完全排除。
- 广告混合排序:对广告内容适当降权。
- 用户偏好处理:对用户不喜欢的类型降权。
5.2.7 参数注意事项
-
negative_boost
必须是 0 0 0 到 1 1 1 之间的浮点数:- 0.2 0.2 0.2 表示降权到原评分的 20 % 20\% 20%。
- 1.0 1.0 1.0 相当于没有效果。
- 0.0 0.0 0.0 相当于完全排除(此时应使用
bool
+must_not
)。
-
可以组合多个
positive
和negative
条件:json"positive": { "bool": { "should": [ { "match": { "title": "手机" } }, { "match": { "description": "智能" } } ] } }, "negative": { "bool": { "should": [ { "term": { "brand": "山寨" } }, { "range": { "price": { "lt": 100 } } } ] } }
5.2.8 性能考虑
- 比纯过滤(
bool
+must_not
)消耗更多资源,因为要计算被降权文档的评分。 - 对于需要完全排除的大量文档,建议使用
bool
+must_not
过滤。 - 适合处理少量需要降权而非完全排除的文档。
5.3 使用 Script Score
json
{
"query": {
"script_score": {
"query": { "match": { "title": "手机" } },
"script": {
"source": "_score * doc['popularity'].value * params.weight",
"params": { "weight": 1.5 }
}
}
}
}
- 首先执行基础
match
查询,找出所有标题包含 "手机
" 的文档,并计算原始_score
。 - 对每个匹配的文档:
- 获取其
popularity
字段的值。 - 使用脚本计算新评分:
新评分 = _score × popularity × 1.5
。
- 获取其
- 按照计算出的新评分对文档进行排序。
- 返回结果。
6.相关度评分控制技巧
-
理解评分因素
- 词频(
Term Frequency
) - 逆文档频率(
Inverse Document Frequency
) - 字段长度归一值(
Field-length norm
)
- 词频(
-
使用 Explain API 分析评分
jsonGET /products/_search { "explain": true, "query": { "match": { "title": "手机" } } }
-
调整相似度算法
- 可配置 BM25 参数(
k1
,b
)。 - 或完全自定义相似度实现。
- 可配置 BM25 参数(
-
查询结构调整
- 合理使用
bool
查询的should
/must
/filter
。 - 调整不同子句的
boost
值。
- 合理使用
自定义评分是 Elasticsearch 强大的功能之一,合理使用可以显著提升搜索体验,但也需要谨慎设计以避免性能问题和不可预期的排序结果。