You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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以下版本(两步操作)

低版本不支持聚合管道更新,需要分两次操作实现:

  1. 先尝试更新已存在的对应part_id条目
const updateRes = db.your_collection_name.updateOne(
  { user_id: '13', 'stock.part_id': 'P123' },
  { $inc: { 'stock.$.quantity': 1 } }
)
  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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.21 11:54:04