MongoDB 注文スキーマの設計

MongoDBBeginner
オンラインで実践に進む

はじめに

この実験では、e コマースアプリケーション向けの MongoDB スキーマを設計する方法を学びます。目標は、管理とクエリが容易な、各注文に対する単一の包括的なドキュメントを作成することです。まず基本的な注文構造を作成し、次に詳細な顧客情報、注文アイテムのリスト、支払い詳細、ステータス履歴を埋め込むことで段階的にリッチ化していきます。このアプローチは、実際のアプリケーションにおける MongoDB のドキュメントモデルの強力さを示しています。

基本的な注文ドキュメントの作成

最初のステップでは、MongoDB に接続し、新しいデータベースを作成します。その後、最初の注文ドキュメントを挿入します。これは、次のステップで構築するスキーマの基盤となります。

まず、MongoDB Shell を開きます。この対話型のコマンドラインインターフェースを使用すると、MongoDB データベースと通信できます。

mongosh

シェルに入ると、> プロンプトが表示されます。次に、ecommerce という名前の新しいデータベースに切り替えます。データベースが存在しない場合、MongoDB は最初にデータを保存する際に自動的に作成します。

use ecommerce

次に、ドキュメントを挿入して orders という名前のコレクションを作成します。このドキュメントは単一の注文を表し、注文 ID、顧客詳細、注文日、現在のステータスなどの必須情報を含みます。

ドキュメントを挿入するには、次のコマンドを実行します。

db.orders.insertOne({
  order_id: "ORD001",
  order_date: new Date("2023-10-26T10:00:00Z"),
  customer_id: "CUST123",
  status: "pending",
  total: 150.0
});

このコマンドは以下の操作を実行します。

  • db.orders: 現在のデータベース内の orders コレクションを指定します。
  • insertOne(): 単一のドキュメントを挿入するための MongoDB メソッドです。
  • ドキュメント自体は、order_idorder_datecustomer_idstatustotal のキーと値のペアを持つ JSON ライクなオブジェクトです。

挿入が成功すると、MongoDB は確認応答と、新しく作成されたドキュメントの一意の _id を返します。

{
  "acknowledged": true,
  "insertedId": ObjectId("...")
}

これで、注文の基本的な構造が作成されました。次のステップでは、このドキュメントをより詳細な情報で強化します。

埋め込み顧客詳細による強化

単なる customer_id だけでは不十分な場合が多くあります。実際のアプリケーションでは、注文を取得する際に顧客の名前や住所が必要になることがよくあります。customers コレクションへの別個のクエリを実行する代わりに、この情報を注文ドキュメント内に直接埋め込むことができます。これは MongoDB で一般的かつ強力なパターンであり、読み取りパフォーマンスを向上させます。

このステップでは、詳細なネストされた顧客情報を含めるように注文ドキュメントを更新します。前のステップで mongosh シェルを終了した場合は、再度起動して use ecommerce を実行してください。

updateOne() メソッドを使用して、order_id: "ORD001" のドキュメントを検索し、それを変更します。$set 演算子はフィールドの値を指定された値に置き換え、$unset はフィールドを完全に削除します。

db.orders.updateOne(
  { order_id: "ORD001" },
  {
    $set: {
      customer: {
        customer_id: "CUST123",
        first_name: "John",
        last_name: "Doe",
        email: "john.doe@example.com",
        shipping_address: {
          street: "123 Main St",
          city: "Anytown",
          state: "CA",
          zip_code: "12345"
        }
      }
    },
    $unset: {
      customer_id: ""
    }
  }
);

このコマンドでは:

  • 最初の引数 { order_id: "ORD001" } は、更新するドキュメントを選択するためのフィルターです。
  • 2 番目の引数には、更新演算子が含まれています。
    • $set: 詳細情報を含む埋め込みドキュメントである新しいフィールド customer を設定しています。
    • $unset: データ冗長性を避けるために、古いトップレベルの customer_id フィールドを削除しています。

変更を確認するには、findOne() を使用して更新されたドキュメントを取得できます。

db.orders.findOne({ order_id: "ORD001" });

出力には、ネストされた customer ドキュメントが表示され、トップレベルの customer_id フィールドはなくなります。この埋め込み構造により、関連データが単一のドキュメントにまとめられます。

注文アイテムの配列を追加する

注文は通常、1 つ以上の製品で構成されます。単一の注文ドキュメント内でこの 1 対多の関係をモデル化する最良の方法は、埋め込みドキュメントの配列を使用することです。配列の各要素は、注文内のアイテムを表します。

注文ドキュメントを更新して、アイテムのリストを含めましょう。items フィールドを追加します。これは配列になります。配列内の各オブジェクトには、製品 ID、名前、価格、数量などの製品に関する詳細が含まれます。

次の updateOne コマンドを実行します。

db.orders.updateOne(
  { order_id: "ORD001" },
  {
    $set: {
      items: [
        {
          product_id: "PROD01",
          name: "Laptop",
          price: 1200.0,
          quantity: 1
        },
        {
          product_id: "PROD02",
          name: "Mouse",
          price: 25.0,
          quantity: 1
        }
      ],
      total: 1225.0
    }
  }
);

ここでは、再度 $set を使用して items 配列を追加します。また、アイテム価格の合計と一致するように total フィールドも更新します。計算された合計をドキュメントに直接保存することも、別のパフォーマンス最適化です。これにより、すべての読み取りで集計を実行する必要がなくなります。

新しい items 配列を確認するために、再度ドキュメントを確認しましょう。

db.orders.findOne({ order_id: "ORD001" });

注文ドキュメント内に埋め込まれた items 配列が表示されます。この設計により、すべてのアイテムを含む完全な注文を単一のデータベースクエリで取得できます。

支払い情報の埋め込み

支払い詳細は、注文のもう一つの重要な部分です。顧客情報やアイテムと同様に、支払いデータも注文ドキュメントに直接埋め込むことができます。これには、支払い方法、トランザクション ID、ステータスが含まれます。

このステップでは、注文に payment サブドキュメントを追加します。

db.orders.updateOne(
  { order_id: "ORD001" },
  {
    $set: {
      payment: {
        method: "credit_card",
        transaction_id: "TXN54321",
        status: "completed"
      }
    }
  }
);

このコマンドは、methodtransaction_idstatus の 3 つのフィールドを持つ payment オブジェクトを追加します。この情報を埋め込むことで、単一のトランザクションに関連するすべてのデータが 1 か所に配置されることが保証されます。

これで、注文ドキュメントの構造を見てみましょう。

db.orders.findOne({ order_id: "ORD001" });

ドキュメントには、注文、顧客、アイテム、支払いに関する包括的な情報が含まれており、すべて単一の読み取り操作でアクセスできます。

注文ステータスの履歴を追跡する

注文は、「保留中」、「処理中」、「発送済み」、「配達済み」など、さまざまな段階を経て進みます。トップレベルの status フィールドは現在の状態を示しますが、すべてのステータス変更のログを維持することはしばしば有用です。これを実現するために status_history 配列を追加できます。

この最終ステップでは、注文ステータスを「処理中」に更新し、status_history 配列の構築を開始します。$push オペレーターは、配列に値を追加するために使用されます。

まず、初期の「保留中」ステータスを履歴に追加し、現在のステータスを「処理中」に更新しましょう。

db.orders.updateOne(
  { order_id: "ORD001" },
  {
    $set: { status: "processing" },
    $push: {
      status_history: {
        status: "pending",
        timestamp: new Date("2023-10-26T10:00:00Z")
      }
    }
  }
);

次に、ログを完全にするために、新しい「処理中」ステータスを履歴に追加しましょう。

db.orders.updateOne(
  { order_id: "ORD001" },
  {
    $push: {
      status_history: {
        status: "processing",
        timestamp: new Date("2023-10-26T11:30:00Z")
      }
    }
  }
);

このアプローチにより、注文のライフサイクルの完全な監査証跡が得られます。いつでもドキュメントをクエリして、その完全な履歴を確認できます。

db.orders.findOne({ order_id: "ORD001" });

ドキュメントには status_history 配列が含まれるようになり、注文の過程を完全に把握できるようになりました。MongoDB シェルを終了するには、「exit」と入力して Enter キーを押します。

まとめ

この実験では、e コマースの注文のための実用的で効率的な MongoDB スキーマを設計する方法を学びました。基本的なドキュメントから始め、関連データを埋め込むことによって段階的にリッチ化しました。顧客の詳細、注文アイテムの配列、支払い情報、および完全なステータス履歴を含む単一のドキュメントを正常に作成しました。この埋め込みドキュメントパターンは、MongoDB スキーマ設計におけるコアコンセプトであり、複雑な結合や複数のクエリの必要性を減らすことで、パフォーマンスが高くスケーラブルなアプリケーションの作成を支援します。