So I got this document with a nested array that I want to filter with this query.
I want ES to return all documents where all items have changes = 0 and that only. If document has even a single item in the list with a change = 1, that's discarded.
Is there any way I can achieve this starting from the query I have already wrote? Or should I use a script instead?
DOCUMENTS:
{
"id": "abc",
"_source" : {
"trips" : [
{
"type" : "home",
"changes" : 0
},
{
"type" : "home",
"changes" : 1
}
]
}
},
{
"id": "def",
"_source" : {
"trips" : [
{
"type" : "home",
"changes" : 0
},
{
"type" : "home",
"changes" : 0
}
]
}
}
QUERY:
GET trips_solutions/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"id": {
"value": "abc"
}
}
},
{
"nested": {
"path": "trips",
"query": {
"range": {
"trips.changes": {
"gt": -1,
"lt": 1
}
}
}
}
}
]
}
}
}
EXPECTED RESULT:
{
"id": "def",
"_source" : {
"trips" : [
{
"type" : "home",
"changes" : 0
},
{
"type" : "home",
"changes" : 0
}
]
}
}
Elasticsearch version: 7.6.2
Already read this answers but they didn't help me: https://discuss.elastic.co/t/how-to-match-all-item-in-nested-array/163873 ElasticSearch: How to query exact nested array
First off, if you filter by
id: abc
, you obviously won't be able to getid: def
back.Second, due to the nature of
nested
fields which are treated as separate subdocuments, you cannot query for alltrips
that have thechanges
equal to 0 -- the connection between the individual trips is lost and they "don't know about each other".What you can do is return only the trips that matched your nested query using
inner_hits
:The easiest solution then is to dynamically save this nested info on a parent object like discussed here and using range/term query on the resulting array.
EDIT:
Here's how you do it using
copy_to
onto the doc's top level:trips_changes
will be an array of numbers -- I presume they're integers but more types are available.Then syncing a few docs:
And finally querying:
Note that we first filter normally using the nested term query to narrow down our search context (scripts are slow so this is useful). We then check if there are any non-zero
changes
in the accumulated top-level changes and reject those that apply.