Actas son nuevas en MongoDB 4.0 y Mongoose 5.2.0. Las transacciones le permiten ejecutar múltiples operaciones de forma aislada y potencialmente deshacer todas las operaciones si una de ellas falla. Esta guía lo ayudará a comenzar a usar transacciones con Mongoose.

Tu primera transacción

MongoDB actualmente solo admite transacciones en conjuntos de réplicas, no servidores independientes. Para ejecutar un conjunto de réplicas locales para el desarrollo en macOS, Linux o Windows, use npm para instalar corredores globalmente y ejecutar run-rs --version 4.0.0. Run-rs descargará MongoDB 4.0.0 para usted.

Para usar transacciones con Mongoose, debe usar Mongoose >= 5.2.0. Para comprobar su versión actual de Mongoose, ejecute npm list | grep "mongoose" o mira el mongoose.version propiedad.

Las transacciones se basan en Sesiones de MongoDB. Para iniciar una transacción, primero debe llamar startSession() y luego llame a la sesión startTransaction() función. Para ejecutar una operación en una transacción, debe pasar el session como una opción.

const Customer = db.model('Customer',newSchema( name: String ));let session =null;return Customer.createCollection().then(()=> db.startSession()).then(_session=>
    session = _session;// Start a transaction
    session.startTransaction();// This `create()` is part of the transaction because of the `session`// option.return Customer.create([ name:'Test'], session: session );).// Transactions execute in isolation, so unless you pass a `session`// to `findOne()` you won't see the document until the transaction// is committed.then(()=> Customer.findOne( name:'Test')).then(doc=> assert.ok(!doc)).// This `findOne()` will return the doc, because passing the `session`// means this `findOne()` will run as part of the transaction.then(()=> Customer.findOne( name:'Test').session(session)).then(doc=> assert.ok(doc)).// Once the transaction is committed, the write operation becomes// visible outside of the transaction.then(()=> session.commitTransaction()).then(()=> Customer.findOne( name:'Test')).then(doc=> assert.ok(doc));

En el ejemplo anterior, session es una instancia del Controlador de MongoDB Node.js ClientSession clase. por favor refiérase a Documentos del controlador MongoDB para obtener más información sobre qué métodos session tiene.

Abortar una transacción

La característica más importante de las transacciones es la capacidad de retroceder todos operaciones en la transacción utilizando el abortTransaction() función.

Pensar en modelando una cuenta bancaria en Mongoose. Para transferir dinero de la cuenta A a la cuenta Btú decrementarías Ael saldo y el incremento Bequilibrio. Sin embargo, si A solo tiene un saldo de $ 5 e intentas transferir $ 10, quieres cancelar la transacción y deshacer el incremento Bequilibrio.

let session =null;return Customer.createCollection().then(()=> Customer.startSession()).then(_session=>
    session = _session;
    session.startTransaction();return Customer.create([ name:'Test'], session: session );).then(()=> Customer.create([ name:'Test2'], session: session )).then(()=> session.abortTransaction()).then(()=> Customer.countDocuments()).then(count=> assert.strictEqual(count,0));

los withTransaction() Ayudante

Los ejemplos anteriores crean explícitamente una transacción y la confirman. En la práctica, querrá utilizar el session.withTransaction() ayudante en lugar de. los session.withTransaction() manijas de ayuda:

  • Creando una transacción
  • Confirmar la transacción si tiene éxito
  • Abortar la transacción si su operación arroja
  • Reintentar en caso de error de transacción transitorio.
return Customer.createCollection().then(()=> Customer.startSession()).// The `withTransaction()` function's first parameter is a function// that returns a promise.then(session=> session.withTransaction(()=>return Customer.create([ name:'Test'], session: session );)).then(()=> Customer.countDocuments()).then(count=> assert.strictEqual(count,1));

Para obtener más información sobre ClientSession#withTransaction() función, por favor vea los documentos del controlador MongoDB Node.js.

Con Documentos de Mangosta y save()

Si obtiene un documento de Mongoose de findOne() o find() usando una sesión, el documento mantendrá una referencia a la sesión y usará esa sesión para save().

Para obtener / configurar la sesión asociada con un documento dado, use doc.$session().

const User = db.model('User',newSchema( name: String ));let session =null;return User.createCollection().then(()=> db.startSession()).then(_session=>
    session = _session;return User.create( name:'foo');).then(()=>
    session.startTransaction();return User.findOne( name:'foo').session(session);).then(user=>// Getter/setter for the session associated with this document.
    assert.ok(user.$session());
    user.name ='bar';// By default, `save()` uses the associated sessionreturn user.save();).then(()=> User.findOne( name:'bar')).// Won't find the doc because `save()` is part of an uncommitted transactionthen(doc=> assert.ok(!doc)).then(()=>
    session.commitTransaction();return User.findOne( name:'bar');).then(doc=> assert.ok(doc));

Con el marco de agregación

los Model.aggregate() La función también admite transacciones. Las agregaciones de mangostas tienen un session() ayudante eso establece el session opción. A continuación, se muestra un ejemplo de cómo ejecutar una agregación dentro de una transacción.

const Event = db.model('Event',newSchema( createdAt: Date ),'Event');let session =null;return Event.createCollection().then(()=> db.startSession()).then(_session=>
    session = _session;
    session.startTransaction();return Event.insertMany([ createdAt:newDate('2018-06-01'), createdAt:newDate('2018-06-02'), createdAt:newDate('2017-06-01'), createdAt:newDate('2017-05-31')], session: session );).then(()=> Event.aggregate([
      $group:
        _id:
          month: $month:'$createdAt',
          year: $year:'$createdAt',
        count: $sum:1, $sort: count:-1,'_id.year':-1,'_id.month':-1]).session(session)).then(res=>
    assert.deepEqual(res,[ _id: month:6, year:2018, count:2, _id: month:6, year:2017, count:1, _id: month:5, year:2017, count:1]);
    session.commitTransaction(););