Nodejs 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.


person SovietSpy2    schedule 01.10.2020    source источник


Ответы (1)


Чтобы использовать find в транзакции, передайте сеанс с помощью метода session:

doc = await Customer.findOne({ name: 'Test' }).session(session);

См. раздел Транзакции в Mongoose.

person Joe    schedule 02.10.2020
comment
Спасибо за Ваш ответ! Я забыл упомянуть, что я использую собственный драйвер mongodb, а не mongoose. - person SovietSpy2; 02.10.2020
comment
Я проверил, что встроенный драйвер также имеет эту функцию (mongodb .github.io/node-mongodb-native/3.6/api/), но я хотел бы получить несколько документов, а не один. Вот почему я хотел бы использовать find() - person SovietSpy2; 02.10.2020
comment
find собственного драйвера принимает сеанс как вариант. - person Joe; 02.10.2020