2
votes

I have a little confusion about the usage SHOULD and MUST in bool queries. When you have several filters in SHOULD and MUST clauses, can they be place at the same level or they should be nested?

Below is a simplified version of my data and the two queries that I tested, first one failing and the latter working. In real practice, I have many filters in MUST and SHOULD.

I start to believe that if one wants to combine several SHOULD and MUST filters, the outer one must always be SHOULD. Is this a correct assumption? And in case I wanted to use a MUST_NOT, where should it be placed in this context?

My data:

_index,_type,_id,_score,_source.id,_source.type,_source.valueType,_source.sentence,_source.location
"test","var","0","1","0","study","text","Lorem text is jumbled","spain"
"test","var","1","1","1","study","text","bla bla bla","spain"
"test","var","2","1","2","schema","decimal","ipsum","germany"
"test","var","3","1","3","study","integer","lorem","france"

Here is the failing query:

{
  "query": {
    "filtered": {
      "query": {
        "match_all": {}
      },
      "filter": {
        "bool": {
          "must": {
            "terms": {
              "location": [
                "germany"
              ]
            }
          },
          "should": {
            "terms": {
              "valueType": [
                "integer"
              ]
            }
          }
        }
      }
    }
  }
}

Here is my WORKING query returning IDs 2 and 3:

{
  "query": {
    "bool": {
      "should": [
        {
          "terms": {
            "location": [
              "germany"
            ]
          }
        },
        {
          "bool": {
            "must": [
              {
                "terms": {
                  "valueType": [
                    "integer"
                  ]
                }
              }
            ]
          }
        }
      ]
    }
  }
}

Many thanks.

1

1 Answers

4
votes

First need to understand meaning of filters.

Compound Filter:

must clauses are required (and)
should clauses are optional (or)

So in first block you are checking term in must(and). So this term must be in result set. and should(or) cond 2 may or may not in result set.

{
   "query": {
      "filtered": {
         "query": {
            "match_all": {}
         },
         "filter": {
            "bool": {  
               "must": {
                   ....... Cond 1
               },
               "should": {
                   ....... Cond 2
               }
            }
         }
      }
   }
}

In your working scenario you are query working because should checking Cond 1 OR Cond 2.

{
   "query": {
      "bool": {
         "should": [   // OR 
            {
              ...... Cond 1
            },
            {
              ...... Cond 2
            }
         ]
      }
   }
}