嵌套字段类型
1.0 版引入
嵌套字段类型是一种特殊的对象字段类型。
任何对象字段都可以接受对象数组。数组中的每个对象都被动态映射为对象字段类型并以扁平化形式存储。这意味着数组中的对象被分解为单独的字段,并且所有对象中每个字段的值都存储在一起。有时需要使用嵌套类型来将嵌套对象作为一个整体保留,以便您可以对其执行搜索。
扁平化形式
默认情况下,每个嵌套对象都被动态映射为对象字段类型。任何对象字段都可以接受对象数组。
PUT testindex1/_doc/100
{
"patients": [
{"name" : "John Doe", "age" : 56, "smoker" : true},
{"name" : "Mary Major", "age" : 85, "smoker" : false}
]
}
当这些对象存储时,它们会被扁平化,因此其内部表示形式为每个字段的所有值的数组。
{
"patients.name" : ["John Doe", "Mary Major"],
"patients.age" : [56, 85],
"patients.smoker" : [true, false]
}
某些查询在这种表示形式下将正常工作。如果您搜索年龄大于 75 岁或吸烟的患者,文档 100 应该匹配。
GET testindex1/_search
{
"query": {
"bool": {
"should": [
{
"term": {
"patients.smoker": true
}
},
{
"range": {
"patients.age": {
"gte": 75
}
}
}
]
}
}
}
该查询正确返回文档 100。
{
"took" : 3,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.3616575,
"hits" : [
{
"_index" : "testindex1",
"_type" : "_doc",
"_id" : "100",
"_score" : 1.3616575,
"_source" : {
"patients" : [
{
"name" : "John Doe",
"age" : "56",
"smoker" : true
},
{
"name" : "Mary Major",
"age" : "85",
"smoker" : false
}
]
}
}
]
}
}
或者,如果您搜索年龄大于 75 岁且吸烟的患者,文档 100 不应匹配。
GET testindex1/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"patients.smoker": true
}
},
{
"range": {
"patients.age": {
"gte": 75
}
}
}
]
}
}
}
然而,此查询仍然错误地返回文档 100。这是因为在为单个字段创建值数组时,年龄和吸烟之间的关系丢失了。
嵌套字段类型
嵌套对象作为单独的文档存储,父对象引用其子对象。要将对象标记为嵌套,请创建具有嵌套字段类型的映射。
PUT testindex1
{
"mappings" : {
"properties": {
"patients": {
"type" : "nested"
}
}
}
}
然后,索引一个具有嵌套字段类型的文档
PUT testindex1/_doc/100
{
"patients": [
{"name" : "John Doe", "age" : 56, "smoker" : true},
{"name" : "Mary Major", "age" : 85, "smoker" : false}
]
}
您可以使用以下嵌套查询来搜索年龄大于 75 岁或吸烟的患者
GET testindex1/_search
{
"query": {
"nested": {
"path": "patients",
"query": {
"bool": {
"should": [
{
"term": {
"patients.smoker": true
}
},
{
"range": {
"patients.age": {
"gte": 75
}
}
}
]
}
}
}
}
}
该查询正确返回两位患者。
{
"took" : 7,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 0.8465736,
"hits" : [
{
"_index" : "testindex1",
"_id" : "100",
"_score" : 0.8465736,
"_source" : {
"patients" : [
{
"name" : "John Doe",
"age" : 56,
"smoker" : true
},
{
"name" : "Mary Major",
"age" : 85,
"smoker" : false
}
]
}
}
]
}
}
您可以使用以下嵌套查询来搜索年龄大于 75 岁且吸烟的患者
GET testindex1/_search
{
"query": {
"nested": {
"path": "patients",
"query": {
"bool": {
"must": [
{
"term": {
"patients.smoker": true
}
},
{
"range": {
"patients.age": {
"gte": 75
}
}
}
]
}
}
}
}
}
前一个查询没有返回结果,符合预期。
{
"took" : 7,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 0,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
}
}
参数
下表列出了对象字段类型接受的参数。所有参数都是可选的。
参数 | 描述 |
---|---|
dynamic | 指定是否可以将新字段动态添加到对象。有效值为 true 、false 、strict 和 strict_allow_templates 。默认值为 true 。 |
include_in_parent | 一个布尔值,指定子嵌套对象中的所有字段是否也应以扁平化形式添加到父文档中。默认值为 false 。 |
include_in_root | 一个布尔值,指定子嵌套对象中的所有字段是否也应以扁平化形式添加到根文档中。默认值为 false 。 |
properties | 此对象的字段,可以是任何支持的类型。如果 dynamic 设置为 true ,则可以动态添加新属性到此对象。 |