let say I have following Document:
{ id: 1, name: "xyz", users: [ { name: 'abc', surname: 'def' }, { name: 'xyz', surname: 'wef' }, { name: 'defg', surname: 'pqr' } ] }
I want to Get only matching nested objects with All Top level fields in search response. I mean If I search/filter for users with name 'abc', I want below response
{ id: 1, name: "xyz", users: [ { name: 'abc', surname: 'def' } ] }
How can I do that?
Reference : select matching objects from array in elasticsearch
You can perform a nested query in Elasticsearch by using the nested parameter. A nested query will search the nested field objects and return the document's root parent if there's a matching object.
You can search nested fields using dot notation that includes the complete path, such as obj1.name . Multi-level nesting is automatically supported, and detected, resulting in an inner nested query to automatically match the relevant nesting level, rather than root, if it exists within another nested query.
The nested type is a specialised version of the object data type that allows arrays of objects to be indexed in a way that they can be queried independently of each other.
When a packed class contains an instance field that is a packed type, the data for that field is packed directly into the containing class. The field is known as a nested field . When reading from a nested field, a small object is created as a pointer to the data.
If you're ok with having all root fields except the nested one and then only the matching inner hits in the nested field, then we can re-use the previous answer like this by specifying a slightly more involved source filtering parameter:
{ "_source": { "includes": [ "*" ], "excludes": [ "users" ] }, "query": { "nested": { "path": "users", "inner_hits": { <---- this is where the magic happens "_source": [ "name", "surname" ] }, "query": { "bool": { "must": [ { "term": { "users.name": "abc" } } ] } } } } }
Maybe late, I use nested sorting to limit element on my nested relation, here a example :
"sort": { "ouverture.periodesOuvertures.dateDebut": { "order": "asc", "mode": "min", "nested_filter": { "range": { "ouverture.periodesOuvertures.dateFin": { "gte": "2017-08-29", "format": "yyyy-MM-dd" } } }, "nested_path": "ouverture.periodesOuvertures" } },
Since 5.5 ES (I think) you can use filter on nested query. Here a example of nested query filter I use:
{ "nested": { "path": "ouverture.periodesOuvertures", "query": { "bool": { "must": [ { "range": { "ouverture.periodesOuvertures.dateFin": { "gte": "2017-08-29", "format": "yyyy-MM-dd" } } }, { "range": { "ouverture.periodesOuvertures.dateFin": { "lte": "2017-09-30", "format": "yyyy-MM-dd" } } } ], "filter": [ { "range": { "ouverture.periodesOuvertures.dateFin": { "gte": "2017-08-29", "format": "yyyy-MM-dd" } } }, { "range": { "ouverture.periodesOuvertures.dateFin": { "lte": "2017-09-30", "format": "yyyy-MM-dd" } } } ] } } } }
Hope this can help ;)
Plus if you ES is not in the last version (5.5) inner_hits could slow your query Including inner hits drastically slows down query results
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With