Core API の使用
トランザクションを実行して、トランザクション全体がコミットされるまでデータを変更しない一連の操作を実行できます。 この使用例では、 Core APIを使用してトランザクションを実行しています。
Tip
以下も参照してください。
Node.js ドライバーでトランザクションを実行する方法の詳細については、 トランザクションガイドを参照してください。
Node.js ドライバーは、トランザクションを実行するための Convenient Transaction API も提供します。 Convenient Transaction API の詳細については、 「 Convenient Transaction APIの使用 」使用例を参照してください。
例
カスタマーがオンライン ショップから商品を購入するシナリオを考えてみましょう。 購入を記録するには、アプリケーションが在庫とカスタマーの注文を更新する必要があります。 アプリケーションは注文の詳細を保存する必要もあります。
次の表では、購入データを保存するコレクションと、購入によって各コレクションのデータがどのように変更されるかについて説明しています。
コレクション | 操作 | 変更の説明 |
---|---|---|
| insert | 順序を説明するドキュメントを挿入します |
| アップデートまたはアップサート | 注文ドキュメントの |
| 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
コレクションに保存します。 購入がないため、このコレクションは空です。
コード例では、 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
コレクションを更新しますトランザクションを終了し、注文内のどのアイテムの在庫が十分でない場合は例外をスローします
注文 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(); } }
トランザクションの結果
このセクションでは、トランザクションによって作成されたデータの変更について説明します。
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 ドキュメント
この使用例で説明したメソッドやタイプの詳細については、次の API ドキュメントを参照してください。