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

如何在Mongoose中使用事务同时创建Stock和GoodsReceivedNote文档

Mongoose 事务实现 GoodsReceivedNote 关联 Stock 批量创建方案

前提说明

首先确认你的MongoDB部署满足事务要求:

  • MongoDB版本 >= 4.0
  • 部署架构为副本集或分片集群(单机模式不支持事务,本地测试可使用run-rs工具快速搭建本地副本集)

修正后完整Controller代码

router.post('/', async (req, res) => {
  const session = await mongoose.startSession()
  try {
    // 显式开启事务
    session.startTransaction()

    // 生成GRN自增ID,若getNextSequence包含数据库操作,建议传入session保证事务一致性
    const grnId = await getNextSequence('goodsReceivedNote', session)
    req.body.id = grnId

    // 1. 保存GoodsReceivedNote,传入session纳入事务管理
    const goodsReceivedNote = new GoodsReceivedNote(req.body)
    await goodsReceivedNote.save({ session })

    // 2. 遍历cart数组构造Stock批量插入数据
    const stockList = []
    for (const cartItem of goodsReceivedNote.cart) {
      // 生成Stock自增ID
      const stockId = await getNextSequence('stock', session)
      stockList.push({
        id: stockId,
        // 兼容两个模型poNumber的类型差异:GRN为String、Stock为Number
        poNumber: Number(goodsReceivedNote.poNumber),
        orderNo: goodsReceivedNote.orderNo,
        packingId: cartItem.packingId,
        orderSize: cartItem.orderSize,
        receivedQty: cartItem.receivedQty,
        // 初始可用量默认等于收货量,可根据业务规则调整
        availableQty: cartItem.receivedQty
      })
    }

    // 3. 批量插入Stock数据,传入session纳入事务管理
    await Stock.insertMany(stockList, { session })

    // 所有操作执行成功,提交事务
    await session.commitTransaction()
    res.sendStatus(200)
  } catch (error) {
    // 任意步骤出错,回滚所有事务内操作
    await session.abortTransaction()
    console.error('GRN创建失败,事务已回滚:', error)
    return res.sendStatus(500)
  } finally {
    // 关闭会话释放资源
    session.endSession()
  }
})

关键修改说明

  • 新增session.startTransaction()显式启动事务,原代码缺少该步骤事务不会生效
  • 所有数据库写操作(GRN保存、Stock插入)都传入{ session }参数,确保操作全部纳入事务,要么全部成功要么全部回滚
  • 删除原代码中无用的const stocks = new Stock(req.body)逻辑,改为遍历cart数组批量构造多条Stock数据
  • 兼容了GRN和Stock模型poNumber的类型差异,避免数据写入异常
  • 采用insertMany批量插入Stock,相比循环调用create性能更高

优化建议

  • 如果你的getNextSequence方法是通过查询计数器集合实现自增ID,建议修改方法支持传入session参数,让ID生成操作也纳入事务,避免事务回滚后ID序列出现空洞(如果业务允许ID不连续可以忽略该优化)
  • 可根据业务需要在catch中返回更具体的错误信息,方便前端做用户提示

内容的提问来源于stack exchange,提问作者kdam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.08 07:39:03