Docs Menu
Docs Home
/ / /
Node.js Driver
/ /

Use the Convenient Transaction API

On this page

  • Example
  • Sample Data
  • Implementation
  • Sample Orders and Transaction Results
  • API Documentation

You can perform a transaction to run a series of operations that do not change any data until the entire transaction is committed. This usage example uses the Convenient Transaction API to perform a transaction.

Tip

See also:

To learn more about the performing transactions in the Node.js driver, see the Transactions guide.

The Node.js driver also provides the Core API to perform transactions. To learn more about the Core API, see the Use the Core API usage example.

Consider a situation in which a customer purchases items from your shop. To record the purchase, your application must update your inventory and record the order information.

The following table describes the collections that store purchase data and how a purchase changes the data in each collection.

Collection
Operation
Description of the Change

orders

insert

Inserts a document that describes the order

inventory

update

Updates the quantities of items available after a purchase

The inventory collection contains the following documents:

{ item: "sunblock", qty: 85, price: 6.0 },
{ item: "beach chair", qty: 30, price: 25.0 }

You store purchase records in the orders collection of the testdb database. This collection is empty, as there have been no purchases.

The code example in this section demonstrates how to use the Convenient Transaction API to perform a multi-document transaction in a session. In this example, the transaction makes the changes needed when a customer purchases items from your shop.

This example code performs a transaction through the following actions:

  1. Calls the withSession() method on the client to implicitly create the session and run the callback passed to it within the session.

  2. Calls the withTransaction() method on the session to create a transaction, run the callback passed to it, and commit the transaction. If the transaction fails, this method ends the transaction and returns an error message.

  3. Performs the following operations within the transaction:

    • Updates the inventory and orders collections if there is sufficient inventory to fulfill the purchase

    • Ends the transaction and throws an exception if there isn't sufficient inventory for any item in the order

    • Returns a message acknowledging that the transaction committed successfully with a copy of the purchase record

  4. Prints the return type of withSession(), which is either the error message or the acknowledgment that the transaction completed.

const txnResult = await client.withSession(async (session) =>
session
.withTransaction(async (session) => {
const invColl = client.db("testdb").collection("inventory");
const recColl = client.db("testdb").collection("orders");
let total = 0;
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 invColl.findOneAndUpdate(
{
item: item.item,
qty: { $gte: item.qty },
},
{ $inc: { qty: -item.qty } },
{ session }
);
if (inStock === null) {
await session.abortTransaction();
return "Item not found or insufficient quantity.";
}
const subTotal = item.qty * inStock.price;
total = total + subTotal;
}
// Create a record of the purchase
const receipt = {
date: new Date(),
items: order,
total: total,
};
await recColl.insertOne(receipt, { session });
return (
"Order successfully completed and recorded!\nReceipt:\n" +
JSON.stringify(receipt, null, 1)
);
}, null)
.finally(async () => await client.close())
);
console.log(txnResult);

This section describes the results of the transactions performed for two sample orders.

Sufficient inventory exists for the following order, so the transaction successfully completes:

{ item: "sunblock", qty: 3 },
{ item: "beach chair", qty: 1 }

After passing this order to the example transaction code, the code outputs the following result:

Order successfully completed and recorded!
Receipt:
{
"date": "2023-08-25T20:06:52.564Z",
"items": [
{ "item": "sunblock", "qty": 3 },
{ "item": "beach chair", "qty": 1 }
],
"total": 43,
"_id": "..."
}

In the inventory collection, the quantity of "sunblock" is now 82 and the quantity of "beach chair" is 29. The orders collection contains the record of the purchase.

There is not sufficient inventory for the following order, so the driver ends the transaction:

{ item: "volleyball", qty: 1 }

After passing this order to the example transaction code, the code outputs the following result:

Item not found or insufficient quantity.

Since the driver ends the transaction, there are no changes to the inventory and orders collections.

To learn more about any of the methods or types discussed in this usage example, see the following API Documentation:

  • withSession()

  • withTransaction()

  • abortTransaction()"

Back

Perform a Transaction