189

What is the difference between MUST and SHOULD bool query in ES?

If I ONLY want results that contain my terms should I then use must ?

I have a query that should only contain certain values, and also no results that has a lower date/timestamp than todays time/date - NOW

Also

Can i use multiple filters inside a must like the code bellow:

"filtered": {
"filter": {
"bool" : {
        "must" : {
            "term" : { "type" : 1 }
            "term" : { "totals" : 14 }
            "term" : { "groupId" : 3 }
            "range" : {
                "expires" : {
                    "gte": "now"
                }
            }
        },
lukasgeiter
  • 124,981
  • 24
  • 288
  • 251
user2722667
  • 6,435
  • 14
  • 41
  • 85

3 Answers3

298

must means: The clause (query) must appear in matching documents. These clauses must match, like logical AND.

should means: At least one of these clauses must match, like logical OR.

Basically they are used like logical operators AND and OR. See this.

Now in a bool query:

must means: Clauses that must match for the document to be included.

should means: If these clauses match, they increase the _score; otherwise, they have no effect. They are simply used to refine the relevance score for each document.


Yes you can use multiple filters inside must.

Sagi
  • 7,484
  • 3
  • 30
  • 36
Utsav Dawn
  • 6,226
  • 2
  • 26
  • 41
  • A bit late to the party, but how about `must` for categories, or pricing, and `should` for attributes, like size and colour. Now, if size L and XL are selected, it's a should between those two, but if colour green is also selected, it has to be a must have for (sizes L OR XL) AND (colour green). Is that possible? – Mave Apr 30 '15 at 18:03
  • I believe in that case _filters_ might be a better approach for attributes. They're geared towards exact matches and not relevance based searches. See [queries and filters](http://www.elastic.co/guide/en/elasticsearch/guide/master/_queries_and_filters.html) in the docs for more info. – Jim K. May 07 '15 at 10:53
  • 9
    I think you need to have `minimum_number_should_match = 1` in order to enforce the idea that "at least one of these clauses must match". – Jim K. May 07 '15 at 10:54
  • Good answer! I just want to share a part of the documentation that was very helpful for me to understand this. https://www.elastic.co/guide/en/elasticsearch/guide/current/_most_important_queries_and_filters.html#_bool_query – ba0708 Dec 13 '15 at 16:30
  • "must means: Clauses that must match for the document to be included."... I think that there is an exception for this statement. when using with multi-match query "operator" : "and" should be added. otherwise it also matches at least one like or. – Emil Aug 11 '16 at 10:44
  • My confusion was `must` and `filter`, and I found this: "`filter` Clauses that `must` match, but are **run in non-scoring**, filtering mode. These clauses do not contribute to the score, instead they simply include/exclude documents based on their criteria." **New documentation**: https://www.elastic.co/guide/en/elasticsearch/guide/current/combining-queries-together.html – Jaider Sep 09 '16 at 15:34
  • 1
    JimK - or no must clause. When there is no must clause, the minimum_number_should_match is implied. – LizH Jan 31 '17 at 17:40
  • If I understand correctly, a `bool` query with a `should` **inside** a `must` (query: { bool: { must: { query: [], should: [] } } }) assumes a different meaning, since in this scenario the `should` can influence in the number of total documents matched, correct? – Luis Vasconcellos Jul 20 '18 at 13:34
  • Just noticed something. In a bool query if you use a `should` clause with an empty `must` clause, the `should` clause acts like a `must` clause. Just an observation – DollarAkshay May 27 '21 at 07:06
17

Since this is a popular question, I would like to add that in Elasticsearch version 2 things changed a bit.

Instead of filtered query, one should use bool query in the top level.

If you don't care about the score of must parts, then put those parts into filter key. No scoring means faster search. Also, Elasticsearch will automatically figure out, whether to cache them, etc. must_not is equally valid for caching.

Reference: https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html

Also, mind that "gte": "now" cannot be cached, because of millisecond granularity. Use two ranges in a must clause: one with now/1h and another with now so that the first can be cached for a while and the second for precise filtering accelerated on a smaller result set.

TautrimasPajarskas
  • 2,471
  • 1
  • 28
  • 38
12

As said in the documentation:

Must: The clause (query) must appear in matching documents.

Should: The clause (query) should appear in the matching document. In a boolean query with no must clauses, one or more should clauses must match a document. The minimum number of should clauses to match can be set using the minimum_should_match parameter.

In other words, results will have to be matched by all the queries present in the must clause ( or match at least one of the should clauses if there is no must clause.

Since you want your results to satisfy all the queries, you should use must.


You can indeed use filters inside a boolean query.

Magnus Reftel
  • 929
  • 6
  • 18
Heschoon
  • 2,443
  • 7
  • 21
  • 47