'How to add mongoose transaction and create a document?

I want to add a mongoose transaction in the POST method. When creating the transaction it should be creating a document called stock. Can anybody help me figure out what should I do here? I have a node/express/mongoose app with the following:

GoodsRecivedNote controller

router.post('/', async (req, res) => {
  const session = await mongoose.startSession()
  try {
    const _id = await getNextSequence('goodsReceivedNote')
    req.body.id = _id

    const goodsReceivedNote = new GoodsReceivedNote(req.body)
    const stocks = new Stock(req.body)

    await goodsReceivedNote.save()

    //use mongoose transaction

    //creates a loop(data get from the arry called cart in goodsrecivednote)
    for (const item of data) {
      //insert stock modal(orderNo, packingId, orderSize, poNumber)
      item.create({})
      //insert(data, {session})
    }

    await session.commitTransaction()
    res.sendStatus(200)
  } catch (error) {
    await session.abortTransaction()
    return res.sendStatus(500)
  } finally {
    session.endSession()
  }
})

GoodsRecivedNote model

const goodsReceivedNoteSchema = new Schema(
  {
    id: Number,    
    poNumber: String,  
    orderedDate: String,
    supplier: String,    
    orderNo: String,  
    cart: [
      {             
        packingId: Number,
        actualSize: String,  
        orderSize: String,
        brandId: Number,
        artWork: String,
        receivedQty: Number,
        grnDate: String,       
      },
    ],      
  },     
)

module.exports = mongoose.model(
  'GoodsReceivedNote',
  goodsReceivedNoteSchema
)

Stock model

const stockSchema = new Schema(
  {
    id: Number,    
    poNumber: Number,  
    orderNo: String,
    packingId: Number,     
    orderSize: String,       
    receivedQty: Number,
    availableQty: Number, 
 
  },     
)

module.exports = mongoose.model(
  'Stock',
  stockSchema
)


Solution 1:[1]

Maybe you can try something like this

const session = await mongoose.startSession()
session.startTransaction()
const opts = { session }

const stocks = await new Stock(req.body).save(opts)
await goodsReceivedNote.save(opts)


...the rest of your code

When ever you call Save Update or Delete please add opts as option

Solution 2:[2]

Answer by 21bn gets the work done but withTransaction() is way better than startTransaction().

I recommend you use withTransaction instead.

    const session = await mongoose.startSession();
    await session.withTransaction(async (session) => {
     
    // For create..
    collection.create({something:"something"},{session:session});
    });

For insertmany, updatemany, the rule is basically the same..

collection.updateMany({find_something:"something"},{name:"Some name"},{session:session});

If you want to find a document using session..

collection.findOne({_id: "some_id"}).session(session));

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 21bn
Solution 2 Sujan Stc