Elasticsearch权威指南:深入理解嵌套对象(Nested Objects)

Elasticsearch权威指南:深入理解嵌套对象(Nested Objects)

elasticsearch-definitive-guide The Definitive Guide to Elasticsearch elasticsearch-definitive-guide 项目地址: https://gitcode.com/gh_mirrors/el/elasticsearch-definitive-guide

嵌套对象的概念与背景

在Elasticsearch中,嵌套对象(Nested Objects)是一种特殊的数据类型,用于解决对象数组(object arrays)在搜索时出现的关联性问题。当我们需要存储具有一对多关系的实体时,比如博客文章与评论、订单与订单项等,嵌套对象提供了完美的解决方案。

为什么需要嵌套对象?

普通对象数组的问题

当我们使用普通对象数组存储关联数据时,例如博客文章及其评论:

{
  "title": "Nest eggs",
  "comments": [
    {
      "name": "John Smith",
      "age": 28
    },
    {
      "name": "Alice White",
      "age": 31
    }
  ]
}

Elasticsearch内部会将这个结构扁平化处理,导致所有评论的属性值被合并在一起:

{
  "comments.name": ["John", "Smith", "Alice", "White"],
  "comments.age": [28, 31]
}

这种扁平化处理会带来严重的关联性问题。例如,搜索"name:Alice AND age:28"会错误地匹配到文档,因为Elasticsearch无法知道Alice实际上31岁而不是28岁。

嵌套对象的解决方案

嵌套对象通过将每个数组元素作为独立的隐藏文档来索引,完美解决了这个问题。对于同样的数据,使用嵌套类型后,内部存储形式变为:

// 第一个评论
{
  "comments.name": ["John", "Smith"],
  "comments.age": [28]
}

// 第二个评论
{
  "comments.name": ["Alice", "White"],
  "comments.age": [31]
}

// 主文档
{
  "title": ["Nest", "eggs"]
}

这样,每个评论对象的字段关系得以保持,搜索条件只会匹配同一嵌套对象内的字段。

如何使用嵌套对象

定义嵌套映射

要使用嵌套对象,首先需要在映射中明确指定字段类型为nested

PUT /my_index
{
  "mappings": {
    "blogpost": {
      "properties": {
        "comments": {
          "type": "nested", 
          "properties": {
            "name":    { "type": "text"  },
            "comment": { "type": "text"  },
            "age":     { "type": "short"   },
            "stars":   { "type": "short"   },
            "date":    { "type": "date"    }
          }
        }
      }
    }
  }
}

查询嵌套对象

查询嵌套对象需要使用特殊的nested查询:

GET /_search
{
  "query": {
    "nested": {
      "path": "comments",
      "query": {
        "bool": {
          "must": [
            { "match": { "comments.name": "Alice" }},
            { "match": { "comments.age":  28      }} 
          ]
        }
      }
    }
  }
}

这个查询现在会正确地返回空结果,因为Alice的年龄是31而不是28。

嵌套对象的工作原理

  1. 索引过程:当索引包含嵌套对象的文档时,Elasticsearch会:

    • 将主文档作为一个独立文档索引
    • 将每个嵌套对象作为隐藏的独立文档索引
    • 维护主文档与嵌套文档之间的关系
  2. 查询过程:当执行嵌套查询时,Elasticsearch会:

    • 先在嵌套文档中执行查询
    • 然后通过内部关系找到匹配的主文档
    • 最后返回完整的主文档

嵌套对象的限制与注意事项

  1. 性能考虑:虽然嵌套查询比父子文档(Join)性能更好,但大量嵌套对象会增加索引大小和查询复杂度。

  2. 更新操作:要更新嵌套对象,必须重新索引整个主文档,无法单独更新某个嵌套对象。

  3. 返回结果:搜索结果总是返回完整的主文档,无法单独返回嵌套对象。

  4. 嵌套深度:Elasticsearch只支持单层嵌套,不能在嵌套对象中再嵌套对象。

实际应用场景

嵌套对象非常适合以下场景:

  • 博客文章与评论
  • 订单与订单项
  • 产品与产品规格
  • 问卷调查与问题选项

在这些场景中,如果需要在查询时保持对象内部的字段关联性,嵌套对象是最佳选择。

总结

嵌套对象是Elasticsearch中处理一对多关系的强大工具,它通过内部将每个数组元素作为独立文档索引,解决了普通对象数组的关联性问题。虽然使用上比普通对象复杂一些,但对于需要精确查询关联字段的场景,嵌套对象提供了完美的解决方案。

elasticsearch-definitive-guide The Definitive Guide to Elasticsearch elasticsearch-definitive-guide 项目地址: https://gitcode.com/gh_mirrors/el/elasticsearch-definitive-guide

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

贡锨庆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值