0
votes

I have the following data in elastic search:

[
{
  "firstName": "John",
  "lastName": "Doe",
  "id": 10
},
{
  "firstName": "Mary",
  "lastName": "Jane",
  "id": 10
},
{
  "firstName": "John",
  "lastName": "Lennon",
  "id": 12
}
]

I want to write an elastic search query that can match either on firstName or lastName (should) and then filter those results with the id.

the current query that i have written is as follows:

{
  "query": {
    "bool": {
      "filter": [{
        "term": {
          "id": 10
        }
      }],
      "should": [{
        "match": {
            "firstName": "john"
        }
      }, {
        "match": {
            "lastName": "john"
        }
      }]
    }
  }
}   

it is my understanding that when i execute the above query, i should only get the record whose firstName is "John" and id is 10. But in actuality, i get multiple records.

What am i doing wrong here? Any help would be appreciated!

2
The documents you mentioned, are they all individual documents or are they nested/array in one document? It'd be great if you can update the question with mapping details.Opster ES Ninja - Kamal
Also if they are all individual documents, then the query works fine. It would return any documents with id=10 AND (firstname = john OR lastname = john). Can you also post what you see in the response for the above samples.Opster ES Ninja - Kamal
sure thing! The fields that i have currently mentioned are all individual fields. But a good catch that i forgot to mention. I have nested arrays and objects as well that is why i have used this approach for defining separate match clauses. Or else i could have simply used multimatch on these fields and then filter them out.Hussain Ali Akbar
@Kamal undelete your answer and add that ;-) Pay attention to the field names, thoughVal
Yup that works! Thank you guys @kamal and Val ! :) I found another solution as well which is to use a bool clause with should inside a must clause. I'll add that answer too in case someone else is looking for this. But i'll accept kamal's answer.Hussain Ali Akbar

2 Answers

1
votes

Updating my answer as per @Val, you just need to add minimum_should_match clause and below is what you are looking for:

POST <your_index_name>/_search
{
  "query": {
    "bool" : {
      "filter": {
        "term" : { "id" : "10" }
      },
      "should" : [
        { "match" : { "firstName" : "john" } },
        { "match" : { "lastName" : "john" } }
      ],
      "minimum_should_match": 1
    }
  }
}

Let me know if it helps!

0
votes

Kamal's accepted answer is certainly a better and more elegant way to resolve this issue. But, another alternative can be by doing this:

{
   "query":{
      "bool":{
         "must":{
                    "bool": {
                        "should": [
                            {"match": {"firstName": "john"}},
                            {"match": {"lastName": "john"}}
                        ]
                    }
                },
         "filter":{
            "term":{
               "id":10
            }
         }
      }
   }
}