[[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].