8

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?

1
  • You need at least particular 2 elements, or docs with that exact array? Commented Aug 10, 2015 at 10:37

4 Answers 4

6

For those who are looking at this in 2020, you might have noticed that minimum_should_match is deprecated long back.

There is an alternative currently available, which is to use terms_set.

For eg:

{
  "query": {
    "terms_set": {
      "programming_languages": {
        "terms": [ "c++", "java", "php" ],
        "minimum_should_match_field": "required_matches"
      }
    }
  }
}

The above example assumes a field required_matches exists which contains an integer, that defines how many matches should be there.

What is more useful is the alternative field minimum_should_match_script.

See the example below:

{
  "query": {
    "terms_set": {
      "programming_languages": {
        "terms": [ "c++", "java", "php" ],
        "minimum_should_match_script": {
          "source": "2"
        },
      }
    }
  }
}

You can always use the inside a filter context to make it works a filter.

Read more here

Sign up to request clarification or add additional context in comments.

1 Comment

I'm not sure in what context minimum_should_match might be deprecated, but Google will only show me that happening to minimum_number_should_match.
4

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.

2 Comments

this should now be written with a must query because filtered queries are deprecated since ES v5.0 as stated here
@Louis entire query needs to be written quite differently for 5 onwards as execution mode on terms query is gone as well
0

You can set minimum_should_match to match your array:

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

Comments

0
{
  "query": {
    "terms_set": {
      "tags": {
        "terms": [ "tag1", "tag2", "tag3" ],
        "minimum_should_match_script": {
          "source": "params.num_terms"
        }
      }
    }
  }
}

params.num_terms is the size of terms, or specific num "source": "3",and more tag matched,return score is higher

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.