Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How combine query, must and must_not in elasticsearch?

The following documents should be found:

matches query 'my text' AND (has not field OR field with value)

I have tried the following:

GET /myIndex/_search

{
  "query": {
    "bool": {
      "must": [
        {
          "query_string": {
            "query": "my text"
          }
        },
        {
        }
      ],
      "filter": {
        "bool": {
          "must_not": {
            "exists": {
              "field": "myField"
            }
          },
          "must": {
            "terms": {
              "myField": [
                "myValue"
              ]
            }
          }
        }
      }
    }
  }
}

It should (but does not) work liek that:

  1. bool combine via OR must and filter parts
  2. first must select by query
  3. filter uses bool which combines by OR must andmust_not`

But this behaves like must combined with must_not via AND clause. E.g. when I removed "must" or "must_not" query works.

How change query to combine "must" with "must_not" via OR clause?

Elasticsearch version is 5.3.2

like image 264
Cherry Avatar asked Oct 25 '17 15:10

Cherry


2 Answers

You need an extra bool filter between the must and must_not terms.

You should also think about your myField field. If it is defined as text or as keyword. Tested with elasticsearch 5.6.1 the following query works:

{
  "query": {
     "bool": {
        "must": [{

          "query_string": {
             "query": "this is a text content"
          }
        }],

        "filter": {
           "bool": {
              "should" : [{                
                 "bool" : {
                    "must_not": {
                      "exists": {
                         "field": "myField"
                       }
                     }
                  }
              },
              {
                "bool" : {
                  "must": {
                    "terms": {
                       "myField.keyword": ["my field exists and has a value"]
                     }
                   }
                }
              }]

         }
      }
   }
  }
}
like image 115
Eirini Graonidou Avatar answered Nov 15 '22 05:11

Eirini Graonidou


On Elasticsearch 7.X, you can simply do:

{
  "query": {
    "bool": {
      "must": [
        {"match": {"field1": {"query": "Hero"}}}
      ],
      "must_not": [
        {"terms":{"field3":["Batman"]}},
      ]
    }
  }
}
like image 38
Thomas Ducrot Avatar answered Nov 15 '22 05:11

Thomas Ducrot