Convenient Transaction API の使用
トランザクションを実行して、トランザクション全体がコミットされるまでデータを変更しない一連の操作を実行できます。 この使用例では、 Convenient Transaction APIを使用してトランザクションを実行します。
Tip
以下も参照してください。
Node.js ドライバーでトランザクションを実行する方法の詳細については、 トランザクションガイドを参照してください。
Node.js ドライバーは、トランザクションを実行するための Core API も提供します。 Core API の詳細については、 「 Core APIの使用例 」を参照してください。
例
カスタマーが店舗から商品を購入するシナリオを考えてみましょう。 購入を記録するには、アプリケーションで在庫を更新し、注文情報を記録する必要があります。
次の表では、購入データを保存するコレクションと、購入によって各コレクションのデータがどのように変更されるかについて説明しています。
コレクション | 操作 | 変更の説明 |
---|---|---|
orders | insert | 順序を説明するドキュメントを挿入します |
inventory | update | 購入後に利用可能なアイテムの量を更新します |
サンプル データ
inventory
コレクションには次のドキュメントが含まれます。
{ item: "sunblock", qty: 85, price: 6.0 }, { item: "beach chair", qty: 30, price: 25.0 }
購入レコードは、 testdb
データベースのorders
コレクションに保存します。 購入がないため、このコレクションは空です。
実装
このセクションのコード例は、 Convenient Transaction API を使用してセッション内でマルチドキュメントトランザクションを実行する方法を示しています。 この例では、トランザクションは、顧客が店舗から商品を購入する際に必要な変更を行っています。
このサンプル コードでは、次のアクションを通じてトランザクションを実行します。
クライアントで
withSession()
メソッドを呼び出して暗黙的にセッションを作成し、それに渡されたコールバックをセッション内で実行します。セッションで
withTransaction()
メソッドを呼び出してトランザクションを作成し、それに渡されたコールバックを実行して、トランザクションをコミットします。 トランザクションが失敗した場合、このメソッドはトランザクションを終了し、エラーメッセージを返します。トランザクション内で次の操作を実行します。
購入を実行するのに十分な在庫がある場合は、
inventory
コレクションとorders
コレクションを更新しますトランザクションを終了し、注文内のどのアイテムの在庫が十分でない場合は例外をスローします
購入レコードのコピーを使用して、トランザクションが正常にコミットされたことを確認するメッセージを返します
エラー メッセージまたはトランザクションが完了した確認応答である
withSession()
の戻り値の型を出力します。
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);
サンプル注文とトランザクションの結果
このセクションでは、2 つのサンプル注文に対して実行されたトランザクションの結果について説明します。
以下の注文向けの十分な在庫があるため、トランザクションは正常に完了します。
{ item: "sunblock", qty: 3 }, { item: "beach chair", qty: 1 }
この順序をサンプルトランザクションコードに渡すと、コードは次の結果を出力します。
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": "..." }
inventory
コレクションでは、 "sunblock"
の量は82
に、 "beach chair"
の量は29
になりました。 orders
コレクションには購入のレコードが含まれています。
次の注文に十分な在庫がないため、ドライバーはトランザクションを終了します。
{ item: "volleyball", qty: 1 }
この順序をサンプルトランザクションコードに渡すと、コードは次の結果を出力します。
Item not found or insufficient quantity.
ドライバーがトランザクションを終了するため、inventory
orders
コレクションと コレクションは変更されません。
API ドキュメント
この使用例で説明したメソッドやタイプの詳細については、次の API ドキュメントを参照してください。