Boolean query #
A query that matches documents matching boolean combinations of other queries. It is built using one or more boolean clauses.
Inside a
nestedquery: supported —must/filter/should/must_notandminimum_should_matchall apply within ONE array element; clauses matched by different elements never combine.
How it works #
bool compiles each clause list into iterator algebra: must clauses
intersect (AND), must_not clauses subtract, filter clauses intersect
without scoring, and should clauses are probed per matched document —
a streaming two-pointer walk that adds each matching should score on
top of the base hit, with no intermediate materialization.
Matching and scoring rules:
must— every clause must match; each contributes its score, summed.filter— every clause must match; resolved through the unscoring range/BKD/column-store paths, contributing nothing to the score.must_not— no clause may match; unscored.should— optional score boosts whilemust/filterdo the filtering. They become required in exactly two cases: when the bool hasshouldclauses but nomust/filter(then at least one must match), or whenminimum_should_matchis 1 or more, which turns the should group into a required at-least-N-of-M gate alongside the other clauses.
When several clauses match the same document their scores add — an OR
union sums per-document scores, and a union reduced to a single child
passes the child’s score through unchanged, so a one-branch bool never
distorts the score below it. score_mode selects how multi-field
should scores combine — most_fields (sum, the default) or
best_fields (dis_max-style: max + tie_breaker * sum(other_scores),
with tie_breaker in [0, 1]). Per-clause boost multiplies into the
BM25 chain before the combination. One frozen-segment nuance: when a
multi-term expansion (wildcard, regexp, prefix) is a should
clause of a same-field bool, its expanded terms merge into the
field’s term stream and score per-term BM25 there instead of the
constant score a standalone expansion receives.
The optimizer picks the execution shape automatically — filter-led
vector evaluation when a filter constrains a vector clause,
text-driven scoring with vector boosts when a must text query pairs
with a should vector, and reciprocal-rank fusion when independent
pipelines sit in a should-only bool. Query::simplify also flattens
the tree: a bool whose only content is a single must collapses to
that query, and a redundant match_all inside must is dropped when
other clauses already restrict the set.
Examples #
The query below combines a full-text must with an unscoring range
filter — the hats (type = hat) that cost at least 25. All 30 hats
are priced 30, so all 30 match:
POST /my-collection/_search
{
"query": {
"bool": {
"must": [
{ "match": { "field": "title", "query": "search" } }
],
"filter": [
{ "term": { "field": "status", "value": "published" } }
],
"must_not": [
{ "range": { "field": "views", "gte": 100000 } }
],
"should": [
{ "term": { "field": "tags", "value": "featured" } }
],
"minimum_should_match": 1
}
}
}
Clause types #
must
The document must match. Contributes to the score.filter
The document must match. Does not contribute to the score — clauses resolve through the unscoring index paths.should
The document should match. Contributes to the score; required to match only when nomust/filterclauses are present (then at least oneshouldmust match) or whenminimum_should_matchis set.must_not
The document must not match. Does not contribute to the score.
Use cases #
- Filter + full text. The workhorse shape:
mustamatchfor relevance,filterarange/termfor the hard constraints — scored where it matters, unscored where it doesn’t. The example above (hats at price ≥ 25) is exactly this pattern. - Exclusion lists.
must_notremoves archived rows, spam flags or maintenance windows from an otherwise broad query. - Optional relevance signals.
shouldboosts featured, recent or vector-similar items without gating admission — and turns into a hard gate viaminimum_should_matchwhen the rule demands it. - Hybrid retrieval. BM25 text and vector search in one bool: the optimizer fuses the pipelines (text-driven with vector boosts, or RRF for independent shoulds) with no query-side hint.
Parameters for bool
#
must,filter,should,must_not
(Optional, array of query objects — a single query object is also accepted as shorthand) The clause lists. At least one clause somewhere is required for the bool to match anything.minimum_should_match
(Optional, integer, 0–255) Minimum number ofshouldclauses a document must match. The built-in default is1when the query hasshouldclauses but nomust/filter, otherwise0. The percentage and offset string forms ("75%","-1") are not accepted — the value is a plain integer.score_mode
(Optional, string) Multi-field score combination strategy forshouldclauses:most_fields(sum — the default, for backward compatibility) orbest_fields(max, dis_max style).tie_breaker
(Optional, float, default:0) Tie-breaker forbest_fieldsmode. Final score:max_score + tie_breaker * sum(other_scores). Range[0, 1].
Related #
match/multi_match— the scored full-text leaves most bools combine;multi_matchitself expands into a bool.range— the typicalfilteroccupant: unscoring numeric and date restrictions.match_all— the everything base under must_not-only bools and filter-only aggregations.- Analyzers — what the analyzed child queries tokenize with.
- API conventions — clause shorthand and strict-gate parameter handling.