布尔查询

编辑

一种匹配符合其他查询的布尔组合的文档的查询。布尔查询映射到 Lucene BooleanQuery。它使用一个或多个布尔子句构建,每个子句都具有一个类型的出现。出现类型为:

出现 描述

must

该子句(查询)必须出现在匹配的文档中,并且会影响得分。

filter

该子句(查询)必须出现在匹配的文档中。但是,与 must 不同,该查询的得分将被忽略。过滤器子句在过滤器上下文中执行,这意味着会忽略评分,并且会考虑子句进行缓存。

should

该子句(查询)应该出现在匹配的文档中。

must_not

该子句(查询)不得出现在匹配的文档中。子句在过滤器上下文中执行,这意味着会忽略评分,并且会考虑子句进行缓存。由于忽略了评分,因此所有文档的得分都返回为 0

bool 查询采用匹配越多越好的方法,因此每个匹配的 mustshould 子句的得分将加在一起,以提供每个文档的最终 _score

resp = client.search(
    query={
        "bool": {
            "must": {
                "term": {
                    "user.id": "kimchy"
                }
            },
            "filter": {
                "term": {
                    "tags": "production"
                }
            },
            "must_not": {
                "range": {
                    "age": {
                        "gte": 10,
                        "lte": 20
                    }
                }
            },
            "should": [
                {
                    "term": {
                        "tags": "env1"
                    }
                },
                {
                    "term": {
                        "tags": "deployed"
                    }
                }
            ],
            "minimum_should_match": 1,
            "boost": 1
        }
    },
)
print(resp)
response = client.search(
  body: {
    query: {
      bool: {
        must: {
          term: {
            'user.id' => 'kimchy'
          }
        },
        filter: {
          term: {
            tags: 'production'
          }
        },
        must_not: {
          range: {
            age: {
              gte: 10,
              lte: 20
            }
          }
        },
        should: [
          {
            term: {
              tags: 'env1'
            }
          },
          {
            term: {
              tags: 'deployed'
            }
          }
        ],
        minimum_should_match: 1,
        boost: 1
      }
    }
  }
)
puts response
const response = await client.search({
  query: {
    bool: {
      must: {
        term: {
          "user.id": "kimchy",
        },
      },
      filter: {
        term: {
          tags: "production",
        },
      },
      must_not: {
        range: {
          age: {
            gte: 10,
            lte: 20,
          },
        },
      },
      should: [
        {
          term: {
            tags: "env1",
          },
        },
        {
          term: {
            tags: "deployed",
          },
        },
      ],
      minimum_should_match: 1,
      boost: 1,
    },
  },
});
console.log(response);
POST _search
{
  "query": {
    "bool" : {
      "must" : {
        "term" : { "user.id" : "kimchy" }
      },
      "filter": {
        "term" : { "tags" : "production" }
      },
      "must_not" : {
        "range" : {
          "age" : { "gte" : 10, "lte" : 20 }
        }
      },
      "should" : [
        { "term" : { "tags" : "env1" } },
        { "term" : { "tags" : "deployed" } }
      ],
      "minimum_should_match" : 1,
      "boost" : 1.0
    }
  }
}

使用 minimum_should_match

编辑

您可以使用 minimum_should_match 参数来指定返回的文档必须匹配的 should 子句的数量或百分比。

如果 bool 查询包含至少一个 should 子句,并且没有 mustfilter 子句,则默认值为 1。否则,默认值为 0

有关其他有效值,请参阅minimum_should_match 参数

使用 bool.filter 评分

编辑

filter 元素下指定的查询对评分没有影响,得分将返回为 0。得分仅受已指定的查询影响。例如,以下所有三个查询都返回 status 字段包含术语 active 的所有文档。

第一个查询将所有文档的得分都分配为 0,因为没有指定任何评分查询。

$params = [
    'body' => [
        'query' => [
            'bool' => [
                'filter' => [
                    'term' => [
                        'status' => 'active',
                    ],
                ],
            ],
        ],
    ],
];
$response = $client->search($params);
resp = client.search(
    query={
        "bool": {
            "filter": {
                "term": {
                    "status": "active"
                }
            }
        }
    },
)
print(resp)
response = client.search(
  body: {
    query: {
      bool: {
        filter: {
          term: {
            status: 'active'
          }
        }
      }
    }
  }
)
puts response
res, err := es.Search(
	es.Search.WithBody(strings.NewReader(`{
	  "query": {
	    "bool": {
	      "filter": {
	        "term": {
	          "status": "active"
	        }
	      }
	    }
	  }
	}`)),
	es.Search.WithPretty(),
)
fmt.Println(res, err)
const response = await client.search({
  query: {
    bool: {
      filter: {
        term: {
          status: "active",
        },
      },
    },
  },
});
console.log(response);
GET _search
{
  "query": {
    "bool": {
      "filter": {
        "term": {
          "status": "active"
        }
      }
    }
  }
}

bool 查询有一个 match_all 查询,该查询将所有文档的得分都分配为 1.0

$params = [
    'body' => [
        'query' => [
            'bool' => [
                'must' => [
                    'match_all' => [
                    ],
                ],
                'filter' => [
                    'term' => [
                        'status' => 'active',
                    ],
                ],
            ],
        ],
    ],
];
$response = $client->search($params);
resp = client.search(
    query={
        "bool": {
            "must": {
                "match_all": {}
            },
            "filter": {
                "term": {
                    "status": "active"
                }
            }
        }
    },
)
print(resp)
response = client.search(
  body: {
    query: {
      bool: {
        must: {
          match_all: {}
        },
        filter: {
          term: {
            status: 'active'
          }
        }
      }
    }
  }
)
puts response
res, err := es.Search(
	es.Search.WithBody(strings.NewReader(`{
	  "query": {
	    "bool": {
	      "must": {
	        "match_all": {}
	      },
	      "filter": {
	        "term": {
	          "status": "active"
	        }
	      }
	    }
	  }
	}`)),
	es.Search.WithPretty(),
)
fmt.Println(res, err)
const response = await client.search({
  query: {
    bool: {
      must: {
        match_all: {},
      },
      filter: {
        term: {
          status: "active",
        },
      },
    },
  },
});
console.log(response);
GET _search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "term": {
          "status": "active"
        }
      }
    }
  }
}

constant_score 查询的行为与上面的第二个示例完全相同。constant_score 查询将过滤器匹配的所有文档的得分都分配为 1.0

$params = [
    'body' => [
        'query' => [
            'constant_score' => [
                'filter' => [
                    'term' => [
                        'status' => 'active',
                    ],
                ],
            ],
        ],
    ],
];
$response = $client->search($params);
resp = client.search(
    query={
        "constant_score": {
            "filter": {
                "term": {
                    "status": "active"
                }
            }
        }
    },
)
print(resp)
response = client.search(
  body: {
    query: {
      constant_score: {
        filter: {
          term: {
            status: 'active'
          }
        }
      }
    }
  }
)
puts response
res, err := es.Search(
	es.Search.WithBody(strings.NewReader(`{
	  "query": {
	    "constant_score": {
	      "filter": {
	        "term": {
	          "status": "active"
	        }
	      }
	    }
	  }
	}`)),
	es.Search.WithPretty(),
)
fmt.Println(res, err)
const response = await client.search({
  query: {
    constant_score: {
      filter: {
        term: {
          status: "active",
        },
      },
    },
  },
});
console.log(response);
GET _search
{
  "query": {
    "constant_score": {
      "filter": {
        "term": {
          "status": "active"
        }
      }
    }
  }
}

命名查询

编辑

每个查询在其顶层定义中都接受一个 _name。您可以使用命名查询来跟踪哪些查询匹配了返回的文档。如果使用了命名查询,则响应将为每个命中项包含一个 matched_queries 属性。

在同一请求中提供重复的 _name 值会导致未定义的行为。具有重复名称的查询可能会相互覆盖。假设查询名称在单个请求中是唯一的。

resp = client.search(
    query={
        "bool": {
            "should": [
                {
                    "match": {
                        "name.first": {
                            "query": "shay",
                            "_name": "first"
                        }
                    }
                },
                {
                    "match": {
                        "name.last": {
                            "query": "banon",
                            "_name": "last"
                        }
                    }
                }
            ],
            "filter": {
                "terms": {
                    "name.last": [
                        "banon",
                        "kimchy"
                    ],
                    "_name": "test"
                }
            }
        }
    },
)
print(resp)
response = client.search(
  body: {
    query: {
      bool: {
        should: [
          {
            match: {
              'name.first' => {
                query: 'shay',
                _name: 'first'
              }
            }
          },
          {
            match: {
              'name.last' => {
                query: 'banon',
                _name: 'last'
              }
            }
          }
        ],
        filter: {
          terms: {
            'name.last' => [
              'banon',
              'kimchy'
            ],
            _name: 'test'
          }
        }
      }
    }
  }
)
puts response
const response = await client.search({
  query: {
    bool: {
      should: [
        {
          match: {
            "name.first": {
              query: "shay",
              _name: "first",
            },
          },
        },
        {
          match: {
            "name.last": {
              query: "banon",
              _name: "last",
            },
          },
        },
      ],
      filter: {
        terms: {
          "name.last": ["banon", "kimchy"],
          _name: "test",
        },
      },
    },
  },
});
console.log(response);
GET /_search
{
  "query": {
    "bool": {
      "should": [
        { "match": { "name.first": { "query": "shay", "_name": "first" } } },
        { "match": { "name.last": { "query": "banon", "_name": "last" } } }
      ],
      "filter": {
        "terms": {
          "name.last": [ "banon", "kimchy" ],
          "_name": "test"
        }
      }
    }
  }
}

名为 include_named_queries_score 的请求参数控制是否返回与匹配的查询关联的得分。设置后,响应将包含一个 matched_queries 映射,其中包含作为键的匹配查询的名称及其作为值的关联得分。

请注意,该得分可能没有影响文档的最终得分,例如出现在过滤器或 must_not 上下文中的命名查询,或出现在忽略或修改得分的子句中(例如 constant_scorefunction_score_query)。

resp = client.search(
    include_named_queries_score=True,
    query={
        "bool": {
            "should": [
                {
                    "match": {
                        "name.first": {
                            "query": "shay",
                            "_name": "first"
                        }
                    }
                },
                {
                    "match": {
                        "name.last": {
                            "query": "banon",
                            "_name": "last"
                        }
                    }
                }
            ],
            "filter": {
                "terms": {
                    "name.last": [
                        "banon",
                        "kimchy"
                    ],
                    "_name": "test"
                }
            }
        }
    },
)
print(resp)
response = client.search(
  include_named_queries_score: true,
  body: {
    query: {
      bool: {
        should: [
          {
            match: {
              'name.first' => {
                query: 'shay',
                _name: 'first'
              }
            }
          },
          {
            match: {
              'name.last' => {
                query: 'banon',
                _name: 'last'
              }
            }
          }
        ],
        filter: {
          terms: {
            'name.last' => [
              'banon',
              'kimchy'
            ],
            _name: 'test'
          }
        }
      }
    }
  }
)
puts response
const response = await client.search({
  include_named_queries_score: "true",
  query: {
    bool: {
      should: [
        {
          match: {
            "name.first": {
              query: "shay",
              _name: "first",
            },
          },
        },
        {
          match: {
            "name.last": {
              query: "banon",
              _name: "last",
            },
          },
        },
      ],
      filter: {
        terms: {
          "name.last": ["banon", "kimchy"],
          _name: "test",
        },
      },
    },
  },
});
console.log(response);
GET /_search?include_named_queries_score
{
  "query": {
    "bool": {
      "should": [
        { "match": { "name.first": { "query": "shay", "_name": "first" } } },
        { "match": { "name.last": { "query": "banon", "_name": "last" } } }
      ],
      "filter": {
        "terms": {
          "name.last": [ "banon", "kimchy" ],
          "_name": "test"
        }
      }
    }
  }
}

此功能会在搜索响应中对每个命中项重新运行每个命名查询。通常,这会给请求增加少量开销。但是,在大量命中项上使用计算成本高的命名查询可能会增加显著的开销。例如,将命名查询与多个存储桶上的 top_hits 聚合结合使用可能会导致更长的响应时间。