relevance score(相关性得分)
TF/IDF
- TF(term frequency): 关键词在每个doc中出现的次数
- IDF(inverse doc frequency): 关键词在整个索引中出现的次数
计算规则
TF数值大的得分较高,因为关键词在一个文档出现的次数多,证明该文档的相关性更大
IDF数值大的得分较低,关键词在整个倒排索引中出现的次数越多,关联的文档越多,证明其相关越低
relevance score(相关性得分):每个query的分数,乘以matched query数量,除以总query数量
- 它会执行 should 语句中的两个查询。
- 两个查询的评分相加。
- 乘以匹配语句的总数。
- 除以所有语句总数
例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| {"match": {"name": "吃鸡手机"}}, doc1: 吃鸡1次,手机1次,计2分 doc2: 吃鸡0次,手机1次,计1分 doc3: 吃鸡0次,手机1次,计1分 {"match": {"desc": "吃鸡手机"}} doc1: 吃鸡0次,手机0次,计0分 doc2: 吃鸡0次,手机1次,计1分 doc3: 吃鸡0次,手机1次,计1分 总分:(query1分数+query2分数)*matched query / total query
doc1: query1+query2:2 matched:1 total query:2 result:2*1/2=1 doc2: query1+query2:2 matched:2 total query:2 result:2*2/2=2 doc3: query1+query2:2 matched:2 total query:2 result:2*2/2=2 matched query数量 = 2 总query数量 = 2
|
总结:总分 =(query1分数+query2分数)*matched query / total query
shard local idf和global idf
es的每个shard只保存一部分的doc数据,当我们的查询路由到某个shard上进行查询时,只在该shard上计算idf,即shard local idf;如果不同的shard存在的文档数量不同,出现不同的shard local idf,在差距较大的情况下会影响分值的计算,影响排序结果。
解决:
- 一般来说,生产环境下,数据量大时尽可能实现均匀分配,一定程度是哪个避免多个shard之间出现shard local idf差距过大的情况
- 搜索附带
search_type=dfs_query_then_fetch参数,当计算一个doc的相关度分数的时候,就会将所有shard对应的local IDF获取出来,在本地进行global IDF分数的计算,所有shard的doc作为上下文来进行计算确保准确性,生产环境下,不推荐这个参数,因为性能很差。
排序规则优化
dix_max
Disjunction Max Query,将任何与任一查询匹配的文档作为结果返回,但只将最佳匹配的评分作为查询的评分结果返回 。
tie_breaker:取值范围 [0,1],其中 0 代表使用 dis_max 最佳匹配语句的普通逻辑,1表示所有匹配语句同等重要。最佳的精确值需要根据数据与查询调试得出,但是合理值应该与零接近(处于 0.1 - 0.4 之间),这样就不会颠覆 dis_max 最佳匹配性质的根本。
boost:设置分值比例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| #查询匹配的文档,被更多term命中的feild查询语句作为查询评分结果(默认使用best_fields) GET product/_search { "query": { "dis_max": { "queries": [ {"match": {"name": "超级快充"}}, {"match": {"desc": "超级快充"}} ] } } }
GET product/_search { "query": { "dis_max": { "queries": [ {"match": {"name": "超级快充"}}, {"match": {"desc": "超级快充"}} ], "boost": 2.0, "tie_breaker": 0.7 } } }
|
multi_match
type属性
best_fields(默认)
多个字段进行查询匹配时,返回评分最高的字段评分作为查询结果。类似:dis_max query。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| POST product/_search { "query": { "multi_match": { "type": "best_fields", "query": "超级快充", "fields": [ "name", "desc" ], "tie_breaker": 0.2 } } #dis_max query查询与上述best_fields等价 POST product/_search { "query": { "dis_max": { "queries": [ { "match": { "name": "超级快充" } }, { "match": { "desc": "超级快充" } } ], "tie_breaker": 0.2 } } }
|
most_fields
多个字段进行查询匹配时,多个字段的评分一起参与计算,返回的综合评分(非最高分)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| GET /product/_search { "query": { "multi_match": { "query": "超级快充", "type": "most_fields", "fields": [ "name^10", "desc" ] } } }
#与上面的most_fields等价 GET product/_search { "query": { "bool": { "should": [ { "match": { "name": { "query": "超级快充", "boost": 10 } } }, { "match": { "desc": "超级快充" } } ] } } }
|
cross_fields
跨字段匹配与operator指令结合操作。
1 2 3 4 5 6 7 8 9 10 11 12 13
| #查询的关键词的term必须在name and desc中出现 #例如,超级必须在name或desc中出现 and 快充必须在name或desc中出现 GET product/_search { "query": { "multi_match" : { "query": "超级 快充", "type": "cross_fields", "fields": [ "name", "desc" ], "operator": "and" } } }
|
function_score
必须定义一个查询和一个或多个函数,自定义函数会为查询返回的每个文档计算一个新分数
field:要计算的字段
factor:当前分数计算,对整个结果产生的权重比
modifier:以何种运算方式计算,接受以下枚举
- none:不处理
- log:计算对数
- log1p:先将字段值 +1,再计算对数
- log2p:先将字段值 +2,再计算对数
- ln:计算自然对数
- ln1p:先将字段值 +1,再计算自然对数
- ln2p:先将字段值 +2,再计算自然对数
- square:计算平方
- sqrt:计算平方根
- reciprocal:计算倒数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| #默认分值与指定field字段数值相乘得出分数、根据modifier指定的运算方式处理、factor权重比、max_boost表示最大的分值、boost_mode指定计算后的分数与原始的_score如何合并 GET /person/_search { "query": { "function_score": { "query": { "match_all": {} }, "field_value_factor": { "field": "age", "modifier": "none", "factor": 1.2 }, "max_boost": 10, "boost_mode": "multiply" } } }
|
boost_mode:指定计算后的分数与原始的_score如何合并,有以下选
multiply:查询分数和函数分数相乘
sum:查询分数和函数分数相加
avg:取平均值
replace:替换原始分数
min:取查询分数和函数分数的最小值
max:取查询分数和函数分数的最大值
script_score:通过自定义脚本计算分值
max_boost:分数上限
random_score:随机得到 0 到 1 分数
term vectors-term向量指标
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| #查询指定内容对应字段的文档term向量指标 GET /test_vector/_termvectors { "doc": { "content":"you can kill" }, "offsets": true, "payloads": true, "positions": true, "term_statistics": true, "field_statistics": true } #查询指定字段的文档term向量指标 GET /test_vector/_termvectors/1 { "fields": ["content"], "offsets": true, "payloads": true, "positions": true, "term_statistics": true, "field_statistics": true }
|