Use the Core API
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 Core API to perform a transaction.
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 Convenient Transaction API to perform transactions. To learn more about the Convenient Transaction API, see the Use the Convenient Transaction API usage example.
Example
Consider a situation in which a customer purchases items from your online shop. To record the purchase, your application must update your inventory and the customer's orders. Your application also needs to save the order details.
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 | 
|---|---|---|
| 
 | insert | Inserts a document that describes the order | 
| 
 | update or upsert | Appends the  | 
| 
 | update | Updates the quantities of items available after a purchase | 
Sample Data
The code examples use the following sample data in the testdb
database:
- Documents in the - customerscollection that describe customers and their past orders
- Documents in the - inventorycollection that include quantities and descriptions of all items
The following document is in the customers collection:
{ _id: 98765, orders: [] } 
The inventory collection contains the following documents:
{ item: "sunblock", item_id: 5432, qty: 85 }, { item: "beach towel", item_id: 7865, qty: 41 } 
You store purchase records in the orders collection of the
testdb database. This collection is empty, as there have been no
purchases.
The code examples use the cart and payment variables to represent
a sample list of items purchased and the order payment details. The
following code describes the contents of the cart and payment variables:
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 }; 
Implementation
The code example in this section demonstrates how to use the Core 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:
- Calls the - startSession()method to create a new session
- Calls the - startTransaction()method with an options parameter to create a new transaction
- Performs the following operations within the transaction: - Inserts a document to the - orderscollection that contains information about the purchase and customer
- Updates the - inventorycollection 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 
- Adds the ID of the order to the list of past orders for the customer 
- Returns a message acknowledging that the transaction committed successfully with a copy of the purchase record 
 
- Calls the - commitTransaction()method to commit the transaction if all operations complete successfully
- Implements a - catchblock that contains error-handling logic
- Calls the - abortTransaction()method to end the transaction
- Calls the - endSession()method to end the session
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();   } } 
Transaction Results
This section describes the data changes created by the transaction.
The customers collection contains the customer document with an
order _id appended to the orders field:
{   "_id": 98765,   "orders": [     "61dc..."   ] } 
The inventory collection contains updated quantities for the
items "sunblock" and "beach towel":
[   {     "_id": ...,     "item": "sunblock",     "item_id": 5432,     "qty": 84   },   {     "_id": ...,     "item": "beach towel",     "item_id": 7865,     "qty": 39   } ] 
The orders collection contains the order and payment
information:
[   {     "_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   } ] 
API Documentation
To learn more about any of the methods or types discussed in this usage example, see the following API Documentation: