Join us Sept 17 at .local NYC! Use code WEB50 to save 50% on tickets. Learn more >
MongoDB Event
Docs Menu
Docs Home
/ / /
Node.js ドライバー
/ /

Core API の使用

トランザクションを実行して、トランザクション全体がコミットされるまでデータを変更しない一連の操作を実行できます。 この使用例では、 Core APIを使用してトランザクションを実行しています。

Tip

Node.js ドライバーでトランザクションを実行する方法の詳細については、 トランザクションガイドを参照してください。

Node.js ドライバーは、トランザクションを実行するための Convenient Transaction API も提供します。 Convenient Transaction API の詳細については、 「 Convenient Transaction APIの使用 」使用例を参照してください。

カスタマーがオンライン ショップから商品を購入するシナリオを考えてみましょう。 購入を記録するには、アプリケーションが在庫とカスタマーの注文を更新する必要があります。 アプリケーションは注文の詳細を保存する必要もあります。

次の表では、購入データを保存するコレクションと、購入によって各コレクションのデータがどのように変更されるかについて説明しています。

コレクション
操作
変更の説明

orders

insert

順序を説明するドキュメントを挿入します

customers

アップデートまたはアップサート

注文ドキュメントの_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 };

このセクションのコード例は、Core 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();
}
}

Tip

明示的なリソース管理

The Node.js driver natively supports explicit resource management for MongoClient, ClientSession, ChangeStreams, and cursors. This feature is experimental and subject to change. To learn how to use explicit resource management, see the v6.9 Release Notes.

このセクションでは、トランザクションによって作成されたデータの変更について説明します。

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 ドキュメントを参照してください。

戻る

Convenient Transaction API

項目一覧