7.3 Nested Objects (嵌套对象)


文档摘要

7.3 Nested Objects (嵌套对象) Elasticsearch 高级特性:7.3 嵌套对象(Nested Objects)详解 什么是嵌套对象? 嵌套对象本质上是允许你在一个文档内部索引另一个文档。这意味着你可以拥有一个包含对象数组的字段,并且 Elasticsearch 会将数组中的每个对象作为独立的、隐藏的文档进行索引。 关键在于,这些嵌套文档之间保持了相互关联,允许你进行精确的查询,而不受数组元素之间顺序和值的干扰。 为什么需要嵌套对象? 考虑一个博客文章的场景,每篇文章都有多个评论。 如果我们将评论简单地存储为对象数组,Elasticsearch 会将数组扁平化,导致多值字段。

7.3 Nested Objects (嵌套对象)

Elasticsearch 高级特性:7.3 嵌套对象(Nested Objects)详解

1. 什么是嵌套对象?

嵌套对象本质上是允许你在一个文档内部索引另一个文档。这意味着你可以拥有一个包含对象数组的字段,并且 Elasticsearch 会将数组中的每个对象作为独立的、隐藏的文档进行索引。 关键在于,这些嵌套文档之间保持了相互关联,允许你进行精确的查询,而不受数组元素之间顺序和值的干扰。

为什么需要嵌套对象?

考虑一个博客文章的场景,每篇文章都有多个评论。 如果我们将评论简单地存储为对象数组,Elasticsearch 会将数组扁平化,导致多值字段。 这可能会导致以下问题:

  • 不正确的查询结果: 假设你想查找包含特定用户发表的特定内容的评论的文章。 如果使用扁平化的数组,Elasticsearch 可能会返回包含该用户 该内容的评论的文章,即使它们不是同一条评论。

  • 性能问题: 对于大型数组,扁平化会导致索引膨胀和查询效率下降。

嵌套对象解决了这些问题,因为它允许你将每个评论作为独立的文档进行索引,同时保持它们与父文档(博客文章)的关联。

2. 嵌套对象的工作原理

当你在 Elasticsearch 中定义一个字段为 nested 类型时,Elasticsearch 会创建一个特殊的索引结构来存储该字段中的对象。 每个嵌套对象都会被索引为一个独立的文档,但它们与父文档之间存在链接。

以下是一个简单的图示,展示了嵌套对象的工作原理:

在这个图中,父文档是博客文章,嵌套对象是评论。 每个评论都被索引为一个独立的文档,但它们都与父文档相关联。

3. 嵌套对象的代码实践

现在,让我们通过一些代码示例来了解如何在 Elasticsearch 中使用嵌套对象。

3.1 创建包含嵌套对象的索引映射

首先,我们需要创建一个索引映射,定义包含嵌套对象的字段。

PUT /my_index { "mappings": { "properties": { "title": { "type": "text" }, "comments": { "type": "nested", "properties": { "user": { "type": "keyword" }, "content": { "type": "text" }, "rating":{ "type": "integer" } } } } } }

在这个例子中,我们创建了一个名为 my_index 的索引,其中包含一个 comments 字段,其类型为 nestedcomments 字段本身包含 user (keyword类型), content (text类型), rating (integer类型) 三个字段。

3.2 索引包含嵌套对象的文档

接下来,我们可以索引包含嵌套对象的文档。

POST /my_index/_doc { "title": "Elasticsearch Nested Objects Explained", "comments": [ { "user": "john.doe", "content": "Great article!", "rating": 5 }, { "user": "jane.smith", "content": "Very helpful, thanks!", "rating": 4 }, { "user": "john.doe", "content": "I have a question about...", "rating": 3 } ] }

在这个例子中,我们索引了一个包含标题和三个评论的文档。 每个评论都是一个嵌套对象,包含用户名和评论内容。

3.3 查询嵌套对象

现在,让我们看看如何查询嵌套对象。 Elasticsearch 提供了 nested 查询来处理嵌套对象。

示例 1:查找包含用户 "john.doe" 发表的评分为5的评论的文章

GET /my_index/_search { "query": { "nested": { "path": "comments", "query": { "bool": { "must": [ { "term": { "comments.user": "john.doe" } }, { "term":{ "comments.rating": 5 } } ] } } } } }

在这个查询中,我们使用 nested 查询来指定我们要查询的嵌套字段是 commentsquery 部分包含一个 bool 查询,它指定了两个条件:comments.user 必须是 "john.doe",并且 comments.rating 必须是5。 path 属性指定了嵌套对象的路径。

示例 2:查找包含任何评论的文章

GET /my_index/_search { "query": { "nested": { "path": "comments", "query": { "exists": { "field": "comments.content" } } } } }

这个查询查找包含任何评论的文章。 exists 查询检查 comments.content 字段是否存在。

3.4 更新嵌套对象

更新嵌套对象需要使用 update API 和 script。 以下是一个示例:

POST /my_index/_update/YOUR_DOCUMENT_ID { "script": { "source": """ for (int i = 0; i < ctx._source.comments.length; i++) { if (ctx._source.comments[i].user == 'jane.smith') { ctx._source.comments[i].content = 'Updated comment content'; } } """, "lang": "painless" } }

在这个例子中,我们使用 Painless 脚本来遍历 comments 数组,并更新 user 为 "jane.smith" 的评论的内容。 你需要将 YOUR_DOCUMENT_ID 替换为实际的文档 ID。

3.5 删除嵌套对象

删除嵌套对象也需要使用 update API 和 script。 以下是一个示例:

POST /my_index/_update/YOUR_DOCUMENT_ID { "script": { "source": """ ctx._source.comments.removeIf(comment -> comment.user == 'jane.smith'); """, "lang": "painless" } }

这个脚本使用 removeIf 方法来删除 user 为 "jane.smith" 的评论。

4. 嵌套对象与父子关系(Parent-Child Relationship)的区别

Elasticsearch 还提供了父子关系(Parent-Child Relationship)来处理关联数据。 嵌套对象和父子关系之间有一些关键区别:

  • 存储方式: 嵌套对象存储在同一个文档中,而父子关系将父文档和子文档存储为独立的文档。

  • 性能: 嵌套对象通常比父子关系更快,因为它们不需要跨文档连接。

  • 灵活性: 父子关系更灵活,因为它允许你独立地更新和删除父文档和子文档。

  • 复杂性: 嵌套对象更易于设置和管理,而父子关系需要更复杂的映射和查询。

何时使用嵌套对象?

  • 当你的数据具有紧密的、一对多的关系时。

  • 当你需要高性能的查询时。

  • 当你不需要独立地更新和删除子文档时。

何时使用父子关系?

  • 当你的数据具有更松散的关系时。

  • 当你需要独立地更新和删除父文档和子文档时。

  • 当你需要支持更复杂的查询时。

5. 嵌套对象的注意事项

  • 性能: 嵌套对象会增加索引的大小,并可能影响查询性能。 避免过度使用嵌套对象,并只在必要时使用它们。

  • 嵌套深度: Elasticsearch 限制了嵌套对象的深度。 避免创建过深的嵌套结构。

  • 更新: 更新嵌套对象需要使用脚本,这可能会比较复杂。

  • 排序和聚合: 对嵌套对象进行排序和聚合需要使用特殊的语法。

6. 总结

嵌套对象是 Elasticsearch 中一个强大的功能,允许你有效地索引和搜索包含对象数组的文档。 通过了解嵌套对象的工作原理、代码示例和注意事项,你可以更好地利用它们来解决实际问题。

希望本文能够帮助你理解和使用 Elasticsearch 中的嵌套对象。 记住,根据你的具体需求选择合适的数据建模方式,才能充分发挥 Elasticsearch 的优势。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U