Docs Menu
Docs Home
/ /

Utilice la API principal

Puede realizar una transacción para ejecutar una serie de operaciones que no modifican ningún dato hasta que se confirme toda la transacción. Este ejemplo de uso utiliza la API principal para realizar una transacción.

Tip

Para obtener más información sobre la realización de transacciones en el controlador Node.js, consulte Guía de transacciones.

El controlador de Node.js también proporciona la API de Transacciones Convenientes para realizar transacciones. Para obtener más información sobre la API de Transacciones Convenientes, consulte el ejemplo de uso de la API de Transacciones Convenientes.

Imaginemos una situación en la que un cliente compra artículos en su tienda online. Para registrar la compra, la aplicación debe actualizar el inventario y los pedidos del cliente. También debe guardar los detalles del pedido.

La siguiente tabla describe las colecciones que almacenan datos de compra y cómo una compra cambia los datos en cada colección.

Colección
Operación
Descripción del cambio

orders

insert

Inserta un documento que describe el pedido.

customers

actualizar o insertar

Añade el _id del documento de pedido al historial de pedidos en el documento del cliente

inventory

update

Actualiza las cantidades de artículos disponibles después de una compra.

Los ejemplos de código utilizan los siguientes datos de muestra en la base de datos testdb:

  • Documentos de la colección customers que describen a los clientes y sus pedidos anteriores

  • Documents in the inventory collection that include quantities and descriptions de all artículos

El siguiente documento está en la colección customers:

{ _id: 98765, orders: [] }

La colección inventory contiene los siguientes documentos:

{ item: "sunblock", item_id: 5432, qty: 85 },
{ item: "beach towel", item_id: 7865, qty: 41 }

Almacena los registros de compra en la colección orders de la base de datos testdb. Esta colección está vacía, ya que no se han realizado compras.

Los ejemplos de código utilizan las variables cart y payment para representar una lista de ejemplo de artículos comprados y los detalles de pago del pedido. El siguiente código describe el contenido de las variables cart y payment:

const cart = [
{ item: 'sunblock', item_id: 5432, qty: 1, price: 5.19 },
{ item: 'beach towel', item_id: 7865, qty: 2, price: 15.99 }
];
const payment = { customer: 98765, total: 37.17 };

El ejemplo de código de esta sección muestra cómo usar la API principal para realizar una transacción multidocumento en una sesión. En este ejemplo, la transacción realiza los cambios necesarios cuando un cliente compra artículos en su tienda.

Este código de ejemplo realiza una transacción a través de las siguientes acciones:

  1. Llama al método startSession() para crear una nueva sesión

  2. Llama al método startTransaction() con un parámetro de opciones para crear una nueva transacción

  3. Realiza las siguientes operaciones dentro de la transacción:

    • Inserta un documento en la colección orders que contiene información sobre la compra y el cliente.

    • Actualiza la colección inventory si hay suficiente inventario para completar la compra

    • Finaliza la transacción y lanza una excepción si no hay suficiente inventario para algún artículo en el pedido

    • Agrega el ID del pedido a la lista de pedidos anteriores del cliente

    • Devuelve un mensaje que reconoce que la transacción se realizó correctamente con una copia del registro de compra.

  4. Llama al método commitTransaction() para confirmar la transacción si todas las operaciones se completan correctamente

  5. Implementa un bloque catch que contiene lógica de manejo de errores

  6. Llama al método abortTransaction() para finalizar la transacción

  7. Llama al método endSession() para finalizar la sesión

async function placeOrder(client, cart, payment) {
const transactionOptions = {
readConcern: { level: 'snapshot' },
writeConcern: { w: 'majority' },
readPreference: 'primary'
};
// Start the session
const session = client.startSession();
try {
// Start the transaction in the session, specifying the transaction options
session.startTransaction(transactionOptions);
const ordersCollection = client.db('testdb').collection('orders');
/* Within the session, insert an order that contains information about the
customer, items purchased, and the total payment */
const orderResult = await ordersCollection.insertOne(
{
customer: payment.customer,
items: cart,
total: payment.total,
},
{ session }
);
const inventoryCollection = client.db('testdb').collection('inventory');
for (const item of order) {
/* Update the inventory for the purchased items. End the
transaction if the quantity of an item in the inventory is
insufficient to complete the purchase. */
const inStock = await inventoryCollection.findOneAndUpdate(
{
item_id: item.item_id,
item_id: { $gte: item.qty }
},
{ $inc: { 'qty': -item.qty }},
{ session }
)
if (inStock === null) {
throw new Error('Insufficient quantity or item ID not found.');
}
}
const customerCollection = client.db('testdb').collection('customers');
// Within the session, add the order details to the "orders" array of the customer document
await customerCollection.updateOne(
{ _id: payment.customer },
{ $push: { orders: orderResult.insertedId }},
{ session }
);
// Commit the transaction to apply all updates performed within it
await session.commitTransaction();
console.log('Transaction successfully committed.');
} catch (error) {
/*
Handle any exceptions thrown during the transaction and end the
transaction. Roll back all the updates performed in the transaction.
*/
if (error instanceof MongoError && error.hasErrorLabel('UnknownTransactionCommitResult')) {
// Add your logic to retry or handle the error
}
else if (error instanceof MongoError && error.hasErrorLabel('TransientTransactionError')) {
// Add your logic to retry or handle the error
} else {
console.log('An error occured in the transaction, performing a data rollback:' + error);
}
await session.abortTransaction();
} finally {
// End the session
await session.endSession();
}
}

Tip

Gestión explícita de recursos

El controlador Node.js admite de forma nativa la gestión explícita de recursos para MongoClient, ClientSession, ChangeStreams y cursores. Esta función es experimental y está sujeta a cambios. Para aprender a usar la gestión explícita de recursos, consulte Notas de la versión v6.9.

Esta sección describe los cambios de datos creados por la transacción.

La colección customers contiene el documento del cliente con un pedido _id añadido al campo de pedidos:

{
"_id": 98765,
"orders": [
"61dc..."
]
}

La colección inventory contiene cantidades actualizadas para los artículos "sunblock" y "beach towel":

[
{
"_id": ...,
"item": "sunblock",
"item_id": 5432,
"qty": 84
},
{
"_id": ...,
"item": "beach towel",
"item_id": 7865,
"qty": 39
}
]

La colección orders contiene la información del pedido y del pago:

[
{
"_id": "...",
"customer": 98765,
"items": [
{
"item": "sunblock",
"item_id": 5432,
"qty": 1,
"price": 5.19
},
{
"item": "beach towel",
"item_id": 7865,
"qty": 2,
"price": 15.99
}
],
"total": 37.17
}
]

Para obtener más información sobre cualquiera de los métodos o tipos analizados en este ejemplo de uso, consulte la siguiente documentación de API:

Volver

API de transacciones convenientes

En esta página