
本文介绍如何在 mongodb 中通过 update + 聚合管道(update with aggregation pipeline)对“数组中的对象数组”执行精准 upsert 操作:当指定 category 和 item 存在时,向其 sub_list 追加新值;若 item 不存在则自动添加新对象;若整个文档不存在则创建新文档。
本文介绍如何在 mongodb 中通过 update + 聚合管道(update with aggregation pipeline)对“数组中的对象数组”执行精准 upsert 操作:当指定 category 和 item 存在时,向其 sub_list 追加新值;若 item 不存在则自动添加新对象;若整个文档不存在则创建新文档。
在 MongoDB 4.2+ 中,db.collection.update() 支持以聚合管道作为更新操作符,这使得处理复杂嵌套结构(如数组内含对象、对象内含数组)成为可能。传统 $push 或 $set 无法同时满足「按子字段定位 + 条件追加 + 不存在则创建」三重要求,而聚合管道更新可完美解决。
核心思路
- 定位外层文档:仅用 "category": "A" 匹配主文档(避免 list.item: 1 导致数组索引匹配歧义);
- 判断目标 item 是否存在:使用 $in 检查 itemToFind 是否在 list.item 数组中;
-
分支处理:
- ✅ 存在 → 用 $map 遍历 list,对匹配 item 的对象执行 $mergeObjects,将新值 valToAdd 安全追加至 sub_list(自动去重需额外逻辑,本文为追加);
- ❌ 不存在 → 用 $concatArrays 将新对象 { item: 1, sub_list: [11] } 插入 list 开头或末尾(顺序可调);
- 兜底容错:所有涉及数组访问(如 "$list.item"、"$$this.sub_list")均包裹 $ifNull,防止空数组或缺失字段报错。
完整可运行代码(Node.js / Shell 兼容)
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 }
);
关键注意事项
- ? 原子性保障:整个操作在单次 update 中完成,无需应用层事务或双读写,强一致性;
- ⚠️ $in 对数组字段的限制:"$list.item" 返回的是 list 中所有 item 值组成的数组(如 [1, 2]),这是 MongoDB 的投影行为,安全可用;
- ? 避免重复添加:示例中已加入 {$not: {$in: [...]}} 判断,确保 valToAdd 不在 sub_list 中才追加(如需强制去重,可后续接 $set: { "list.$[elem].sub_list": { $setUnion: ["$$elem.sub_list", [valToAdd]] } } 配合 arrayFilters);
- ? Upsert 触发条件:仅当 category 未匹配任何文档时创建新文档,新文档将包含 "category": "A" 和初始化的 list(含新对象),其他字段(如 _id)由 MongoDB 自动分配;
- ? 调试建议:先在 Mongo Playground 中验证逻辑,再部署到生产环境。
该方案是 MongoDB 处理深层嵌套 upsert 场景的推荐实践,兼顾表达力、健壮性与性能,适用于商品 SKU 管理、用户标签系统、配置项动态维护等典型业务场景。











