Nodejs mongoose Model.create 传入数组,是否是事务性的

Nodejs mongoose Model.create 传入数组,是否是事务性的

是否该数组插入到数据库中,要么都成功,要么都失败吗?

4 回复

Nodejs Mongoose Model.create 传入数组,是否是事务性的

问题描述

在使用 Mongoose 的 Model.create 方法时,如果传入一个数组作为参数,那么这些文档是否会被作为一个事务性操作处理?也就是说,如果数组中的某些文档插入失败,其他文档是否也会被回滚?

答案

默认情况下,Mongoose 的 Model.create 方法并不支持事务性操作。这意味着,即使你传递一个包含多个文档的数组,这些文档仍然可能部分成功、部分失败。如果你需要确保所有文档要么全部成功插入,要么全部失败并回滚,你需要使用 MongoDB 的事务功能。

示例代码

  1. 不使用事务
const mongoose = require('mongoose');
const UserSchema = new mongoose.Schema({
    name: String,
    email: String
});

const User = mongoose.model('User', UserSchema);

async function createUser() {
    try {
        await User.create([
            { name: 'Alice', email: 'alice@example.com' },
            { name: 'Bob', email: 'bob@example.com' }
        ]);
        console.log('Users created successfully');
    } catch (error) {
        console.error('Error creating users:', error);
    }
}
  1. 使用事务
const mongoose = require('mongoose');

async function createUserWithTransaction() {
    const session = await mongoose.startSession();
    session.startTransaction();

    try {
        await User.create([
            { name: 'Alice', email: 'alice@example.com' },
            { name: 'Bob', email: 'bob@example.com' }
        ], { session });

        // 如果一切正常,提交事务
        await session.commitTransaction();
        session.endSession();
        console.log('Users created successfully');
    } catch (error) {
        // 如果发生错误,回滚事务
        await session.abortTransaction();
        session.endSession();
        console.error('Error creating users:', error);
    }
}

createUserWithTransaction();

解释

  • 在第一个示例中,我们直接使用 Model.create 方法插入多个文档。如果其中某个文档插入失败,其他文档仍可能会被插入。
  • 在第二个示例中,我们使用了 MongoDB 的事务功能。通过创建一个会话并开始一个事务,我们可以确保所有的操作要么全部成功,要么全部失败。如果任何一个操作失败,整个事务将被回滚。

因此,如果你需要确保数据的一致性和完整性,建议使用事务来管理多个文档的插入操作。


用mongoskin吧,mongoose 很蛋疼

mongodb没有事务性,只能保证单条记录的事务

在 Node.js 中使用 Mongoose 的 Model.create 方法传入数组时,默认情况下并不具备事务性。也就是说,数组中的多个文档可能不会作为一个整体进行操作,某个文档插入成功后,另一个文档插入失败也不会回滚之前的操作。

然而,从 Mongoose v5.11.0 版本开始,MongoDB 支持了多文档事务。你可以利用这一特性来实现原子性操作,即数组中的所有文档要么全部成功插入,要么全部失败。以下是一个简单的示例代码,演示如何使用事务来确保数组中的所有文档都能作为一个整体插入到数据库中:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

// 定义模型
const MySchema = new Schema({
    name: String,
});

const MyModel = mongoose.model('MyModel', MySchema);

async function createDocuments(documents) {
    const session = await mongoose.startSession();
    session.startTransaction();

    try {
        await MyModel.create(documents, { session });

        // 提交事务
        await session.commitTransaction();
        session.endSession();
    } catch (error) {
        console.log("事务失败,进行回滚:", error);
        // 回滚事务
        await session.abortTransaction();
        session.endSession();
        throw error; // 可以选择重新抛出错误
    }
}

(async () => {
    const documents = [
        { name: 'Document1' },
        { name: 'Document2' },
    ];

    await createDocuments(documents);
    console.log("所有文档已成功创建");
})();

在这段代码中,我们首先启动一个会话,并显式地开启一个事务。然后,我们调用 MyModel.create 方法,并将会话对象传递给它。如果任何文档插入过程中发生错误,整个事务都会被回滚。否则,事务将被提交,所有文档都将成功插入到数据库中。

回到顶部