猫鼬事务会话在保存和查找时的差异



这两种方法有区别吗?

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

测试时,功能是相同的。在mongoose事务中使用会话的正确方法是什么?

首先在交易中你需要async/await

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

但是事务允许你在isolationpotentially中执行多个操作,如果其中一个操作失败,撤销所有操作,事务的主要目标是让你在MongoDB中隔离update multiple documents

,但是在您的示例中,您更新了一个集合,并且不需要事务。让我们继续……请看下面的例子,在这个例子中结果是不同的,这个create()是事务的一部分,因为session和事务是隔离执行的,所以除非你传递一个sessionfindOne(),否则在事务提交之前你不会看到结果。所以findOne的结果是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();

在下面的示例中,这个findOne()将返回结果,因为传递session意味着这个findOne()将作为事务的一部分运行。

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();

如果使用会话从findOne()或find()获取Mongoose文档,文档将保留对会话的引用,并在save()中使用该会话,如下例所示找不到result,因为save()是未提交事务的一部分,但firstReuslt不是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

如果你想更新两个集合,应该使用save({ session: sess }),但如果你想更新一个集合,你不需要,因为:

如果使用会话从findOne()或find()获取Mongoose文档,文档将保留对会话的引用并使用该会话用于save():

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

最新更新