[[nested]]
=== Nested(嵌套)数据类型
nested 类型是一种特殊的 [object,object] 类型.
这种类型允许对 object 数组内的元素进行单独查询.
object 数组是怎么展开(flatten)的
[object,object] 数组的功能可能跟你想象中的不太一样.
Lucene 没有内部 object 的概念, 所以 Elasticsearch 内部会把 object 解析成简单的字段名与值的信息,
以下面这个文档为例:
[source,js]
PUT my_index/_doc/1
{
"group" : "fans",
"user" : [ <1>
{
"first" : "John",
"last" : "Smith"
},
{
"first" : "Alice",
"last" : "White"
}
]
}<1> user 被字段配置为 object 字段.
内部会把文档转化为类似与下面这种形式:
[source,js]
{
"group" : "fans",
"user.first" : [ "alice", "john" ],
"user.last" : [ "smith", "white" ]
}user.first 和 user.last 被展开成多值字段,
而且 alice 与 white 之间的关系被丢弃了.
这个文档可能会错误地匹配 alice AND smith.
[source,js]
GET my_index/_search
{
"query": {
"bool": {
"must": [
{ "match": { "user.first": "Alice" }},
{ "match": { "user.last": "Smith" }}
]
}
}
}将 object 数组字段配置为 nested
如果你需要保留 object 数组中每个对象的内部关系, 则需要使用 nested 类型, 而不是 [object,object] 类型.
Elasticsearch 内部会把数组中的每个元素当成一个隐藏文档, 所以可以用 [query-dsl-nested-query,nested query]
单独对每个元素进行查询:
[source,js]
PUT my_index
{
"mappings": {
"_doc": {
"properties": {
"user": {
"type": "nested" <1>
}
}
}
}
}
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" }} <2>
]
}
}
}
}
}
GET my_index/_search
{
"query": {
"nested": {
"path": "user",
"query": {
"bool": {
"must": [
{ "match": { "user.first": "Alice" }},
{ "match": { "user.last": "White" }} <3>
]
}
},
"inner_hits": { <4>
"highlight": {
"fields": {
"user.first": {}
}
}
}
}
}
}<1> user 被配置为 nested 而不是 object.
<2> 无法查询到数据, 因为 Alice 和 Smith 不在同一个 nested object.
<3> 可以查询到数据, 因为 Alice 和 White 在相同一个 nested object.
<4> inner_hits 允许高亮匹配到的 nested 文档.
Nested 文档可以:
- 用 [query-dsl-nested-query,
nested] 进行查询. - 用 [search-aggregations-bucket-nested-aggregation,
nested]
和 [search-aggregations-bucket-reverse-nested-aggregation,reverse_nested]
进行聚合分析. - 用 [nested-sorting,nested sorting] 进行排序.
- 用 [nested-inner-hits,nested inner hits] 获取和高亮.
[[nested-params]]
nested 的参数
nested 字段支持以下参数:
[horizontal]
[dynamic,dynamic]:
是否把新的 `属性` 自动添加到已有的嵌套对象. 接收 `true` (默认), `false` 和 `strict`.
[properties,properties]:
嵌套对象包含的字段, 可以是任意的
[mapping-types,数据类型], 包括 `nested`, 新的 `属性` 可能会被添加到已有的嵌套对象.
[IMPORTANT]
因为 nested 文档被索引为单独的文档, 所以只能使用 nested 查询, nested/reverse_nested 聚合, 或者用 [nested-inner-hits,nested inner hits].
例如, 对一个 nested 文档中的 string 字段用 [index-options,index_options] 对 offsets 进行设置, 是没有用的.
需要用 [nested-inner-hits,nested inner hits].
=============================================
限制 nested 字段的数量
索引一个有 100个 nested 字段的文档, 实际上需要索引 101 个文档, 因为每个嵌套对象会被当成一个隐藏文档.
为了防止某些错误配置的 mapping, nested 字段的数量可以限制为每个 index 最多 50 个. 详情参考 [mapping-limit-settings].