本文介绍如何使用 MongoDB 5.0+ 的 $function 聚合阶段,通过内联 JavaScript 实现任意深度嵌套 kids 数组的递归展平,生成单层结构的 _id 列表,适用于构建只读视图或简化下游处理。
本文介绍如何使用 mongodb 5.0+ 的 `$function` 聚合阶段,通过内联 javascript 实现任意深度嵌套 `kids` 数组的递归展平,生成单层结构的 `_id` 列表,适用于构建只读视图或简化下游处理。
在 MongoDB 中处理深度未知的嵌套文档(如树形结构的 kids 字段)时,原生聚合操作符(如 $unwind、$reduce、$map)难以直接支持真正的递归遍历——因为它们不具备动态调用自身的能力。虽然可通过多级 $reduce + $concatArrays 手动展开固定层数(如 3 层),但无法应对任意深度,且易导致结构混乱(如数组嵌套数组)。
此时,MongoDB 5.0 引入的 $function 聚合阶段提供了关键能力:允许在聚合管道中安全执行内联 JavaScript 函数,从而实现真正的递归逻辑。该方案无需外部应用介入,可直接用于创建 materialized view 或聚合视图。
以下是一个生产就绪的聚合管道示例:
db.collection.aggregate([ { $set: { kids: { $function: { body: "function drill(kids, out) { " + " if (!Array.isArray(kids) || kids.length === 0) return out; " + " for (let elem of kids) { " + " out.push({ _id: elem._id }); " + " drill(elem.kids ?? [], out); " + " } " + " return out; " + "}", args: ["$kids", []], lang: "js" } } } }])
✅ 关键说明:
⚠️ 注意事项:
最终输出严格符合预期:顶层文档保持不变,kids 数组变为仅含 {_id} 对象的一维列表,层级信息虽丢失但满足“展平”核心诉求。此方案简洁、可维护,并可无缝集成至 MongoDB View 定义中,是目前处理动态深度嵌套结构最实用的聚合级解法。