ES object与nested
ES object与nested
在 ES 中,object 和 nested 是用来表示复杂 JSON 结构的两种字段类型
object 类型
object 类型是最基本的嵌套结构,用来表示 JSON 对象中的字段。这些字段会被扁平化存储在同一个文档中。
使用场景
- 当你需要存储一个简单的对象或键值对,并且不需要在查询时进行复杂的关联操作。
- 适合处理非数组的嵌套结构,或者数组中的元素之间不需要保持独立的关联。
定义方式
1 | PUT /my_index |
存储的数据
1 | PUT /my_index/_doc/1 |
查询示例
对于 object 类型,查询是基于字段的简单扁平化索引。
1 | GET /my_index/_search |
优缺点
- 优点:适合简单嵌套对象,查询性能较好,易于使用。
- 缺点:当对象嵌套在数组中时,查询的关联性问题可能无法得到正确处理(比如数组中的多个元素之间的关联关系会丢失)。
扁平化问题
当对象存储为 object 类型时,所有字段都会被扁平化。这意味着如果存储的是数组,多个元素的字段值会被简单地索引在一起,查询时可能会返回意想不到的结果。
nested 类型
nested 类型用于存储嵌套的数组,并保持每个数组元素之间的独立性。Elasticsearch 会为每个数组元素创建独立的文档,因此可以保证数组中的对象之间不会因为扁平化而失去关联性。
使用场景
- 当你需要存储一个复杂的对象数组,并且希望数组中的每个对象在查询时保持独立的关联性(即查询时不会因为扁平化造成不准确的匹配)。
- 适合处理需要复杂查询条件的对象数组。
定义方式
1 | PUT /my_index |
存储的数据
1 | PUT /my_index/_doc/1 |
查询示例
使用 nested 类型时,你需要明确指定 nested 查询,来保证查询的精确性。
查询评论中 author 为 “Alice” 且 likes 为 5 的文档:
1 | GET /my_index/_search |
优缺点
- 优点:支持嵌套数组的精确查询,能正确处理数组中对象之间的关系。
- 缺点:由于每个数组元素被独立索引,因此存储和查询的性能成本更高(相比
object类型)。
区别总结
| 特性 | object 类型 |
nested 类型 |
|---|---|---|
| 结构 | 文档中简单的嵌套对象 | 适用于数组中的嵌套对象 |
| 存储方式 | 扁平化存储在同一个文档中 | 每个数组元素独立存储,关联性保持 |
| 查询关联性 | 扁平化可能导致数组中不同对象字段混淆 | 维持数组中对象之间的独立性 |
| 查询语法 | 普通查询 | 需要使用 nested 查询 |
| 性能 | 查询性能较好,适合简单结构 | 查询性能较低,适合复杂数组结构 |
| 适用场景 | 适合简单对象或非数组结构 | 适合需要复杂查询的嵌套数组 |
什么时候使用 object,什么时候使用 nested
使用 object 类型:
- 数据结构较为简单,没有数组,或者数组中的字段之间不需要保持严格的关联。
- 需要较高的查询性能,且不需要处理复杂的嵌套查询逻辑。
- 查询需求不涉及对嵌套数组内部对象的精确匹配。
使用 nested 类型:
- 需要存储嵌套的对象数组,且数组中的对象需要在查询时保持独立性。
- 需要对嵌套数组的内部对象进行复杂的查询,确保精确匹配(如数组中的某个对象的多个字段必须同时满足查询条件)。
- 愿意为了精确查询支付更高的性能和存储成本。
实例对比
object 类型的查询误差:
假设你存储了如下数据(对象数组形式):
1 | PUT /my_index/_doc/1 |
你执行以下查询:
1 | GET /my_index/_search |
结果可能会匹配到这个文档,尽管实际数据中 "Alice" 的年龄是 30,而不是 40。因为 object 类型会扁平化字段,导致查询结果混淆。
nested 类型的精确匹配:
相同的数据如果定义为 nested 类型,则可以避免这个问题:
1 | PUT /my_index |
当你执行相同的查询时:
1 | GET /my_index/_search |
此时,查询将不会返回错误的结果,因为 nested 保证了数组元素的独立性。
总结
object类型 适用于简单的对象结构,不会引起数组字段之间的混淆。nested类型 适合复杂的嵌套对象数组,能够在查询时维持元素的独立性,避免因为扁平化引起的数据不一致问题。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CautionX!
