别人抄袭网站设计怎么办,vs2015做网站,有趣的网站网址之家,手机版电脑qq登录入口前言
Disjunction Max Query 又称最佳 best_fields 匹配策略#xff0c;用来优化当查询关键词出现在多个字段中#xff0c;以单个字段的最大评分作为文档的最终评分#xff0c;从而使得匹配结果更加合理
写入数据
如下的两条例子数据#xff1a;
docId: 1
title: java …前言
Disjunction Max Query 又称最佳 best_fields 匹配策略用来优化当查询关键词出现在多个字段中以单个字段的最大评分作为文档的最终评分从而使得匹配结果更加合理
写入数据
如下的两条例子数据
docId: 1
title: java python go
content: java scaladocId: 2
title: kubernetes docker
content: java spring python POST test01/doc/_bulk
{ index : { _id : 1 } }
{ title : kubernetes docker, content: java spring python }
{ index : { _id : 2 } }
{ title : java python go, content: java scala }
查询数据
GET test01/_search?
{query: {bool: {should: [{match: {title: java spring}},{match: {content: java spring}}]}}
}结果如下
{took : 2,timed_out : false,_shards : {total : 6,successful : 6,skipped : 0,failed : 0},hits : {total : 2,max_score : 0.5753642,hits : [{_index : test01,_type : doc,_id : 2,_score : 0.5753642,_source : {title : java python go,content : java scala}},{_index : test01,_type : doc,_id : 1,_score : 0.5753642,_source : {title : kubernetes docker,content : java spring python}}]}
}可以看到两个 doc 的 score 一样尽管从内容上看 id1 的 数据更应该排在前面但默认的排序策略是有可能会导致id2 的数据排在 id1 的前面。
原理分析
在 ES 的默认评分策略下boolean 查询的score是所有 should 条件匹配到的评分相加下面简化分析一下得分流程真实评分会比这个复杂但大致思路一致
在 id1 中数据由于 title 无命中但 content 匹配到了 2 个关键词所以得分为 2.
在 id2 中数据其 title 命中 1 个关键词 并且其 content 也命中一个关键词所以最后得分也为 2.
从而得出了最终结果两个 doc 的得分一样 dis_max 查询
使用 dis_max查询优化匹配机制采用单字段最大评分作为最终的 score
GET test01/_search?
{query: {dis_max: {queries: [{match: {title: java spring}},{match: {content: java spring}}]}}
}
结果如下
{took : 4,timed_out : false,_shards : {total : 6,successful : 6,skipped : 0,failed : 0},hits : {total : 2,max_score : 0.5753642,hits : [{_index : test01,_type : doc,_id : 1,_score : 0.5753642,_source : {title : kubernetes docker,content : java spring python}},{_index : test01,_type : doc,_id : 2,_score : 0.2876821,_source : {title : java python go,content : java scala}}]}
}结果已经符合预期了 tie_breaker参数
前面的结果我们看到已经符合预期了现在如果我们用 dis max 继续查询另一种 case GET test01/_search?
{query: {dis_max: {queries: [{match: {title: python scala}},{match: {content: python scala}}]}}
}结果如下
hits : [{_index : test01,_type : doc,_id : 2,_score : 0.2876821,_source : {title : java python go,content : java scala}},{_index : test01,_type : doc,_id : 1,_score : 0.2876821,_source : {title : kubernetes docker,content : java spring python}}]可以看到两者的评分又一样了但从实际来说我们肯定希望 id 2 的文档的得分更高的因为其在多个字段中都有命中但因为 dis max的匹配评分机制又导致忽略了其他字段的评分的贡献这个时候就需要进一步优化了在 dis max 里面可以使用 tie_breaker 参数来控制tie_breaker的值默认是 0 其设置了tie_breaker参数之后dis max 的工作原理如下
从得分最高的匹配子句中获取相关性得分。将任何其他匹配子句的分数乘以 tie_breaker 值。将最高分数和其他子句相乘的分数进行累加得到最终的排序 score 值。
改进后的查询语句如下
GET test01/_search?
{query: {dis_max: {queries: [{match: {title: python scala}},{match: {content: python scala}}],tie_breaker: 0.4}}
}
查询结果
hits : {total : 2,max_score : 0.40275493,hits : [{_index : test01,_type : doc,_id : 2,_score : 0.40275493,_source : {title : java python go,content : java scala}},{_index : test01,_type : doc,_id : 1,_score : 0.2876821,_source : {title : kubernetes docker,content : java spring python}}]}
这样结果就符合我们的预期了
总结
使用dis max 查询可以达到 best_fields 匹配的效果在某些细分的检索场景下效果更好但单纯的 dis max 查询会导致忽略其他字段评分贡献这种一刀切的机制并不是最优的策略所以需要配合 tie_breaker 参数来弱化非 best field 子句的评分贡献从而达到最终的优化效果