Boolean query

edit

A query that matches documents matching boolean combinations of other queries. The bool query maps to Lucene BooleanQuery. It is built using one or more boolean clauses, each clause with a typed occurrence. The occurrence types are:

Occur Description

must

The clause (query) must appear in matching documents and will contribute to the score.

filter

The clause (query) must appear in matching documents. However unlike must the score of the query will be ignored. Filter clauses are executed in filter context, meaning that scoring is ignored and clauses are considered for caching.

should

The clause (query) should appear in the matching document.

must_not

The clause (query) must not appear in the matching documents. Clauses are executed in filter context meaning that scoring is ignored and clauses are considered for caching. Because scoring is ignored, a score of 0 for all documents is returned.

The bool query takes a more-matches-is-better approach, so the score from each matching must or should clause will be added together to provide the final _score for each document.

resp = 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,
            }
        }
    },
)
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
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
    }
  }
}

Using minimum_should_match

edit

You can use the minimum_should_match parameter to specify the number or percentage of should clauses returned documents must match.

If the bool query includes at least one should clause and no must or filter clauses, the default value is 1. Otherwise, the default value is 0.

For other valid values, see the minimum_should_match parameter.

Scoring with bool.filter

edit

Queries specified under the filter element have no effect on scoring — scores are returned as 0. Scores are only affected by the query that has been specified. For instance, all three of the following queries return all documents where the status field contains the term active.

This first query assigns a score of 0 to all documents, as no scoring query has been specified:

$params = [
    'body' => [
        'query' => [
            'bool' => [
                'filter' => [
                    'term' => [
                        'status' => 'active',
                    ],
                ],
            ],
        ],
    ],
];
$response = $client->search($params);
resp = client.search(
    body={"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({
  body: {
    query: {
      bool: {
        filter: {
          term: {
            status: 'active'
          }
        }
      }
    }
  }
})
console.log(response)
GET _search
{
  "query": {
    "bool": {
      "filter": {
        "term": {
          "status": "active"
        }
      }
    }
  }
}

This bool query has a match_all query, which assigns a score of 1.0 to all documents.

$params = [
    'body' => [
        'query' => [
            'bool' => [
                'must' => [
                    'match_all' => [
                    ],
                ],
                'filter' => [
                    'term' => [
                        'status' => 'active',
                    ],
                ],
            ],
        ],
    ],
];
$response = $client->search($params);
resp = client.search(
    body={
        "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({
  body: {
    query: {
      bool: {
        must: {
          match_all: {}
        },
        filter: {
          term: {
            status: 'active'
          }
        }
      }
    }
  }
})
console.log(response)
GET _search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "term": {
          "status": "active"
        }
      }
    }
  }
}

This constant_score query behaves in exactly the same way as the second example above. The constant_score query assigns a score of 1.0 to all documents matched by the filter.

$params = [
    'body' => [
        'query' => [
            'constant_score' => [
                'filter' => [
                    'term' => [
                        'status' => 'active',
                    ],
                ],
            ],
        ],
    ],
];
$response = $client->search($params);
resp = client.search(
    body={
        "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({
  body: {
    query: {
      constant_score: {
        filter: {
          term: {
            status: 'active'
          }
        }
      }
    }
  }
})
console.log(response)
GET _search
{
  "query": {
    "constant_score": {
      "filter": {
        "term": {
          "status": "active"
        }
      }
    }
  }
}

Named queries

edit

Each query accepts a _name in its top level definition. You can use named queries to track which queries matched returned documents. If named queries are used, the response includes a matched_queries property for each hit.

Supplying duplicate _name values in the same request results in undefined behavior. Queries with duplicate names may overwrite each other. Query names are assumed to be unique within a single request.

resp = 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",
                    }
                },
            }
        }
    },
)
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
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"
        }
      }
    }
  }
}

The request parameter named include_named_queries_score controls whether scores associated with the matched queries are returned or not. When set, the response includes a matched_queries map that contains the name of the query that matched as a key and its associated score as the value.

Note that the score might not have contributed to the final score of the document, for instance named queries that appear in a filter or must_not contexts, or inside a clause that ignores or modifies the score like constant_score or function_score_query.

resp = 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",
                    }
                },
            }
        }
    },
)
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
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"
        }
      }
    }
  }
}

This functionality reruns each named query on every hit in a search response. Typically, this adds a small overhead to a request. However, using computationally expensive named queries on a large number of hits may add significant overhead. For example, named queries in combination with a top_hits aggregation on many buckets may lead to longer response times.