1

Given this document:

{"name": "Perfect Sunny-Side Up Eggs","ingredientList": ["canola oil","eggs"]}

How can I build a query in elastic search to return exact matches on a string array given query term "oil eggs", so far this it what I have, but it returns other irrelevant documents:

POST /recipes/recipe/_search
{
   "query": {
      "match": {
         "ingredientList": {
            "query": [
               "oil",
               "eggs"
            ],
            "operator": "and"
         }
      }
   }
}

for instance, this document is returned but it doesn't contain "oil". Results should only contain "oil" and "eggs":

{"name": "Quick Baked French Toast","ingredientList": ["butter","cinnamon raisin bread","eggs"]}
1

2 Answers 2

5

Your query will look like this:

{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "ingredientList": "oil"
          }
        },
        {
          "term": {
            "ingredientList": "eggs"
          }
        }
      ]
    }
  }
}

Gives me the results:

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 1,
    "max_score" : 1.0,
    "hits" : [ {
      "_index" : "ingredients",
      "_type" : "recipe",
      "_id" : "AVeprXFrNutW6yNguPqp",
      "_score" : 1.0,
      "_source" : {
        "name" : "Perfect Sunny-Side Up Eggs",
        "ingredientList" : [ "canola oil", "eggs" ]
      }
    } ]
  }
}
Sign up to request clarification or add additional context in comments.

5 Comments

Thank you so much!
Hello, I know this was posted a long time ago but I'm trying to do something similar, except in my case it should contain the exact phrase "oil" and not "canola oil". Do you know how to do this ? Thanks.
@tomfl Hi, I'm looking for the same thing, did you resolve it?
@Vladimir Hmm if I remember correctly I had to change the analyzer to keyword : elastic.co/guide/en/elasticsearch/reference/current/…
to make "oil" not match on "canola oil", then say "term": { "ingredientList.keyword": "oil" }
3

Elastic dont have API to exact match array. But same can be achieved using two methods:

  1. Using multiple must blocks (not preferred)

  2. Using terms set query and script

     "query": {
       "bool": {
         "must": [
           {
             "terms_set": {
               "ingredientList": {
                 "terms": ingredients,
                 "minimum_should_match_script": {
                   "source": "Math.min(params.num_terms, {})".format(len(ingredients))
                 }
               }
             }
           },
           {
             "script": {
               "script": {
                 "inline": "doc['ingredientList'].length == params.list_length",
                 "lang": "painless",
                 "params": {
                   "list_length": len(ingredients)
                 }
               }
             }
           }
         ]
       }
     }
    

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.