文档菜单
文档首页
/ / /
Node.js 驱动程序
/ /

使用核心 API

在本页

  • 示例
  • 示例数据
  • 实现
  • 事务结果
  • API 文档

您可以使用事务来执行一系列操作,直到整个事务提交才更改任何数据。此使用示例使用 核心 API 执行事务。

提示

另请参阅

有关 Node.js 驱动程序中执行事务的更多信息,请参阅事务 指南。

Node.js 驱动还提供了一个方便的事务 API 来执行事务。要了解更多关于方便事务 API 的信息,请参阅使用方便事务 API的使用示例。

考虑一个客户从您的在线商店购买商品的情况。为了记录购买,您的应用程序必须更新您的库存和客户的订单。您的应用程序还需要保存订单详情。

以下表格描述了存储购买数据的集合以及购买如何更改每个集合中的数据。

集合
操作
更改描述
orders
insert
插入描述订单的文档
customers
update or upsert
将订单文档中的 _id 追加到客户文档中的订单历史
inventory
update
更新购买后可用物品的数量

以下代码示例使用 testdb 数据库中的以下示例数据

  • customers 集合中的文档描述客户及其过去的订单

  • inventory 集合中的文档包括所有物品的数量和描述

以下文档位于 customers 集合中

{ _id: 98765, orders: [] }

inventory 集合包含以下文档

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

您将购买记录存储在 testdb 数据库的 orders 集合中。此集合为空,因为没有进行任何购买。

以下代码示例使用 cartpayment 变量来表示购买物品的示例列表和订单支付详情。以下代码描述了 cartpayment 变量的内容

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 };

本节中的代码示例展示了如何使用核心API在会话中执行多文档事务。在此示例中,事务在客户从您的商店购买商品时进行必要的更改。

此示例代码通过以下操作执行事务

  1. 调用 startSession() 方法创建新会话

  2. 调用 startTransaction() 方法并传递一个选项参数来创建新事务

  3. 在事务中执行以下操作

    • 将包含购买和客户信息的文档插入到 orders 集合中

    • 如果有足够的库存来满足购买,则更新 inventory 集合

    • 结束事务,如果订单中的任何商品库存不足,则抛出异常

    • 将订单ID添加到客户的过去订单列表中

    • 返回确认事务成功提交的消息以及购买记录的副本

  4. 如果所有操作都成功完成,则调用 commitTransaction() 方法提交事务

  5. 实现一个包含错误处理逻辑的 catch

  6. 调用 abortTransaction() 方法结束事务

  7. 调用 endSession() 方法结束会话

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();
}
}

本节描述了事务创建的数据更改。

customers 集合包含带有附加到订单字段的订单 _id 的客户文档

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

inventory 集合包含物品 "sunblock""beach towel" 的更新数量

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

orders 集合包含订单和付款信息

[
{
"_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 文档

  • TransactionOptions

  • ClientSession

  • startSession()

  • startTransaction()

  • commitTransaction()

  • abortTransaction()

  • endSession()

返回

便捷的事务 API