当需要对同一个字符串在多个字段中进行查询时,用bool查询在算分时会对多个查询结果的算分进行平均,而实际上有可能我们需要的是最匹配的那个字段对应的那条记录,这个时候就可以用到disjunciton max query 了。
一,插入演示数据
PUT dis_max_index/_bulk
{"index":{"_id":1}}
{"title":"apple key", "name":"i like iphone"}
{"index":{"_id":2}}
{"title":"2 key", "name":"i like apple iphone"}
二,bool查询
需求是查询title和name中apple iphone匹配度最高的文档,明显第二个文档匹配度更高,但查询的结果是两个文档评分相同,原因就在于bool查询会把多个字段的查询结果进行综合算分。
第一个文档的title字段中能匹配到apple,name字段中能匹配到iphone,匹配词数为2。
第二个文档title中未匹配到,name中匹配到apple iphone,匹配词数也是2。
最后进行综合评分,两个文档的评分一致,实际上需要是要匹配到第二个文档。
GET dis_max_index/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"name": "apple iphone"
}
},
{
"match": {
"title":"apple iphone"
}
}
]
}
}
}
三,disjunction max query
dis max 会将单个字段查询匹配最高的那个文档首先查询出来。
GET dis_max_index/_search
{
"query": {
"dis_max": {
"boost": 1.2,
"queries": [
{
"match": {
"name": "apple iphone"
}
},
{
"match": {
"title": "apple iphone"
}
}
]
}
}
}
也可以用multi_match的best field模式,得出的结果是一样的。
GET dis_max_index/_search
{
"query": {
"multi_match" : {
"query": "apple iphone",
"fields": [ "title", "name" ]
}
}
}
二者的区别在于,dis_max查询可以自动找出得分最高的字段对应的文档,并用tie breaker将得分其次的按照一定的权重进入算分,这个权重是针对结果的,而不是针对某个字段的,是后知的。
mutli_match可以给指定字段加权重,是先知的。
四,disjunction max query 之tie breaker
还有一种情况就是虽然使用了dis max,但两个文档的评分还是一样,这个时候就可以将另外一个字段的加入算分过程,使用tie_breaker设置非最高匹配字段的权重。
测试数据:
PUT dis_max_index/_bulk
{"index":{"_id":3}}
{"title":"good key", "name":"i like iphone"}
{"index":{"_id":4}}
{"title":"good key", "name":"i like china iphone"}
在下面的查询中,本来good key能匹配到两个文档,而且评分是一样的,但由于我们添加了tie_breaker参数,会将另外的非最高匹配字段加入算分,因为第二个文档name匹配到了china,所以第二个文档综合算分比较高。
GET dis_max_index/_search
{
"query": {
"dis_max": {
"tie_breaker": 0.1,
"boost": 1.2,
"queries": [
{"match":{"title":"good key"}},
{"match":{"name":"china"}}
]
}
}
}