简体   繁体   中英

Nodejs mongodb find and update multiple documents in transaction

I have a mongo 4.2 replica set. I have N processes running concurrently and trying to read a collection. This collection is like a queue. I'd like to read 100 elements and update them in a transaction so other processes won't try to read those.

My code goes:

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")
}

this is the code I've got right now. The thing is that find() won't accept options so I can't pass the session. This means it won't be part of the transaction.

the mongodb documentations states that: When using the drivers, each operation in the transaction must be associated with the session (ie pass in the session to each operation).

So I'm assuming that this is actually not transactional only the update part which not solves my problem. Is there any way to include both in my transaction? Any ideas on this? Other/better options?

Thanks

EDIT: So I was staring at my question for 15 minutes when it hit me. If I update first using the transaction. Then querying with the runId even outside of the transaction I can achieve my goal. Am I right? Is it so easy?

EDIT2: Edit1 was stupid now I can't limit to 100 items. Back to the start.

EDIT3: I'am using native mongodb nodejs driver.

To use a find in a transaction, pass the session using the session method:

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

See Transactions in Mongoose

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM