MongoDB聚合:如何合并多层嵌套数组为单个数组置于文档根节点
问题原因
直接通过路径$tasks.assigned.solutions访问多层嵌套数组时,MongoDB会逐层保留数组维度:第一层对应根节点的tasks数组维度,第二层对应每个task下的assigned数组维度,第三层才是每个assigned节点下的solutions数组本身。你当前使用的$map操作仅做原样元素返回,没有做任何数组展开扁平化处理,因此最终得到三层嵌套数组。
修复方案
使用$reduce配合$concatArrays逐层展开两层嵌套数组,最终合并得到一维的solutions数组,代码如下:
const order = this.orderModel .aggregate([ { $match: { _id: orderId, student: studentId } }, { $addFields: { solutions: { // 第一层遍历:展开tasks数组维度 $reduce: { input: '$tasks', initialValue: [], in: { $concatArrays: [ '$$value', { // 第二层遍历:展开assigned数组维度,合并所有solutions $reduce: { input: '$$this.assigned', initialValue: [], in: { $concatArrays: ['$$value', '$$this.solutions'] } } } ] } } } } } ]) .exec();
- 上述写法兼容MongoDB 4.0及以上所有版本,执行后会把所有层级下的solutions元素合并为根节点下的一维数组。
- 如果需要对solutions做条件筛选,只需要把上述
$reduce的返回结果作为$filter的输入,在cond字段中写筛选规则即可,示例:
solutions: { $filter: { input: { // 粘贴上面两层$reduce的完整逻辑作为输入 $reduce: { input: '$tasks', initialValue: [], in: { $concatArrays: [ '$$value', { $reduce: { input: '$$this.assigned', initialValue: [], in: { $concatArrays: ['$$value', '$$this.solutions'] } } } ] } } }, as: 'item', // 示例筛选规则:name字段包含'有效'关键词 cond: { $regexMatch: { input: '$$item.name', regex: '有效' } } } }
注意:不要尝试用多层
$unwind做扁平化,会大幅增加聚合阶段的内存开销,数据量较大时性能远低于$reduce+$concatArrays的写法。
内容的提问来源于stack exchange,提问作者Ashish
相关产品推荐
相关产品推荐

