ElasticSearch的Nested(嵌套)数据类型

[[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.firstuser.last 被展开成多值字段,
而且 alicewhite 之间的关系被丢弃了.
这个文档可能会错误地匹配 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> 无法查询到数据, 因为 AliceSmith 不在同一个 nested object.
<3> 可以查询到数据, 因为 AliceWhite 在相同一个 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].

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值