使用 Core API
您可以执行一个事务来运行一系列操作,这些操作在提交整个事务之前不会更改任何数据。 此用法示例使用Core API执行事务。
提示
另请参阅:
要学习;了解有关在 Node.js驾驶员中执行事务的更多信息,请参阅事务指南。
Node.js 驱动程序还提供了便捷事务 API 来执行事务。 要了解有关便捷事务 API 的更多信息,请参阅使用便捷事务 API用法示例。
例子
考虑客户从您的在线商店购买商品的情况。 要记录购买,应用程序必须更新库存和客户订单。 您的应用程序还需要保存订单详细信息。
下表描述了存储购买数据的collection,以及购买如何更改每个collection中的数据。
Collection | 操作 | 变更说明 |
---|---|---|
| insert | 插入描述订单的文档 |
| 更新或更新插入 | 将订单文档中的 |
| update | 更新购买后可用商品的数量 |
样本数据
代码示例使用testdb
数据库中的以下样本数据:
customers
集合中描述客户及其过往订单的文档inventory
collection中的文档,其中包括所有商品的数量和说明
以下文档位于customers
collection中:
{ _id: 98765, orders: [] }
inventory
集合包含以下文档:
{ item: "sunblock", item_id: 5432, qty: 85 }, { item: "beach towel", item_id: 7865, qty: 41 }
您将购买记录存储在testdb
数据库的orders
集合中。 此collection为空,因为没有任何购买操作。
代码示例使用cart
和payment
变量来表示所购商品的样本清单和订单付款详情。 以下代码描述了cart
和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 };
实现
本节中的代码示例演示了如何使用 Core API 在会话中执行多文档事务。 在此示例中,事务在客户从您的商店购买商品时进行所需的更改。
此示例代码通过以下动作执行事务:
调用
startSession()
方法创建新会话使用选项参数调用
startTransaction()
方法以创建新事务在事务中执行以下操作:
将文档插入到
orders
集合中,其中包含有关购买和客户的信息如果有足够的库存来完成采购,更新
inventory
collection如果订单中的任何商品没有足够的库存,则结束事务并引发异常
将订单 ID 添加到客户过去的订单列表中
返回一条消息,确认已使用购买记录的副本成功提交事务
如果所有操作均成功完成,则调用
commitTransaction()
方法提交事务实现包含错误处理逻辑的
catch
区块调用
abortTransaction()
方法结束事务调用
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(); } }
事务结果
本节描述事务创建的数据更改。
The customers
collection 包含客户文档,其订单字段附加了订单_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 文档
要了解有关此用法示例中讨论的任何方法或类型的更多信息,请参阅以下 API 文档: