PUT /my_index/my_type/1 { "title": "Quick brown rabbits", "body": "Brown rabbits are commonly seen." } PUT /my_index/my_type/2 { "title": "Keeping pets healthy", "body": "My quick brown fox eats rabbits on a regular basis." }
{ "query": { "bool": { "should": [ { "match": { "title": "Brown fox" }}, { "match": { "body": "Brown fox" }} ] } } }
{ "hits": [ { "_id": "1", "_score": 0.14809652, "_source": { "title": "Quick brown rabbits", "body": "Brown rabbits are commonly seen." } }, { "_id": "2", "_score": 0.09256032, "_source": { "title": "Keeping pets healthy", "body": "My quick brown fox eats rabbits on a regular basis." } } ] }
理论上 2 的文档实际上是咱们须要的,可是搜索的结果不是。要理解缘由,须要知道 bool 查询时如何计算获得其分值的:ui
should
子句中的两个查询文档1 在两个字段中都包含了 brown,所以两个 match 查询都匹配成功并拥有了一个分值。文档2 在 body 字段中包含了 brown 以及 fox,可是在 title 字段中没有出现任何搜索的单词。所以对 body 字段查询获得的高分加上对 title字段查询获得的零分,而后再乘以匹配的查询子句数量1,最后除以总的查询子句数量2,致使总体分值比文档1 的低。具体计算过程以下:spa
score_1 = (1 + 1) * 2 / 2 = 2 score_2 = (0 + 2) * 1 / 2 = 1
在这个例子中,title 和 body 字段是互相竞争的。咱们想要找到一个最佳匹配(Best-matching)的字段。
若是咱们不是合并来自每一个字段的分值,而是使用最佳匹配字段的分值做为整个查询的总体分值呢?这就会让包含有咱们寻找的两个单词的字段有更高的权重,而不是在不一样的字段中重复出现的相同单词。code
相比使用bool查询,咱们能够使用dis_max查询(Disjuction Max Query)。Disjuction的意思"OR"(而Conjunction的意思是"AND"),所以Disjuction Max Query的意思就是返回匹配了任何查询的文档,而且分值是产生了最佳匹配的查询所对应的分值:blog
{ "query": { "dis_max": { "queries": [ { "match": { "title": "Brown fox" }}, { "match": { "body": "Brown fox" }} ] } } }
它会产生咱们指望的结果:文档
{ "hits": [ { "_id": "2", "_score": 0.21509302, "_source": { "title": "Keeping pets healthy", "body": "My quick brown fox eats rabbits on a regular basis." } }, { "_id": "1", "_score": 0.12713557, "_source": { "title": "Quick brown rabbits", "body": "Brown rabbits are commonly seen." } } ] }
若是用户搜索的是"quick pets",那么会发生什么呢?两份文档都包含了单词 quick
,可是只有文档2 包含了单词 pets
。两份文档都没能在一个字段中同时包含搜索的两个单词。it
一个像下面那样的简单 dis_max
查询会选择出拥有最佳匹配字段的查询子句,而忽略其余的查询子句:io
查询语句: { "query": { "dis_max": { "queries": [ { "match": { "title": "Quick pets" }}, { "match": { "body": "Quick pets" }} ] } } } 获得的结果: { "hits": [ { "_id": "1", "_score": 0.12713557, "_source": { "title": "Quick brown rabbits", "body": "Brown rabbits are commonly seen." } }, { "_id": "2", "_score": 0.12713557, "_source": { "title": "Keeping pets healthy", "body": "My quick brown fox eats rabbits on a regular basis." } } ] }
能够发现,两份文档的分值是如出一辙的。class
咱们指望的是同时匹配了title
字段 和 body
字段 的文档可以拥有更高的排名,可是结果并不是如此。须要记住:dis_max
查询只是简单的使用最佳匹配查询子句获得的_score
。搜索
可是,将其它匹配的查询子句考虑进来也是可能的。经过指定tie_breaker
参数:数据
查询语句: { "query": { "dis_max": { "queries": [ { "match": { "title": "Quick pets" }}, { "match": { "body": "Quick pets" }} ], "tie_breaker": 0.3 } } } 它会返回如下结果: { "hits": [ { "_id": "2", "_score": 0.14757764, "_source": { "title": "Keeping pets healthy", "body": "My quick brown fox eats rabbits on a regular basis." } }, { "_id": "1", "_score": 0.124275915, "_source": { "title": "Quick brown rabbits", "body": "Brown rabbits are commonly seen." } } ] }
如今文档2 的分值比文档1 稍高一些。
tie_breaker参数会让dis_max查询的行为更像是dis_max和bool的一种折中。它会经过下面的方式改变分值计算过程:
1. 取得最佳匹配查询子句的_score。
2. 将其它每一个匹配的子句的分值乘以tie_breaker。
3. 将以上获得的分值进行累加并规范化。
经过tie_breaker参数,全部匹配的子句都会起做用,只不过最佳匹配子句的做用更大。