问题描述
我有一个mongo 4.2副本集。我有N个进程正在同时运行并尝试读取集合。这个集合就像一个队列。我想读取100个元素并在事务中更新它们,以便其他进程不会尝试读取这些元素。
我的代码去了
const collection = client.db("test").collection(TEST_COLLECTION);
const session = client.startSession();
try {
let data = null;
await session.withTransaction(async () => {
console.log("starting transaction")
data = await collection.find({ runId: null },{ _id: 1,limit: 100 }).toArray();
const idList = data.map(item => item._id.toHexString());
await collection.updateMany(
{ runId: { $in: idList } },{ $set: { runId: runId } },{ session });
console.log("Successful transaction")
});
data.map(item => {
// process element one by one and update them (no need for transaction here)
})
} catch (e) {
console.error("The transaction was aborted due to an unexpected error: " + e);
} finally {
await session.endSession();
console.log("Closing transaction")
}
这是我现在得到的代码。关键是find()不会接受选项,因此我无法通过会话。这意味着它不会成为交易的一部分。
mongodb文档指出:使用驱动程序时,事务中的每个操作必须与会话相关联(即,将会话传递给每个操作)。
所以我假设这实际上不是事务性的更新部分,而不能解决我的问题。有什么办法可以将两者都包含在我的交易中吗?有什么想法吗?其他/更好的选择?
谢谢
编辑: 所以当我遇到问题时,我盯着问题看了15分钟。如果我先使用事务更新。然后甚至在事务外部使用runId进行查询也可以实现我的目标。我对吗?很简单吗?
EDIT2: Edit1很愚蠢,现在我不能限制为100个项目。回到开始。
EDIT3: 我正在使用本机mongodb nodejs驱动程序。
解决方法
要在交易中使用find
,请使用session
方法传递会话:
doc = await Customer.findOne({ name: 'Test' }).session(session);