Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ElasticSearch - Get only matching nested objects with All Top level fields in search response

Tags:

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

like image 602
Jay Shah Avatar asked Nov 24 '16 07:11

Jay Shah


People also ask

How do you write nested query in elastic search?

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.

How do I search in nested fields?

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.

What is nested in elastic search?

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.

What is a nested field?

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.


2 Answers

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"               }             }           ]         }       }     }   } } 
like image 165
Val Avatar answered Sep 25 '22 08:09

Val


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

like image 20
Mathieu Giboulet Avatar answered Sep 25 '22 08:09

Mathieu Giboulet