Nested 数据类型
nested
类型是特殊的object
类型,它可以使对象数组已相对独立的查询方式进行索引。
对象数组是如何展平的
内部对象数组的字段并不是期望的那样工作。Lucene 并没有内部对象的概念,所以 elasticsearch 展平了对象的层级,变成了字段名称和值的简单列表。如:
PUT my_index/_doc/1
{
"group" : "fans",
"user" : [
{
"first" : "John",
"last" : "Smith"
},
{
"first" : "Alice",
"last" : "White"
}
]
}
自动添加了
object
类型的user
字段。
该文档将会在内部转换为如下的文档:
{
"group" : "fans",
"user.first" : [ "alice", "john" ],
"user.last" : [ "smith", "white" ]
}
其中user.first
和user.last
字段将会被展平为多值字段,而alice
与white
的关联关系丢失了。当查询alice AND smith
时会错误的匹配到该文档。
GET my_index/_search
{
"query": {
"bool": {
"must": [
{ "match": { "user.first": "Alice" }},
{ "match": { "user.last": "Smith" }}
]
}
}
}
使用 nested
类型的对象数组
如果希望索引对象数组,并保持数组中每个对象的独立性,应该使用nested
类型,而不是object
类型。在内部,嵌套类型将数组中的对象索引为独立的隐藏文档,意味着使用nested
查询,可以独立的查询每个嵌套对象。
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": {}
}
}
}
}
}
}
user
字段主动映射为nested
类型;第一个查询不会命中,
Alice
andSmith
并不在同一个嵌套文档中;第二个查询成功命中;
inner_hits
可以高亮匹配到的嵌套文档;
嵌套文档可以:
- 使用 nested 查询;
- 使用
nested
andreverse_nested
aggregations 分析; - 使用 nested sorting;
- 获取并高亮,通过 nested inner hits;
nested 类型的参数
dynamic:新属性是否可以动态的添加到 nested 类型的对象中,true(默认),false,strict;
properties:嵌套对象中的字段,可以是任意数据类型,包括 nested。可以将新属性添加到现有的嵌套类型对象中。
注:
因为嵌套类型的文档被索引在独立的文档中,它们仅可以通过
nested
查询、nested
/reverse_nested
聚合,或者 nested inner hits 访问。例如,嵌套文档中的一个字符串字段设置了
index_options
为offset
to allow use of the postings,在标记阶段,这些 offsets 在主要标记阶段不会生效。相反,高亮操作需要通过 nested inner hits 执行。(不懂这句)
限制 nested
类型字段的数量
索引一个 100 个嵌套字段的文档,实际上索引了 101 个文档(一个嵌套字段会产生一个隐藏文档,并不是一个嵌套数组的对象产生一个隐藏文档???),因为每一个嵌套文档都被索引一个单独的文档。为了防止定义不明确的映射,每个索引可以定义的嵌套字段数量限制在 50 个。