Difference of mongoose transaction session on save and on find

Viewed 4105

Is there a difference between these two approach.

const something = Model.findById(id).
something.save({ session })
const something = Model.findById(id).session(({ session })
something.save() 

When testing it, the functionality is the same. What should be right way to use session in mongoose transaction.

1 Answers

first of all in transaction you need to async/await,

const something = await Model.findById(id).
await something.save({ session })

but transactions let you execute multiple operations in isolation and potentially undo all the operations if one of them fails and the primary goal of a transaction is to let you update multiple documents in MongoDB in isolation.

but in your example you update one collection, and don't need to transaction. let's move on... see the following exmaple, in this example result is diffrence, this create() is part of the transaction because of the session and transactions execute in isolation, so unless you pass a session to findOne() you won't see the result until the transaction is committed. so result of findOne is Null

const session = await db.startSession();
session.startTransaction();
await Model.create([{ name: 'Test' }], { session: session });
let result = await Model.findOne({ name: 'Test' });//without session
session.endSession();

in the following exapmle, this findOne() will return the result, because passing the session means this findOne() will run as part of the transaction.

const session = await db.startSession();
session.startTransaction();
await Model.create([{ name: 'Test' }], { session: session });
let result = await Model.findOne({ name: 'Test' }).session(session);
session.endSession();

If you get a Mongoose document from findOne() or find() using a session the document will keep a reference to the session and use that session for save(), in the following example Won't find the result because save() is part of an uncommitted transaction, but firstReuslt is not Null

const session = await db.startSession();
session.startTransaction();
await Model.create({ name: 'Test' });
const something  = await Model.findOne({ name: 'Test' }).session(session);
something.name = 'firstTest';
await something.save();

let result = await Model.findOne({ name: 'firstTest' }); //Is Null
await session.commitTransaction();
session.endSession();

firstReuslt = await Model.findOne({ name: 'firstTest' });//Is Not Null

if you want update two collection like following code, should use save({ session: sess }) but when you want update one collection you don't need because:

if you get a Mongoose document from findOne() or find() using a session the document will keep a reference to the session and use that session for save():

const sess = await mongoose.startSession();
sess.startTransaction();
await first.save({ session: sess }); 
await second.save({ session: sess });
await sess.commitTransaction();
Related