Elasticsearch 数据建模详解:nested vs parent-child

Elasticsearch 数据建模详解:nested vs parent-child(高级工程师必会)

这篇文档只讲 ES 数据建模里最容易踩坑、也是最容易拉开水平差距的两块
nestedparent-child(join)

目标:让你在面试和真实项目里都能选对模型、讲清原理、说明取舍


1. 为什么 Elasticsearch 的"对象数组"会坑人?

先看一个直觉正确、但 ES 默认是错的例子。

1.1 业务数据(商品 + 属性)

json 复制代码
{
  "id": "p1",
  "attrs": [
    { "name": "color", "value": "red" },
    { "name": "size",  "value": "L" }
  ]
}

1.2 你想查的条件

color = red AND size = L(同一个商品)

1.3 默认 object 的真实存储方式(重点)

ES 会把数组对象 扁平化 成这样:

text 复制代码
attrs.name  = ["color", "size"]
attrs.value = ["red", "L"]

于是这个查询:

json 复制代码
{
  "bool": {
    "must": [
      { "term": { "attrs.name": "color" } },
      { "term": { "attrs.value": "L" } }
    ]
  }
}

可能匹配到不存在的组合

(color=red + size=L 并不在同一个对象里)


2. nested:解决"对象内强一致匹配"

2.1 nested 的本质

  • 每个 nested 对象在底层是 独立隐藏文档
  • 查询时通过 nested query 约束"同一个对象内"

👉 代价:
查询更贵,但语义绝对正确


2.2 mapping 定义(nested)

json 复制代码
PUT product
{
  "mappings": {
    "properties": {
      "id": { "type": "keyword" },
      "attrs": {
        "type": "nested",
        "properties": {
          "name":  { "type": "keyword" },
          "value": { "type": "keyword" }
        }
      }
    }
  }
}

2.3 nested 查询示例(核心)

json 复制代码
GET product/_search
{
  "query": {
    "nested": {
      "path": "attrs",
      "query": {
        "bool": {
          "must": [
            { "term": { "attrs.name": "color" } },
            { "term": { "attrs.value": "red" } }
          ]
        }
      }
    }
  }
}

✔️ 只匹配同一个 attrs 对象


2.4 Spring Boot 示例(nested)

java 复制代码
NestedQueryBuilder nestedQuery =
    QueryBuilders.nestedQuery(
        "attrs",
        QueryBuilders.boolQuery()
            .must(QueryBuilders.termQuery("attrs.name", "color"))
            .must(QueryBuilders.termQuery("attrs.value", "red")),
        ScoreMode.None
    );

2.5 nested 的典型使用场景

  • 商品属性(key-value)
  • 标签 + 权重
  • 条件组合必须在同一元素内

2.6 nested 的代价(面试要说)

  • 每个 nested 元素 = 一个隐藏文档
  • nested 多 → 文档数膨胀
  • 查询需要 join-like 过程 → CPU 成本高

3. parent-child(join):解决"文档独立生命周期"

3.1 parent-child 解决什么问题?

当你遇到这些情况:

  • 子对象数量非常多
  • 子对象频繁更新
  • 不想因为改一个子对象而重写整个父文档

👉 parent-child 更合适


3.2 mapping 定义(join 类型)

json 复制代码
PUT order
{
  "mappings": {
    "properties": {
      "relation": {
        "type": "join",
        "relations": {
          "order": "order_item"
        }
      }
    }
  }
}

3.3 写入示例

父文档
json 复制代码
PUT order/_doc/1
{
  "relation": "order",
  "orderNo": "O20250001"
}
子文档(必须 routing 到父)
json 复制代码
PUT order/_doc/2?routing=1
{
  "relation": {
    "name": "order_item",
    "parent": "1"
  },
  "skuId": "sku-1",
  "price": 100
}

3.4 parent → child 查询

json 复制代码
GET order/_search
{
  "query": {
    "has_child": {
      "type": "order_item",
      "query": {
        "range": {
          "price": { "gte": 100 }
        }
      }
    }
  }
}

3.5 child → parent 查询

json 复制代码
GET order/_search
{
  "query": {
    "has_parent": {
      "parent_type": "order",
      "query": {
        "term": { "orderNo": "O20250001" }
      }
    }
  }
}

4. nested vs parent-child 正面硬对比(必背)

维度 nested parent-child
数据存储 同一文档 独立文档
查询性能 较快 更慢
更新成本 高(重写父文档) 低(只改子文档)
子对象数量 少~中
查询语义 强一致 强一致
实现复杂度

5. 真实项目选型口诀(面试直接说)

对象不多、更新不频繁 → nested
子对象很多、更新很频繁 → parent-child
两者都复杂 → 先考虑业务是否真的需要 ES


6. 高频踩坑总结(面试加分)

  • ❌ 忘了 nested,导致条件串味
  • ❌ nested 当关系型 join 用
  • ❌ parent-child 没 routing,数据直接乱
  • ❌ parent-child 当 OLTP 用(更新风暴)

7. 面试官追问时的"标准回答结构"

当被问:

"你为什么用 nested / parent-child?"

你回答顺序:

  1. 业务特征(数量 / 更新频率 / 查询方式)
  2. ES 底层机制(扁平化 / join 成本)
  3. 性能与维护取舍
  4. 为什么不用关系型数据库

8. 一句话总结(背这个)

nested 是"文档内一致性",
parent-child 是"文档间独立生命周期"。
能用 nested 别上 join,
能不用 ES 就别硬用。

相关推荐
Dxy123931021615 分钟前
Elasticsearch 索引与映射:为你的数据打造一个“智能仓库”
大数据·elasticsearch·搜索引擎
倒流时光三十年5 小时前
SpringBoot 数据库同步 Elasticsearch 性能优化
数据库·spring boot·elasticsearch
星辰_mya6 小时前
Elasticsearch更新了分词器之后
大数据·elasticsearch·搜索引擎
Elastic 中国社区官方博客7 小时前
Elasticsearch:Workflows 介绍 - 9.3
大数据·数据库·人工智能·elasticsearch·ai·全文检索
星辰_mya7 小时前
Elasticsearch主分片数写入后不能改
大数据·elasticsearch·搜索引擎
春日见18 小时前
vscode代码无法跳转
大数据·人工智能·深度学习·elasticsearch·搜索引擎
那起舞的日子1 天前
ElasticSearch系列-3-java端整合CURD
elasticsearch
历程里程碑1 天前
普通数组----最大子数组和
大数据·算法·elasticsearch·搜索引擎·排序算法·哈希算法·散列表
星辰_mya1 天前
Elasticsearch之下
大数据·elasticsearch·搜索引擎
Elastic 中国社区官方博客1 天前
跳过 MLOps:通过 Cloud Connect 使用 EIS 为自管理 Elasticsearch 提供托管云推理
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·全文检索