Nested datatype | Elasticsearch Reference [6.3]

The nested type is a specialised version of the object datatype that allows arrays of objects to be indexed in a way that they can be queried independently of each other.

Arrays of inner object fields do not work the way you may expect. Lucene has no concept of inner objects, so Elasticsearch flattens object hierarchies into a simple list of field names and values. For instance, the following document:

PUT my_index/_doc/1
{ "group" : "fans", "user" : [  { "first" : "John", "last" : "Smith" }, { "first" : "Alice", "last" : "White" } ]

The user field is dynamically added as a field of type object.

would be transformed internally into a document that looks more like this:

{ "group" : "fans", "user.first" : [ "alice", "john" ], "user.last" : [ "smith", "white" ]

The user.first and user.last fields are flattened into multi-value fields, and the association between alice and white is lost. This document would incorrectly match a query for alice AND smith:

GET my_index/_search
{ "query": { "bool": { "must": [ { "match": { "user.first": "Alice" }}, { "match": { "user.last": "Smith" }} ] } }

If you need to index arrays of objects and to maintain the independence of each object in the array, you should use the nested datatype instead of the object datatype. Internally, nested objects index each object in the array as a separate hidden document, meaning that each nested object can be queried independently of the others, with the nested query:

PUT my_index
{ "mappings": { "_doc": { "properties": { "user": { "type": "nested"  } } } }
} PUT my_index/_doc/1
{ "group" : "fans", "user" : [ { "first" : "John", "last" : "Smith" }, { "first" : "Alice", "last" : "White" } ]
} GET my_index/_search
{ "query": { "nested": { "path": "user", "query": { "bool": { "must": [ { "match": { "user.first": "Alice" }}, { "match": { "user.last": "Smith" }}  ] } } } }
} GET my_index/_search
{ "query": { "nested": { "path": "user", "query": { "bool": { "must": [ { "match": { "user.first": "Alice" }}, { "match": { "user.last": "White" }}  ] } }, "inner_hits": {  "highlight": { "fields": { "user.first": {} } } } } }

The user field is mapped as type nested instead of type object.

This query doesn’t match because Alice and Smith are not in the same nested object.

This query matches because Alice and White are in the same nested object.

inner_hits allow us to highlight the matching nested documents.

Nested documents can be:

The following parameters are accepted by nested fields:


Because nested documents are indexed as separate documents, they can only be accessed within the scope of the nested query, the nested/reverse_nested aggregations, or nested inner hits.

For instance, if a string field within a nested document has index_options set to offsets to allow use of the postings during the highlighting, these offsets will not be available during the main highlighting phase. Instead, highlighting needs to be performed via nested inner hits.

Indexing a document with 100 nested fields actually indexes 101 documents as each nested document is indexed as a separate document. To safeguard against ill-defined mappings the number of nested fields that can be defined per index has been limited to 50. See Settings to prevent mappings explosionedit.