TL;DR - How do I check whether one-of and all-of a nested array meet specified criteria?
I have a document. Each document has an array of nested outer objects, who themselves have a list of nested inner objects. I need to perform a filter for all documents where at least one of the document's outer nested objects match. When I say match, I mean that all the outer nested objects' inner objects match in some way. Here's an example mapping for reference;
{ "document" : {
"properties" : {
"name" : {
"type" : "string"
},
"outer" : {
"type" : "nested",
"properties" : {
"inner" : {
"type" : "nested",
"properties" : {
"match" : {
"type" : "string",
"index" : "not_analyzed"
},
"type" : {
"type" : "string",
"index" : "not_analyzed"
}
}}}}}}
}
If the document has no outer/inner objects it is considered to match. But to make things worse the inner objects need to be considered to match differently depending on the type in a kind of conditional logic manner (eg CASE in SQL). For example, if the type were the term "Country" then inner object would be considered to match if the match were a specified country code such as ES. A document may have inner objects of varying type and there is not guarantee that specific types will exist.
Coming from a imperative (Java) programming background I am having incredible trouble figuring out how to implement this kind of filtering. Nothing I can think of even vaguely matches this behaviour. Thus far all I have is the filtered query;
"filtered" : {
"query" : {
"match_all" : { }
},
"filter" : {
"bool" : {
"should" : {
"missing" : {
"field" : "outer.inner.type"
}
}}}}
}
So, the question is...
How can I filter to documents who have at least one outer object which has all inner objects matching based on the type of inner object?
Further details By Request -
Example Document JSON
{
"name":"First",
"outer":[
{
"inner":[
{"match":"ES","type":"Country"},
{"match":"Elite","type":"Market"}
]
},{
"inner":[
{"match":"GBR","type":"Country"},
{"match":"1st Class","type":"Market"},
{"match":"Admin","type":"Role"}
]
}
],
"lockVersion":0,"sourceId":"1"
}
The above example should come through the filter if we were to provide "1st Class" market and the country "GRB" because the second of the two outer objects would be considered a match because both inner objects match. If, however, we provided the country country "GRB" and the market "Elite" then we would not have this document returned because neither of the outer objects would have bother of their inner objects match in their entirety. If we wanted the second outer object to match then all three inner would need to match. Take note that there is an extra type in the third inner. This leads to a situation where if a type exists then it needs to have a match for it else it doesn't need to match because it is absent.