猫鼬如何发送交易多个集合

swf*_*u69 2 javascript transactions mongoose mongodb node.js

旁注我使用以下代码连接到数据库:

const mongoose = require('mongoose');

const connectDB = (url) => {
  return mongoose.connect(url);
}

Run Code Online (Sandbox Code Playgroud)

问题描述: 我有两个不同的集合。这两个操作,findByIdAndUpdate并且create必须作为原子操作运行。这对于猫鼬交易来说应该是可能的。

const registerCustomer = async (req, res) => {
   await CustomerRegistrationCode.findByIdAndUpdate(req.body._id, { used: true });
   const customer = await Customer.create({firstName: req.body.firstName});
}
Run Code Online (Sandbox Code Playgroud)

我尝试过的:

const registerCustomer = async (req, res) => {
    const session = await mongoose.startSession();
    await session.startTransaction();
    try {
        await CustomerRegistrationCode.findByIdAndUpdate(req.body._id, { used: true }); //updates even though 
        const customer = await Customer.create({ firstName: req.body.firstName });// this line will throw error
        await session.commitTransaction();
        session.endSession();
    } catch (error) {
        console.error('abort transaction');
        await session.abortTransaction();
        session.endSession();
        throw error;
    }
}

Run Code Online (Sandbox Code Playgroud)

问题即使 Customer.create 方法抛出错误,CustomerRegistrationCode 集合也会更新。如何解决这个问题?

理解 MongoDB 事务的新方法失败了,但这是来自https://mongoosejs.com/docs/transactions.html的官方代码

const mongoose = require('mongoose');
const debugMongo = async () => {
  const db = await mongoose.createConnection("mongodb://localhost:27017/mongotest");
  const Customer = db.model('Customer', new mongoose.Schema({ name: String }));
  const session = await db.startSession();
  session.startTransaction();
  await Customer.create([{ name: 'Test' }], { session: session }); //(node:20416) UnhandledPromiseRejectionWarning: MongoServerError: Transaction numbers are only allowed on a replica set member or mongos
  let doc = await Customer.findOne({ name: 'Test' });
  assert.ok(!doc);
  doc = await Customer.findOne({ name: 'Test' }).session(session);
  assert.ok(doc);
  await session.commitTransaction();
  doc = await Customer.findOne({ name: 'Test' });
  assert.ok(doc);
  session.endSession();
}

debugMongo();

Run Code Online (Sandbox Code Playgroud)

抛出Customer.create错误,我不知道为什么。有人有一个最小的工作示例吗?

Ayz*_*ian 10

您以错误的方式使用交易,这就是它不起作用的原因。

您需要将该session对象传递给您的操作。

const registerCustomer = async (req, res) => {
    const session = await mongoose.startSession();
    session.startTransaction();
    try {
        await CustomerRegistrationCode.findByIdAndUpdate(req.body._id, { used: true }, { session });
        const customer = await Customer.create({ firstName: req.body.firstName }, { session });
        await session.commitTransaction();
    } catch (error) {
        console.error('abort transaction');
        await session.abortTransaction();
    } finally {
        session.endSession();
    }
}
Run Code Online (Sandbox Code Playgroud)

另外,我对你的代码进行了一些重构。

您可以在此处阅读有关交易的更多信息