Nested datatype
editNested datatype
editThe 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.
How arrays of objects are flattened
editArrays 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"
}
]
}
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" }}
]
}
}
}
Using nested fields for arrays of objects
editIf 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": {
"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 |
|
|
This query doesn’t match because |
|
|
This query matches because |
|
|
|
Nested documents can be:
-
queried with the
nestedquery. -
analyzed with the
nestedandreverse_nestedaggregations. - sorted with nested sorting.
- retrieved and highlighted with nested inner hits.
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. The same consideration applies when loading
fields during a search through docvalue_fields
or stored_fields.
Parameters for nested fields
editThe following parameters are accepted by nested fields:
|
Whether or not new |
|
|
The fields within the nested object, which can be of any
datatype, including |
Limits on nested mappings and objects
editAs described earlier, each nested object is indexed as a separate document under the hood.
Continuing with the example above, if we indexed a single document containing 100 user objects,
then 101 Lucene documents would be created — one for the parent document, and one for each
nested object. Because of the expense associated with nested mappings, Elasticsearch puts
settings in place to guard against performance problems:
-
index.mapping.nested_fields.limit -
The
nestedtype should only be used in special cases, when arrays of objects need to be queried independently of each other. To safeguard against poorly designed mappings, this setting limits the number of uniquenestedtypes per index. In our example, theusermapping would count as only 1 towards this limit. Defaults to 50. -
index.mapping.nested_objects.limit -
This setting limits the number of nested objects that a single document may contain across all
nestedtypes, in order to prevent out of memory errors when a document contains too many nested objects. To illustrate how the setting works, say we added anothernestedtype calledcommentsto our example mapping above. Then for each document, the combined number ofuserandcommentobjects it contains must be below the limit. Defaults to 10000.
Additional background on these settings, including information on their default values, can be found in Settings to prevent mappings explosion.