如何使用Mongoose实现嵌套数组不存在则插入、存在则更新数量
解决方案
方案1:MongoDB 4.2及以上版本(单次原子操作,推荐)
这个版本支持带聚合管道的更新操作,可以在单次请求里完成判断+更新的逻辑,全程原子性,不会有并发问题。
示例代码(假设你要更新user_id: '13'的文档,新增/更新part_id: 'P123'的库存):
db.your_collection_name.updateOne( // 匹配目标用户文档 { user_id: '13' }, // 聚合更新管道 [ { $set: { stock: { $cond: { // 判断stock数组中是否已经存在对应part_id的条目 if: { $in: ['P123', '$stock.part_id'] }, // 存在则遍历数组,对应条目quantity加1 then: { $map: { input: '$stock', in: { $cond: { if: { $eq: ['$$this.part_id', 'P123'] }, then: { $mergeObjects: ['$$this', { quantity: { $add: ['$$this.quantity', 1] } }] }, else: '$$this' } } } }, // 不存在则拼接新条目到数组末尾 else: { $concatArrays: ['$stock', [{ part_id: 'P123', quantity: 1 }]] } } } } } ], // 如果需要用户文档不存在时自动创建,可将upsert设为true { upsert: false } )
方案2:MongoDB 4.2以下版本(两步操作)
低版本不支持聚合管道更新,需要分两次操作实现:
- 先尝试更新已存在的对应part_id条目
const updateRes = db.your_collection_name.updateOne( { user_id: '13', 'stock.part_id': 'P123' }, { $inc: { 'stock.$.quantity': 1 } } )
- 如果第一步没有匹配到任何文档,说明对应part_id不存在,执行新增操作
if (updateRes.matchedCount === 0) { db.your_collection_name.updateOne( { user_id: '13' }, { $push: { stock: { part_id: 'P123', quantity: 1 } } } ) }
补充说明
你之前单独使用upsert: true和$inc无法实现需求的原因是:普通更新的upsert逻辑仅作用于整个文档级别,文档不存在时才会新建,不会自动创建数组中不存在的嵌套条目。
内容的提问来源于stack exchange,提问作者TKX
相关产品推荐
相关产品推荐

