Elasticsearch 中的 **Nested 数据结构** 和 **Object 结构** 是处理复杂数据类型的两种核心机制,其根本区别在于 **数据存储方式** 和 **查询逻辑**。
---
### 一、根本区别
| **维度** | **Object 结构** | **Nested 结构** |
|--------------------|-----------------------------------------------------|-----------------------------------------------------|
| **存储方式** | 数组对象被扁平化为键值对列表,失去对象间关联性 | 每个嵌套对象作为独立隐藏文档存储,保留字段间关联性 |
| **查询逻辑** | 使用点号(`.`)直接查询字段,但数组元素间逻辑为“或”关系 | 必须通过 `nested` 查询,支持数组元素的“且”逻辑 |
| **索引开销** | 低(字段合并存储) | 高(每个嵌套对象独立索引) |
| **适用场景** | 无需独立查询子对象字段的简单嵌套 | 需要精确匹配数组元素内部字段的场景(如评论、标签) |
#### 示例说明:
假设存储用户评论数组:
```json
"comments": [
{ "user": "A", "text": "Good" },
{ "user": "B", "text": "Bad" }
]
```
• **Object 存储**:字段会被打平为 `comments.user: ["A", "B"]` 和 `comments.text: ["Good", "Bad"]`,查询 `user:A AND text:Bad` 会错误匹配到该文档。
• **Nested 存储**:每个评论作为独立文档索引,仅匹配 `user:A AND text:Bad` 时无结果返回。
---
### 二、如何使用 Nested 结构
#### 1. **定义 Mapping**
需显式声明字段类型为 `nested`,并定义子字段属性:
```json
PUT /my_index
{
"mappings": {
"properties": {
"comments": {
"type": "nested",
"properties": {
"user": { "type": "keyword" },
"text": { "type": "text" }
}
}
}
}
}
```
#### 2. **查询语法**
必须使用 `nested` 查询,指定路径(`path`)和子查询条件:
```json
GET /my_index/_search
{
"query": {
"nested": {
"path": "comments",
"query": {
"bool": {
"must": [
{ "match": { "comments.user": "A" } },
{ "match": { "comments.text": "Good" } }
]
}
}
}
}
}
```
#### 3. **聚合操作**
需结合 `nested` 聚合和 `reverse_nested` 跳出嵌套层级:
```json
GET /my_index/_search
{
"aggs": {
"comment_agg": {
"nested": { "path": "comments" },
"aggs": {
"user_terms": {
"terms": { "field": "comments.user" },
"aggs": {
"back_to_root": {
"reverse_nested": {},
"aggs": { "avg_rating": { "avg": { "field": "rating" } } }
}
}
}
}
}
}
}
```
---
### 三、如何使用 Object 结构
#### 1. **默认行为**
未显式声明时,ES 自动将 JSON 对象映射为 `object` 类型:
```json
PUT /my_index/_doc/1
{
"address": {
"street": "Main St",
"city": "New York"
}
}
```
#### 2. **查询语法**
直接使用点号访问字段:
```json
GET /my_index/_search
{
"query": { "term": { "address.city": "New York" } }
}
```
---
### 四、选型建议
| **场景** | **推荐类型** | **理由** |
|------------------------------|--------------|--------------------------------------------------------------------------|
| 单层对象(如用户地址) | Object | 结构简单,查询高效 |
| 数组对象需独立查询(如评论) | Nested | 避免跨对象错误匹配 |
| 高频更新的动态标签 | Flattened | 替代 Nested,降低更新开销(需 ES 7.3+) |
---
### 五、性能注意事项
1. **Nested 更新成本高**:修改嵌套对象需重建整个父文档索引。
2. **避免深度嵌套**:超过 2 层嵌套会显著影响查询性能。
3. **字段数量控制**:Nested 结构适合字段数可控的场景,避免因字段爆炸导致内存压力。
通过合理选择数据结构,可显著提升 Elasticsearch 在处理复杂数据时的准确性和效率。实际应用中需结合查询需求、数据更新频率和性能要求综合权衡。
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传