首页/数据/NoSQL 速查/聚合数组函数 $filter / $map / $reduce
MongoDB99 条

聚合数组函数 $filter / $map / $reduce

在管道里加工数组:$filter 筛选、$map 映射、$reduce 折叠聚合、$arrayElemAt 取元素、$size 取长度。

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

管道里加工数组

数组型字段在文档库里很常见(标签、明细行、分数列表),聚合阶段提供了一组数组表达式直接在数据库侧加工:$filter 按条件筛选元素,$map 逐个转换,$reduce 折叠成单值,$slice 与 $arrayElemAt 取片段或元素。把这些计算放在管道里,能显著减少应用程序侧的遍历与拼接代码。

基本信息

筛选{ $filter: { input: "$scores", as: "s", cond: { $gt: ["$$s", 60] } } }
映射{ $map: { input: "$items", as: "i", in: { $multiply: ["$$i.qty", "$$i.price"] } } }
折叠{ $reduce: { input: "$items", initialValue: 0, in: { $add: ["$$value", "$$this.qty"] } } }
取元素与长度{ $arrayElemAt: ["$items", 0] }、{ $size: "$items" }
变量引用自定义变量用 $$名称 引用,系统变量为 $$this 与 $$value
适用版本多数数组表达式在 3.2 至 3.6 之间陆续提供

典型使用场景

  • 统计达标记数:筛选出及格元素后取长度
  • 计算明细合计:把每行数量乘单价再累加成金额
  • 取首末元素:列表页只展示首条与末条概要
  • 数组字段瘦身:只保留需要的元素,减少返回体积
  • 结构转换:把元素数组映射成新的嵌套结构供前端直接使用

示例

示例
db.students.aggregate([
  { $project: {
      name: 1,
      // 筛选及格成绩后计数
      passCount: { $size: { $filter: { input: "$scores", as: "s", cond: { $gte: ["$$s", 60] } } } },
      // 数组内每行数量乘单价,得到金额数组
      amounts: { $map: { input: "$items", as: "i", in: { $multiply: ["$$i.qty", "$$i.price"] } } },
      // 折叠成总额
      total: { $reduce: { input: "$items", initialValue: 0,
                          in: { $add: ["$$value", { $multiply: ["$$this.qty", "$$this.price"] }] } } },
      first: { $arrayElemAt: ["$scores", 0] },
      // 取前三个元素,负值表示从末尾开始
      top3: { $slice: ["$scores", 3] }
  } }
])

运算符对照

运算符作用注意点
$filter按条件筛选元素input 为 null 时结果为 null 而非空数组
$map对每个元素求值生成新数组元素结构不符预期会得到 null 或缺字段
$reduce把数组折叠成单值initialValue 决定累加类型,别漏设
$arrayElemAt按下标取元素下标越界返回缺失,不会报错
$size数组长度对非数组字段使用会报错
$slice截取片段正数从头取,负数从末尾取
自定义变量用 $$名称 引用,$reduce 里则是 $$value 与 $$this:写错前缀会得到空结果或报错,条件计数前建议先用 $ifNull 把缺失数组兜底为空数组。
数组运算发生在文档内部:元素很多时单文档体积与计算量都会上升,超大数组应考虑拆分建模而不是靠表达式硬算。

易错点

  • $filter 或 $map 的 input 为 null:表达式返回 null 而不是空数组,取长度或比较时会得到非预期结果
  • 把字段缺失当成空数组处理:缺少字段与空数组在聚合中的表现不同,用 $ifNull 统一起点更稳
  • 在数组很大的文档上做多重运算:单文档内存与 CPU 开销上升,影响整体吞吐
  • 下标越界时不校验:$arrayElemAt 越界返回缺失而非报错,下游读取容易拿到空值

数据来源与参考

  • MongoDB Manual: Array Expression Operators
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌