之前的查询都是针对某一个field的,Elasticsearch也支持类似关系型数据库中where a=x and c=x
这种对多个字段的查询。布尔查询是将多个查询条件组合在一起。
Bool查询现在包括四种子句,must,filter, should, must_not
must:返回的文档必须满足must子句的条件,并且参与计算分值
must_not:返回的文档必须不满足must_not定义的条件。
filter:返回的文档必须满足filter子句的条件。但是不会像Must一样,参与计算分值
should:返回的文档可能满足should子句的条件。在一个Bool查询中,如果没有must或者filter,有一个或者多个should子句,那么只要满足一个就可以返回。minimum_should_match
参数定义了至少满足几个子句。
must:返回的文档必须满足must子句的条件,并且参与计算分值
例如查询recipe索引中ingredients.name == parmesan
且preparation_time_minutes >= 10
的记录:
GET /recipe/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"ingredients.name": "parmesan"
}
},
{
"range": {
"preparation_time_minutes": {
"gte": 10
}
}
}
]
}
}
}
filter:返回的文档必须满足filter子句的条件。但是不会像Must一样,参与计算分值
和上面一样,使用filter
方式查询recipe索引中ingredients.name == parmesan
且preparation_time_minutes >= 10
的记录:
GET /recipe/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"ingredients.name": "parmesan"
}
}
],
"filter": [
{
"range": {
"preparation_time_minutes": {
"gte": 10
}
}
}
]
}
}
}
返回的结果内容与上面一致,但是注意``max_score全部比
must查询的结果小1,这是因为filter不会计算
relevance score`:
bool
查询会为每个文档计算相关度评分 _score
,再将所有匹配的 must
和 should
语句的分数 _score
求和,最后除以 must
和 should
语句的总数。
must_not:返回的文档必须不满足must_not定义的条件。
在上面查询的基础上增加一个条件,过滤掉ingredients.name == tuna
的记录:
GET /recipe/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"ingredients.name": "parmesan"
}
}
],
"must_not": [
{
"match": {
"ingredients.name": "tuna"
}
}
],
"filter": [
{
"range": {
"preparation_time_minutes": {
"gte": 10
}
}
}
]
}
}
}
从结果可以看到,must_not
语句不会影响评分;它的作用只是将不相关的文档排除。
should:返回的文档可能满足should子句的条件。在一个Bool查询中,如果没有must或者filter,有一个或者多个should子句,那么只要满足一个就可以返回。
在上面查询的基础上增加一个条件,用should查询ingredients.name == parsley
的记录:
GET /recipe/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"ingredients.name": "parmesan"
}
}
],
"must_not": [
{
"match": {
"ingredients.name": "tuna"
}
}
],
"should": [
{
"match": {
"ingredients.name": "parsley"
}
}
],
"filter": [
{
"range": {
"preparation_time_minutes": {
"gte": 10
}
}
}
]
}
}
}
查询到的结果虽然和上面一致,但排序有变化,这是因为bool
查询会将所有匹配的 must
和 should
语句的分数 _score
求和。
如果想知道到底是bool里面哪个条件匹配,可以使用named query查询:
GET /recipe/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"ingredients.name": {
"query": "parmesan",
"_name": "parmesan_must"
}
}
}
],
"must_not": [
{
"match": {
"ingredients.name": {
"query": "tuna",
"_name": "tuna_must_not"
}
}
}
],
"should": [
{
"match": {
"ingredients.name": {
"query": "parsley",
"_name": "parsley_should"
}
}
}
],
"filter": [
{
"range": {
"preparation_time_minutes": {
"gte": 10,
"_name": "preparation_time_minutes_range"
}
}
}
]
}
}
}
返回结果中将每条记录命中的查询以列表显示出来: