Search code examples
arrayselasticsearch

Elasticsearch array property must contain given array items


I have documents that look like:

{
    "tags" => [
        "tag1",
        "tag2",
    ],
    "name" => "Example 1"
}

{
    "tags" => [
        "tag1",
        "tag3",
        "tag4"
    ],
    "name" => "Example 2"
}

What I now want is to do a terms search where given array might look like:

[tag1, tag3]

where expected hit should be:

{
    "tags" => [
        "tag1",
        "tag3",
        "tag4"
    ],
    "name" => "Example 2"
}

However, when I do a query like:

GET _search
{
    "query": {
        "filtered": {
           "query": {
               "match_all": {}
           },
           "filter": {
               "bool": {
                   "must": [
                      {
                          "terms": {
                             "tags": [
                                "tag1",
                                "tag3"
                             ]
                          }
                      }
                   ]
               }
           }
       }
    }
}

I get both "Example 1" and "Example 2" as hits since both Example 1 and Example 2 contains either tag1 or tag3. By looking at the documentation for terms I figured out that terms is actually a contains query.

How can I in this case make sure that Example 2 is the only hit when querying with tag1 and tag3?


Solution

  • You need to set the execution mode to "and" by adding "execution": "and" to the terms filter so that all terms must be contained within a document to be considered a match

    GET _search
    {
       "query": {
          "filtered": {
             "query": {
                "match_all": {}
             },
             "filter": {
                "terms": {
                   "tags": [
                      "tag1",
                      "tag3"
                   ],
                   "execution": "and"
                }
             }
          }
       }
    }
    

    This is effectively the same as building a bool must filter with the conjunction of all terms, but in a more compact form.