现实的查询需求从来都没有那么简单;他们需要在多个字段上查询多种多样的文本,并且根据一系列的标准来过滤。为了构建类似的高级查询,你需要一种能够将多查询组合成单一查询的查询方法。
你可以用bool 查询来实现你的需求。这种查询将多查询组合在一起,成为用户自己想要的布尔查询。他接收以下参数:
must
must_not
should
如果满足这些语句中的任意语句,将增加_source,否则,无任何影响。他们主要用于修正每个文档的相关性得分。
filter
必须匹配,但他以不评分、过滤模式来进行。这些语句对评分没有贡献,只是根据过滤标准来排除或包含文档。
由于这是我们看到的第一个包含多个查询的查询,所以有必要讨论一下相关性得分是如何组合的。每一个子查询都独自的计算文档的相关性得分。一旦他们的得分被计算出来,bool 查询就将这些得分进行合并并且返回一个代表整个布尔操作的得分。
下面的查询用于查找title 字段匹配 how ti make millions 并且不被标识为spam 的文档。那些被标识为starred 或在2014之后的文档,将比另外那些文档拥有更高的排名。如果两者 都满足,那么他排名将更高:
{"bool": {"must": { "match": { "title": "how to make millions" }},"must_not": { "match": { "tag": "spam" }},"should": [{ "match": { "tag": "starred" }},{ "range": { "date": { "gte": "2014-01-01" }}}]}}
TIP
如果没有must 语句,那么至少需要能够匹配其中的一条 should语句。但,如果存在至少一条must 语句,则对 should 语句的匹配没有要求。
增加带过滤器(filtering)的查询
如果我们不想因为文档的时间而影响得分,可以用 filter 语句来重写前面的例子;
{"bool": {"must": { "match": { "title": "how to make millions" }},"must_not": { "match": { "tag": "spam" }},"should": [{ "match": { "tag": "starred" }}],"filter": {"range": { "date": { "gte": "2014-01-01" }} 1}}}
- range 查询已经从 should 语句中移到filter 语句
通过将range 查询移到 filter 语句中,我们将它转成不评分的查询,将不再影响文档的相关性排名。由于他现在是一个不评分的查询,可以使用各种对 filter 查询有效的优化手段来提升性能。
所有查询都可以借鉴这种方式。将查询移到bool 查询的filter 语句中,这样他就自动的转成一个不评分的filter 了。
如果你需要通过多个不同标准来过滤你的文档,bool 查询本身也可以被用做不评分的查询。简单的将它放置到filter 语句中并在内部构建布尔逻辑:
{"bool": {"must": { "match": { "title": "how to make millions" }},"must_not": { "match": { "tag": "spam" }},"should": [{ "match": { "tag": "starred" }}],"filter": {"bool": { 1"must": [{ "range": { "date": { "gte": "2014-01-01" }}},{ "range": { "price": { "lte": 29.99 }}}],"must_not": [{ "term": { "category": "ebooks" }}]}}}}
- 将bool 查询包裹在filter 语句中,我们可以在过滤标准中增加布尔逻辑。
通过混合布尔查询,我们可以在我们的查询请求中灵活的编写scoring 和filtering 查询逻辑。
constant_score查询
尽管没有bool 查询使用这么频繁,constant_score 查询也是你工具箱里有用的查询工具。他将一个不变的常量评分应用于所有匹配的文档。他被经常用于你只需要执行一个filter 而没有其他查询(例如,评分查询)的情况下。
可以使用他来取代只有filter 语句的bool查询。在性能上是完全相同的,但对于提高查询简洁性和清晰度有很大帮助。
{"constant_score": {"filter": {"term": { "category": "ebooks" } 1}}}
- term 查询被放置在constant_score 中,转成不评分的filter。这种方式可以用来取代只有filter 语句的bool 查询。
