二十四、ElasticSearch的评分知识讲解
1、TF/IDF相关评分算法公式
score(q,d) =
queryNorm(q)
· coord(q,d)
· ∑ (
tf(t in d)
· idf(t)2
· t.getBoost()
· norm(t,d)
) (t in q)
score(q,d)
这个公式的最终结果,就是说是一个query(叫做q),对一个doc(叫做d)的最终的总评分
queryNorm(q)
是用来让一个doc的分数处于一个合理的区间内,不要太离谱,举个例子,一个doc分数是10000,一个doc分数是0.1,你们说好不好,肯定不好
coord(q,d)
简单来说,就是对更加匹配的doc,进行一些分数上的成倍的奖励
∑:求和的符号
∑ (t in q):
query中每个term对doc的分数,进行求和,多个term对一个doc的分数
2、对相关度评分进行调节和优化的常见的4种方法
(1)query-time boost(对查询的评分增加评分)
GET /forum/article/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"title": {
"query": "java spark",
"boost": 2
}
}
},
{
"match": {
"content": "java spark"
}
}
]
}
}
}
(2)、重构查询结构
GET /forum/article/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"content": "java"
}
},
{
"match": {
"content": "spark"
}
},
{
"bool": {
"should": [
{
"match": {
"content": "solution"
}
},
{
"match": {
"content": "beginner"
}
}
]
}
}
]
}
}
}
(3)、negative boost(降低不相关的值分数)
搜索包含java,不包含spark的doc,但是这样子很死板
搜索包含java,尽量不包含spark的doc,如果包含了spark,不会说排除掉这个doc,而是说将这个doc的分数降低
包含了negative term的doc,分数乘以negative boost,分数降低
以前写法:
GET /forum/article/_search
{
"query": {
"bool": {
"must": [
{"match": {
"content": "java"
}}
],
"must_not": [
{"match": {
"content": "solution"
}}
]
}
}
}
negative boost写法:
GET /forum/article/_search
{
"query": {
"boosting": {
"positive": {
"match": {
"content": "java"
}
},
"negative": {
"match": {
"content": "solution"
}
},
"negative_boost": 0.2
}
}
}
(4)、constant_score(不需要相关评分)
GET /forum/article/_search
{
"query": {
"bool": {
"should": [
{
"constant_score": {
"query": {
"match": {
"content": "java"
}
}
}
}
]
}
}
}
3、用function_score自定义相关度分数算法
GET /forum/article/_search
{
"query": {
"function_score": {
"query": {
"multi_match": {
"query": "java spark",
"fields": ["title","content"]
}
},
"field_value_factor": {
"field": "view_cnt",
"modifier": "log1p",
"factor": 1.2
},
"boost_mode": "sum",
"max_boost": 2
}
}
}
如果只有field,那么会将每个doc的分数都乘以view_cnt,如果有的doc follower是0,那么分数就会变为0,效果很不好。因此一般会加个log1p函数,公式会变为,new_score = old_score * log(1 + number_of_votes),这样出来的分数会比较合理
再加个factor,可以进一步影响分数,new_score = old_score * log(1 + factor * number_of_votes)
boost_mode,可以决定分数与指定字段的值如何计算,multiply,sum,min,max,replace
max_boost,限制计算出来的分数不要超过max_boost指定的值