Is there a way to get elasticsearch to return only documents that have all their nested objects matching some criteria? Say I have the following contrived example:
"mappings": {
"person": {
"properties": {
"name": { "type": "string" },
"other_info": ...
"pet": {
"type": "nested",
"properties": {
"gender": { "type": "string" },
"age": { "type": "integer" },
"name": { "type": "string" },
"other_info": ...
}
}
}
}
}
In this case, how would I search for people who have pets that all have age greater than 5? I'd also like to search for other properties unrelated to pets, but let's assume otherwise, for simplicity. If a person has three pets but only one or two of them are older than 5, I don't want it to come up as a search hit.
I couldn't find anything about how to do this, so I considered an alternate solution that I don't really like. Instead of using a nested document, have a separate index for pets, with the person ID as a property (maybe with a _parent
field?). Then I could do the following:
- search for pets older than 5, get a list of pets as a result
- on the application side, group the pets in the list by person ID
- count the number of pets in each group, and if that matches the total number of pets owned by the person, add the person ID to a list
- do another search on the person index based on the IDs, and any other person-specific property I want to check for
This seems like a very roundabout way of doing it though, plus if I went that route I'd need to know the total number of pets owned by each person before querying the person index (like storing it as a property for each pet, but that just makes it really messy) or by searching for all the people with at least one matching pet, with the pet count stored in the person index ahead of time (or using a script filter?), and then checking if the count matches.
I came across this github issue (adding the feature "Return matching nested inner objects per hit") which would have been really useful, but unfortunately it hasn't been implemented yet.
Surely there's a better way to do this?