本文介绍如何在 mongodb 中通过 update + 聚合管道语法,对“文档内数组中的子数组”执行条件更新:若指定 item 存在,则向其 sub_list 追加元素;若不存在,则在 list 中新增该 item 对象——全程支持 upsert。
本文介绍如何在 mongodb 中通过 update + 聚合管道语法,对“文档内数组中的子数组”执行条件更新:若指定 item 存在,则向其 sub_list 追加元素;若不存在,则在 list 中新增该 item 对象——全程支持 upsert。
在 MongoDB 5.0+ 中,update() 方法已支持聚合管道作为更新操作符(即 update({ filter }, [{ pipeline }], { upsert: true })),这为处理复杂嵌套结构(如数组内含对象、对象内含数组)提供了强大能力。传统 $ 或 $[] 操作符无法同时满足「按条件定位子文档 + 条件追加元素 + 不存在时创建」的需求,而聚合管道可精准控制逻辑分支。
以下是一个完整、可复用的解决方案,目标是:
✅ 给定 category(如 "A")和 item 值(如 1),找到对应 list 元素;
✅ 若该元素存在且 valToAdd(如 68)尚未在 sub_list 中,则将其追加;
✅ 若该 item 在 list 中不存在,则新建 { item: 1, sub_list: [68] } 并加入 list;
✅ 若整个文档(category: "A")不存在,则自动 upsert 创建。
const categoryVal = "A";const itemToFind = 1;const valToAdd = 68;db.collection.update( { "category": categoryVal }, [ { $set: { list: { $cond: { if: { $in: [itemToFind, { $ifNull: ["$list.item", []] }] }, then: { $map: { input: "$list", in: { $cond: { if: { $and: [ { $eq: ["$$this.item", itemToFind] }, { $not: { $in: [valToAdd, { $ifNull: ["$$this.sub_list", []] }] } } ] }, then: { $mergeObjects: [ "$$this", { sub_list: { $concatArrays: [ { $ifNull: ["$$this.sub_list", []] }, [valToAdd] ] } } ] }, else: "$$this" } } } }, else: { $concatArrays: [ [{ item: itemToFind, sub_list: [valToAdd] }], { $ifNull: ["$list", []] } ] } } } } } ], { upsert: true })
掌握此模式后,你可轻松扩展至更深层嵌套(如 list[].sub_list[].tags),只需逐层嵌套 $map 与 $cond —— 真正实现“声明式嵌套更新”。