elaticsearch (21) elasticsearch的nested object

探讨了在Elasticsearch中使用Nested Object类型相对于Object类型的优点,通过具体案例展示了Nested Object如何解决Object类型在搜索复杂嵌套数据时的局限性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、做一个实验,引出来为什么需要nested object

冗余数据方式的来建模,其实用的就是object类型,我们这里又要引入一种新的object类型,nested object类型

博客,评论,做的这种数据模型

PUT /website/blogs/6
{
  "title": "花无缺发表的一篇帖子",
  "content":  "我是花无缺,大家要不要考虑一下投资房产和买股票的事情啊。。。",
  "tags":  [ "投资", "理财" ],
  "comments": [ 
    {
      "name":    "小鱼儿",
      "comment": "什么股票啊?推荐一下呗",
      "age":     28,
      "stars":   4,
      "date":    "2016-09-01"
    },
    {
      "name":    "黄药师",
      "comment": "我喜欢投资房产,风,险大收益也大",
      "age":     31,
      "stars":   5,
      "date":    "2016-10-22"
    }
  ]
}

被年龄是28岁的黄药师评论过的博客,搜索

GET /website/blogs/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "comments.name": "黄药师" }},
        { "match": { "comments.age":  28      }} 
      ]
    }
  }
}

{
  "took": 102,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 1.8022683,
    "hits": [
      {
        "_index": "website",
        "_type": "blogs",
        "_id": "6",
        "_score": 1.8022683,
        "_source": {
          "title": "花无缺发表的一篇帖子",
          "content": "我是花无缺,大家要不要考虑一下投资房产和买股票的事情啊。。。",
          "tags": [
            "投资",
            "理财"
          ],
          "comments": [
            {
              "name": "小鱼儿",
              "comment": "什么股票啊?推荐一下呗",
              "age": 28,
              "stars": 4,
              "date": "2016-09-01"
            },
            {
              "name": "黄药师",
              "comment": "我喜欢投资房产,风,险大收益也大",
              "age": 31,
              "stars": 5,
              "date": "2016-10-22"
            }
          ]
        }
      }
    ]
  }
}

结果是。。。好像不太对啊???

object类型数据结构的底层存储。。。

{
  "title":            [ "花无缺", "发表", "一篇", "帖子" ],
  "content":             [ "我", "是", "花无缺", "大家", "要不要", "考虑", "一下", "投资", "房产", "买", "股票", "事情" ],
  "tags":             [ "投资", "理财" ],
  "comments.name":    [ "小鱼儿", "黄药师" ],
  "comments.comment": [ "什么", "股票", "推荐", "我", "喜欢", "投资", "房产", "风险", "收益", "大" ],
  "comments.age":     [ 28, 31 ],
  "comments.stars":   [ 4, 5 ],
  "comments.date":    [ 2016-09-01, 2016-10-22 ]
}

object类型底层数据结构,会将一个json数组中的数据,进行扁平化

所以,直接命中了这个document,name=黄药师,age=28,正好符合

 

2、引入nested object类型,来解决object类型底层数据结构导致的问题

修改mapping,将comments的类型从object设置为nested

PUT /website
{
  "mappings": {
    "blogs": {
      "properties": {
        "comments": {
          "type": "nested", 
          "properties": {
            "name":    { "type": "string"  },
            "comment": { "type": "string"  },
            "age":     { "type": "short"   },
            "stars":   { "type": "short"   },
            "date":    { "type": "date"    }
          }
        }
      }
    }
  }
}


  "comments.name":    [ "小鱼儿" ],
  "comments.comment": [ "什么", "股票", "推荐" ],
  "comments.age":     [ 28 ],
  "comments.stars":   [ 4 ],
  "comments.date":    [ 2014-09-01 ]
}

  "comments.name":    [ "黄药师" ],
  "comments.comment": [ "我", "喜欢", "投资", "房产", "风险", "收益", "大" ],
  "comments.age":     [ 31 ],
  "comments.stars":   [ 5 ],
  "comments.date":    [ 2014-10-22 ]
}

  "title":            [ "花无缺", "发表", "一篇", "帖子" ],
  "body":             [ "我", "是", "花无缺", "大家", "要不要", "考虑", "一下", "投资", "房产", "买", "股票", "事情" ],
  "tags":             [ "投资", "理财" ]
}

再次搜索,成功了。。。

GET /website/blogs/_search 
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "title": "花无缺"
          }
        },
        {
          "nested": {
            "path": "comments",
            "query": {
              "bool": {
                "must": [
                  {
                    "match": {
                      "comments.name": "黄药师"
                    }
                  },
                  {
                    "match": {
                      "comments.age": 28
                    }
                  }
                ]
              }
            }
          }
        }
      ]
    }
  }
}
 

<think>嗯,用户问的是Elasticsearchobjectnested类型的优势。首先,我需要回忆一下这两种数据类型的基本概念和区别。Object类型是Elasticsearch默认的嵌套结构,适用于简单的键值对嵌套,而Nested类型则用于处理更复杂的嵌套对象,特别是当子对象需要独立查询的时候。 我应该先解释为什么需要这两种类型。传统上,在Elasticsearch中,如果一个字段是对象类型,数组中的多个对象会被扁平化为多个字段,导致数据之间的关联丢失。例如,一个用户有多个订单,每个订单有商品和数量,如果用object类型存储,查询时可能会出现错误匹配,因为各个订单的数据会被合并。这时候就需要nested类型来保持每个对象的独立性,确保查询准确。 接下来,需要分别说明objectnested的优势。对于object类型,优势可能在于简单易用,不需要额外配置,存储和查询效率高,适合不需要维护数组元素独立性的场景。而nested类型则通过内部维护隐藏的文档,使得每个嵌套对象可以独立索引和查询,适合需要精准匹配多个字段的情况,比如电商中的订单或博客的评论。 然后要比较两者的区别,比如内部结构、查询方式、性能差异。Object类型数组中的对象会被扁平化,导致跨对象的字段查询不准确;而nested类型每个对象都是独立的,可以精确查询。查询时,object使用普通的查询方式,而nested需要使用专门的nested查询。性能方面,nested因为要维护更多文档,可能在写入和查询时开销更大。 应用场景方面,object适用于简单的嵌套结构,比如用户的地址,而nested适合需要维护独立性的数组对象,如订单、评论等。最后给出选择建议,根据是否需要独立查询来决定使用哪种类型。 需要确保回答结构清晰,分点说明优势、区别和应用场景,同时用例子帮助理解。还要注意使用正确的LaTeX格式,虽然这里可能用不到数学公式,但如果有的话要按照规则处理。另外,语言要口语化,避免技术术语过于密集,让用户容易理解。</think>Elasticsearch 中 `object` 和 `nested` 是两种处理嵌套数据的核心类型,它们的优势和适用场景如下: --- ### **一、Object 类型的优势** 1. **简单嵌套场景** - 适用场景:单层键值对嵌套(如 `用户信息` → `地址`)。 - 示例:存储 `{"user": {"name": "张三", "age": 30}}`,通过 `user.name` 直接查询。 2. **存储和查询效率高** - Object 字段的子属性会被扁平化为普通字段(如 `user.name`),索引和查询性能接近原生字段。 3. **自动映射** - Elasticsearch 自动识别嵌套对象为 `object` 类型,无需显式声明。 --- ### **二、Nested 类型的优势** 1. **保持数组元素的独立性** - **问题背景**:当对象数组(如多个订单)使用 `object` 类型时,Elasticsearch 会将其扁平化,导致跨元素的字段错误关联。 **示例**: 数据:`{"orders": [{"product": "A", "quantity": 2}, {"product": "B", "quantity": 3}]}` `object` 类型查询 `product:A AND quantity:3` 会错误匹配(因为字段被合并为 `["A", "B"]` 和 `[2, 3]`)。 **nested 解决方案**:每个数组元素独立存储和索引,确保查询精确性。 2. **支持复杂查询** - 使用 `nested` 查询和聚合,可精准匹配同一子对象的多个字段。 **查询示例**: ```json { "query": { "nested": { "path": "orders", "query": { "bool": { "must": [ { "term": { "orders.product": "A" } }, { "term": { "orders.quantity": 2 } } ] } } } } } ``` 3. **独立评分机制** - 每个 `nested` 对象独立计算相关性得分(如 `nested` 子查询的 `score_mode` 参数)。 --- ### **三、核心区别对比** | **特性** | **Object 类型** | **Nested 类型** | |------------------------|----------------------------------|----------------------------------| | 内部结构 | 子字段扁平化存储 | 每个数组元素存储为独立隐藏文档 | | 数组元素独立性 | ❌ 元素间字段混合 | ✅ 元素间完全独立 | | 查询方式 | 普通查询(如 `term`) | 必须使用 `nested` 查询 | | 性能 | 高(无额外开销) | 较低(维护更多文档) | | 适用场景 | 简单嵌套(无跨元素查询需求) | 复杂嵌套(需精准匹配子对象字段) | --- ### **四、如何选择?** 1. **使用 `object` 的场景** - 无需维护数组元素的独立性(如用户的多个电话号码)。 - 查询逻辑简单,无跨元素字段匹配需求。 2. **使用 `nested` 的场景** - 需要精确匹配数组元素的多个字段(如订单中的商品和数量组合)。 - 需要聚合或排序嵌套对象内的字段(如统计每个商品的销量)。 --- ### **五、总结** - **`object`**:简单高效,适合轻量级嵌套。 - **`nested`**:解决数组元素独立性丢失问题,适合复杂查询场景。 实际选择需权衡查询需求与性能成本。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值