Node.js MongoDB在事务中查找并更新多个文档

问题描述

我有一个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);

请参见Transactions in Mongoose