首页/数据/NoSQL 速查/nested 类型与嵌套查询
Elasticsearch89 条

nested 类型与嵌套查询

普通 object 数组在索引时会被扁平化,跨对象条件会互相串位;若数组内字段必须成组匹配,需要声明 nested 类型并用 nested 查询(可加 inner_hits 返回命中的子文档)。

NoSQL 速查数据更新于 2026-10-13

为什么需要 nested

普通 object 数组在索引时会被扁平化:元素内部的层级关系被抹掉,只留下字段名与值的列表。于是 user.first=John 与 user.last=Smith 可能来自数组里两个不同元素,跨字段条件会串位命中。声明为 nested 后,每个元素成为独立的 Lucene 文档,成组匹配与按元素返回才成立。

基本信息

适用版本Elasticsearch 7.x / 8.x
映射声明{ "type": "nested", "properties": { ... } }
查询写法nested 查询包裹 path + query,可选 inner_hits
索引代价每个嵌套对象都是独立文档,体积与写入放大
能力限制不能像普通字段那样直接排序与聚合

典型使用场景

  • 用户对象数组:姓名、手机号必须来自同一元素,不能跨元素拼出假命中
  • 订单明细行:按「同一行内 sku 与数量」组合筛选,而不是全表任一命中
  • 商品多规格:颜色与尺码成组匹配,避免颜色来自 A 规格、尺码来自 B 规格
  • 权限与标签分组:需要判断某个标签组合出现在同一元素中
  • 展示命中的具体子对象:用 inner_hits 把匹配到的元素一起返回给前端

示例

示例
PUT /my-index/_mapping                 # 先声明 nested 类型,普通 object 无法事后改
{
  "properties": {
    "user": {
      "type": "nested",
      "properties": {
        "first": { "type": "keyword" },
        "last":  { "type": "keyword" }
      }
    }
  }
}

GET /my-index/_search
{
  "query": {
    "nested": {
      "path": "user",
      "query": {
        "bool": {
          "must": [ { "term": { "user.first": "John" } },
                    { "term": { "user.last": "Smith" } } ]
        }
      },
      "inner_hits": { "size": 2 }       # 返回具体命中的子文档,方便展示与排查
    }
  }
}

行为对照

写法行为注意点
普通 object 数组字段被扁平化跨元素条件会串位,产生假命中
nested 类型每个元素独立成文档索引体积与写入开销随元素数放大
nested 查询path + query 成组匹配查询路径必须与 mapping 的 nested 路径一致
inner_hits额外返回命中的子文档大数组时返回体膨胀,需显式设 size
nested 排序聚合需 nested 上下文不能把嵌套字段当普通字段直接用
nested 文档是独立的 Lucene 文档,因此它的相关度与主文档分开计算,主文档的得分是这些子查询得分的合成结果;理解这一点才能解释为什么同一条查询在不同数组长度下得分不同。
字段一旦建成 nested 就不能事后改回普通字段,只能重建索引(_reindex);设计阶段就要想清楚哪些数组需要成组语义。
nested 的元素数量直接决定索引体积与查询代价:数组有几百个元素时要评估是否改用父子文档模型,或把数组拆到独立索引由应用层关联。

易错点

  • 用普通 object 数组做跨元素条件匹配,条件命中却来自不同元素,业务上属于假数据 → 数组必须成组匹配时声明 nested
  • 对 nested 字段写普通查询(不加 nested 包裹),根文档上没有这些值,命中为空
  • nested 字段不能直接排序聚合,直接写 sort/terms aggs 会报错 → 用 nested 上下文或 nested 排序
  • 每个嵌套对象都是独立文档,几十上百个元素会显著放大索引体积与写入延迟
  • inner_hits 不限 size,命中大数组时返回体远大于预期,拖慢查询与前端渲染

数据来源与参考

  • Elasticsearch Guide: Nested field type
  • Elasticsearch Guide: Nested query
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌