布尔查询
Elasticsearch支持类似于在SQL中使用AND
、OR
以及NOT
的运算(在MySQL中仅支持部分语句使用NOT
运算符,例如IN
运算等,在这里我们也可以理解为使用相反的运算符),称之为布尔查询(Boolean Query)。Elasticsearch支持的布尔逻辑类型包括有以下几种:
must
:文档必须符合其中所有的查询条件,包含多个条件时类似于SQL中的AND
。should
:文档必须符合其中任意一个及以上查询条件(可由minimum_should_match
指定需要满足的条件数量),包含多个条件时类似于SQL中的OR
。must_not
:文档必须不符合其中所有的查询条件,类似于SQL中的NOT
,且返回的结果的分值都为0
。filter
:效果与使用must
相同,但不影响查询结果的分值(score)。
在使用布尔查询时,需要将查询的条件写在bool
查询语句中,且同个bool
查询语句可以有多个不同的条件。
{
"query": {
"bool": {
"must": {
"term": {
"age": 20
}
},
"must_not": {
"term": {
"gender": "male"
}
}
}
}
}
例如该查询运行后,将返回age
的值为20
且gender
的值不为"male"
的文档。
下面,我们将介绍上述各个类型查询语句在DSL(Domain Specific Language,即Elasticsearch使用的结构化查询语言)的用法。
must
查询
当使用must
查询时,文档必须符合其中包括的所有查询条件。当must
查询只包括一个查询条件时,可在DSL中使用JSON对象的形式表示,例如以下示例:
{
"query": {
"bool": {
"must": {
"term": {
"age": 20
}
}
}
}
}
该查询等同于下面对应的SQL语句:
SELECT * FROM xxx WHERE age = 20;
使用must
时可以同时指定多个查询条件,在DSL中它以数组的形式表示,效果类似于SQL中的AND
运算。例如下面的例子:
{
"query": {
"bool": {
"must": [
{ "term": { "age": 20 } },
{ "term": { "gender": "male" } }
]
}
}
}
该查询等同于下面的SQL语句:
SELECT * FROM xxx WHERE age = 20 AND gender = "male";
filter
查询
使用filter
查询时其效果等同于must
查询,但不同于must
查询的是,filter
查询不参与查询结果的分值计算,它返回的文档的分值始终为0。filter
的使用场景适合于过滤不需要的文档,但又不影响最终计算的得分。
例如下面的查询中,将返回所有status
的值为"active"
的文档,其得分均为0.0
。
{
"query": {
"bool": {
"filter": {
"term": {
"status": "active"
}
}
}
}
}
should
查询
should
查询类似于SQL中的OR
语句,当其中包括两个及两个以上的条件时,其查询的结果必须至少满足其中一个。当只有一个查询条件时,即结果必须满足该条件。
{
"query": {
"bool": {
"should": [
{ "term": { "age": 20 } },
{ "term": { "gender": "male" } },
{ "range": { "height": { "gte": 170 } } },
]
}
}
}
该查询等同于下面对应的SQL语句:
SELECT * FROM xxx WHERE age = 20 OR gender = "male" or height >= 170;
should
查询与SQL中的OR
运算较为不同的一点是,should
查询可以使用minimum_should_match
参数指定至少需要满足几个条件。例如下面的例子中,查询的结果需要满足两个或两个以上的查询条件:
{
"query": {
"bool": {
"should": [
{ "term": { "age": 20 } },
{ "term": { "gender": "male" } },
{ "term": { "height": 170 } },
],
"minimum_should_match": 2
}
}
}
在同一个bool
语句中若不存在must
或filter
时,minimum_should_match
默认的值为1,即至少要满足其中一个条件;但若有其它must
或filter
存在时,minimum_should_match
默认值为0。例如下面的查询,所有返回的文档age
值必定为20,但其中可能包括有status
值不为"active"
的文档。若需要二者同时生效,可入上面例子中一样在bool
查询中增加一个参数"minimum_should_match": 1
。
{
"query": {
"bool": {
"must": {
"term": {
"age": 20
},
},
"should": {
"term": {
"status": "active"
}
}
}
}
}
must_not
查询
must_not
查询类似于SQL语句中的NOT
运算,它将只返回不满足指定条件的文档。例如:
{
"query": {
"bool": {
"must_not": [
{ "term": { "age": 20 } },
{ "term": { "gender": "male" } }
]
}
}
}
该查询等同于下面的SQL查询语句(由于MySQL不支持下面语句使用NOT,于是改写为使用!=
实现):
SELECT * FROM xxx WHERE age != 20 AND gender != "male";
另外,must_not
与filter
相同,采用过滤器执行而不需要计算文档的得分,所以返回的结果对应的分值为0。
布尔组合查询
在上面的示例(本文第一个示例代码)中,我们提到过同一个bool
下可以存在多个不同的查询条件,如该查询等同于下面的SQL语句:
SELECT * FROM xxx WHERE age = 20 AND gender != "male";
另外,我们也可以在各个查询中进行嵌套查询。但需要注意的是,布尔查询必须包含在bool
查询语句中,所以在嵌套查询中必须在内部再次使用bool
查询语句。
{
"query": {
"must": [
{
"bool": {
"should": [
{ "term": { "age": 20 } },
{ "term": { "age": 25 } }
]
}
},
{
"range": {
"level": {
"gte": 3
}
}
}
]
}
}
该查询语句等同于以下SQL语句:
SELECT * FROM xxx WHERE (age = 20 OR age = 25) AND level >= 3;
结束语
在本文中,我们简单地介绍了一下Elasticsearch中的布尔查询以及其组合查询。对于Elasticsearch的更多使用,可以参考官方提供的Elasticsearch Reference以及其它文章、书籍。
参考资料
- Boolean query - Elasticsearch Reference
- Rafal Kuc, Marek Rogozinski. Mastering Elasticsearch, second edition.