DynamoDB をオンラインショップのデータストアとして使用する - Amazon DynamoDB

DynamoDB をオンラインショップのデータストアとして使用する

このユースケースでは、オンラインショップ (または e ストア) のデータストアとして DynamoDB を使用する方法について説明しています。

ユースケース

オンラインストアでは、ユーザーはさまざまな製品を閲覧し、最終的に購入することができます。生成された請求書に基づいて、お客様はディスカウントコードまたはギフトカードを使用して支払い、残りの金額をクレジットカードで支払うことができます。購入した商品は、複数の倉庫から集荷され、指定された住所に発送されます。オンラインストアの一般的なアクセスパターンは以下のとおりです。

  • 指定された customerId のお客様を取得する

  • 指定された productId の製品を取得する

  • 指定された warehouseId の倉庫を取得する

  • productId で全倉庫の商品在庫を取得する

  • 指定された OrderId の注文を取得する

  • 指定された OrderID のすべての商品を取得する

  • 指定された OrderID の請求書を取得する

  • 指定された OrderID のすべての出荷情報を取得する

  • 指定された日付範囲における指定された productId のすべての注文を取得する

  • 指定された invoiceId の請求書を取得する

  • 指定された InvoiceID のすべての支払いを取得する

  • 指定された shipmentId の出荷詳細を取得する

  • 指定された warehouseId のすべての出荷情報を取得する

  • 指定された warehouseId のすべての商品の在庫を取得する

  • 指定された日付範囲における指定された customerId のすべての請求書を取得する

  • 指定された日付範囲で指定された customerId で注文されたすべての製品を取得する

エンティティ関係図

これは、オンラインショップのデータストアとして DynamoDB をモデル化するために使用するエンティティ関係図 (ERD) です。

製品、注文、支払い、顧客などのエンティティを示す、オンラインストアのデータモデルの ERD。

アクセスパターン

以上が、DynamoDB をオンラインショップのデータストアとして利用する場合のアクセスパターンです。

  1. getCustomerByCustomerId

  2. getProductByProductId

  3. getWarehouseByWarehouseId

  4. getProductInventoryByProductId

  5. getOrderDetailsByOrderId

  6. getProductByOrderId

  7. getInvoiceByOrderId

  8. getShipmentByOrderId

  9. getOrderByProductIdForDateRange

  10. getInvoiceByInvoiceId

  11. getPaymentByInvoiceId

  12. getShipmentDetailsByShipmentId

  13. getShipmentByWarehouseId

  14. getProductInventoryByWarehouseId

  15. getInvoiceByCustomerIdForDateRange

  16. getProductsByCustomerIdForDateRange

スキーマ設計の進化

DynamoDB 用の NoSQL Workbench を使用して、AnOnlineShop_1.json をインポートし、AnOnlineShop という新しいデータモデルと OnlineShop という新しいテーブルを作成します。パーティションキーとソートキーには一般的な名前 PKSK を使用することに注意してください。これは、さまざまなタイプのエンティティを同じテーブルに保存するための方法です。

ステップ 1: アクセスパターン 1 (getCustomerByCustomerId) に対処する

AnOnlineShop_2.json をインポートして、アクセスパターン 1 (getCustomerByCustomerId) を処理します。エンティティの中には他のエンティティとリレーションシップを持たないものもあるため、それらには同じ値の PKSK を使用します。データ例では、customerId を後で追加される他のエンティティから区別するために、キーに接頭辞 c# が使われていることに注意してください。この方法は他のエンティティでも繰り返されます。

このアクセスパターンに対処するために、GetItem オペレーションを PK=customerIdSK=customerId で使用できます。

ステップ 2: アクセスパターン 2 (getProductByProductId) に対処する

AnOnlineShop_3.json をインポートして、product エンティティのアクセスパターン 2 (getProductByProductId) に対処します。製品エンティティには p# というプレフィックスが付けられ、同じソートキー属性が customerIDproductID の保存にも使われています。一般的な命名規則と垂直パーティショニングによって、このような項目コレクションを作成し、効果的な単一テーブル設計を実現できます。

このアクセスパターンに対処するため、GetItem オペレーションは PK=productId および SK=productId で使用できます。

ステップ 3: アクセスパターン 3 (getWarehouseByWarehouseId) に対処する

AnOnlineShop_4.json をインポートして、warehouse エンティティのアクセスパターン 3 (getWarehouseByWarehouseId) に対処します。現在、customerproduct、および warehouse エンティティが同じテーブルに追加されています。これらはプレフィックスと EntityType 属性を使用して区別されます。タイプ属性 (またはプレフィックスの命名) は読みやすさを向上させます。さまざまなエンティティの英数字 ID を同じ属性に保存するだけでは、読みやすさに影響が出ます。これらの識別子がないと、あるエンティティを別のエンティティと区別するのが難しくなります。

このアクセスパターンに対処するため、GetItem オペレーションは PK=warehouseId および SK=warehouseId で使用できます。

ベーステーブル:

ID で倉庫データを取得するためのプレフィックスと EntityType を含む DynamoDB テーブル設計。

ステップ 4: アクセスパターン 4 (getProductInventoryByProductId) に対処する

AnOnlineShop_5.json をインポートしてアクセスパターン 4 (getProductInventoryByProductId) に対処します。warehouseItem エンティティは、各倉庫の商品数を追跡するために使用されます。この項目は通常、倉庫に商品が追加されたり、倉庫から商品が削除されたりすると更新されます。ERD にあるように、productwarehouse の間には多対多リレーションシップがあります。ここで、product から warehouse への 1 対多リレーションシップは warehouseItem のようにモデル化されます。その後、warehouse から product への 1 対多リレーションシップもモデル化されます。

アクセスパターン 4 は、PK=ProductId および SK begins_with “w#“ に対するクエリで対処できます。

ソートキーに適用できる begins_with() およびその他の式の詳細については、「キー条件式」を参照してください。

ベーステーブル:

特定の倉庫の製品在庫を追跡するために ProductID と warehouseId をクエリするテーブル設計。

ステップ 5: アクセスパターン 5 (getOrderDetailsByOrderId) と 6 (getProductByOrderId) に対処する

AnOnlineShop_6.json をインポートして、さらに customerproduct、および warehouse の項目をテーブルに追加します。次に、AnOnlineShop_7.json をインポートして、アクセスパターン 5 (getOrderDetailsByOrderId) および 6 (getProductByOrderId) に対処できる order 用項目コレクションを構築します。orderItem エンティティとしてモデル化された orderproduct の間の 1 対多リレーションシップを確認できます。

アクセスパターン 5 (getOrderDetailsByOrderId) に対処するには、PK=orderId を使用してテーブルをクエリします。これにより、customerId および注文された製品を含む注文に関するすべての情報が提供されます。

ベーステーブル:

orderId を使用してクエリを実行し、注文したすべての製品に関する情報を取得するテーブル設計。

アクセスパターン 6 (getProductByOrderId) に対処するには、order 内の製品のみを読み取る必要があります。これを達成するために、PK=orderId および SK begins_with “p#” を使用してテーブルをクエリします。

ベーステーブル:

orderId と productId を使用してクエリし、注文内の製品を取得するテーブル設計。

ステップ 6: アクセスパターン 7 (getInvoiceByOrderId) に対処する

AnOnlineShop_8.json をインポートして、アクセスパターン 7 (getInvoiceByOrderId) を処理する注文項目コレクションに invoice エンティティを追加します。このアクセスパターンに対処するために、PK=orderId および SK begins_with “i#” でクエリオペレーションを使用できます。

ベーステーブル:

orderId で請求書を取得するための請求書エンティティを注文項目コレクション内に含むテーブル設計。

ステップ 7: アクセスパターン 8 (getShipmentByOrderId) に対処する

AnOnlineShop_9.json をインポートして、アクセスパターン 8 (getShipmentByOrderId) を処理する注文項目コレクションに shipment エンティティを追加します。単一テーブルの設計にさらに多くの種類のエンティティを追加することで、同じ垂直分割モデルを拡張しています。注文項目コレクションに、order エンティティが shipmentorderItem、および invoice エンティティと持つさまざまな関係がどのように含まれているかに注意してください。

orderId による出荷を取得するには、PK=orderIdSK begins_with “sh#” でクエリオペレーションを実行します。

ベーステーブル:

注文 ID で出荷を取得するための出荷エンティティが注文項目コレクションに追加されているテーブル設計。

ステップ 8: アクセスパターン 9 (getOrderByProductIdForDateRange) に対処する

前のステップで、注文項目コレクションを作成しました。このアクセスパターンには新しいルックアップディメンション (ProductID および Date) があり、テーブル全体をスキャンし、関連するレコードをフィルタリングして、ターゲット項目を取得する必要があります。このアクセスパターンに対処するには、グローバルセカンダリインデックス (GSI) を作成する必要があります。AnOnlineShop_10.json をインポートし、複数の注文項目コレクションから orderItem データを取得できる GSI を使用して、新しい項目コレクションを作成します。データには GSI1-PKGSI1-SK が含まれ、それぞれ GSI1 のパーティションキーとソートキーになります。

DynamoDB は、GSI のキー属性を含む項目をテーブルから GSI に自動的に入力します。GSI に追加の挿入を手動で行う必要はありません。

アクセスパターン 9 に対処するには、GSI1-PK=productId および GSI1SK between (date1, date2) を使用して GSI1 でクエリを実行します。

ベーステーブル:

複数の注文項目コレクションから注文データを取得するための GSI を含むテーブル設計。

GSI1:

製品 ID と日付で注文を取得するための ProductID と Date をパーティションキーおよびソートキーとして含む GSI 設計。

ステップ 9: アクセスパターン 10 (getInvoiceByInvoiceId) と 11 (getPaymentByInvoiceId) に対処する

AnOnlineShop_11.json をインポートして、アクセスパターン 10 (getInvoiceByInvoiceId) と 11 (getPaymentByInvoiceId) に対処します。どちらも invoice に関連しています。これらは 2 つの異なるアクセスパターンですが、同じキー条件を使用して実現されます。Payments は、invoice エンティティのマップデータタイプを持つ属性として定義されます。

注記

GSI1-PKGSI1-SK は、さまざまなエンティティに関する情報を保存するためにオーバーロードされているため、同じ GSI から複数のアクセスパターンに対応できます。GSI オーバーロードの詳細については、「DynamoDB のグローバルセカンダリインデックスの多重定義」を参照してください。

アクセスパターン 10 と 11 に対処するには、GSI1-PK=invoiceId および GSI1-SK=invoiceId を使用して GSI1 に対してクエリを実行します。

GSI1:

請求書 ID で請求書と支払いを取得するための invoiceId をパーティションキーおよびソートキーの両方として含む GSI 設計。

ステップ 10: アクセスパターン 12 (getShipmentDetailsByShipmentId) と 13 (getShipmentByWarehouseId) に対処する

AnOnlineShop_12.json をインポートして、アクセスパターン 12 (getShipmentDetailsByShipmentId) と 13 (getShipmentByWarehouseId) に対処します。

1 回のクエリオペレーションで注文に関するすべての詳細を取得できるように、shipmentItem エンティティがベーステーブルの注文項目コレクションに追加されることに注意してください。

ベーステーブル:

すべての注文の詳細を取得するための shipmentItem エンティティを注文項目コレクション内に含むテーブル設計。

GSI1 パーティションとソートキーは、shipmentshipmentItem の間の 1 対多リレーションシップをモデル化するために既に使用されています。アクセスパターン 12 (getShipmentDetailsByShipmentId) に対処するには、GSI1-PK=shipmentId および GSI1-SK=shipmentId を使用して GSI1 に対してクエリを実行します。

GSI1:

出荷 ID で出荷の詳細を取得するための shipmentId をパーティションおよびソートキーとして含む GSI1 設計。

アクセスパターン 13 (getShipmentByWarehouseId) の warehouseshipment の間の新しい 1 対多リレーションシップをモデル化するには、別の GSI (GSI2) を作成する必要があります。アクセスパターンに対処するには、GSI2-PK=warehouseId および GSI2-SK begins_with “sh#” を使用して GSI2 に対してクエリを実行します。

GSI2:

倉庫別の出荷を取得するための warehouseId と shipmentId をパーティションキーおよびソートキーとして含む GSI2 設計。

ステップ 11: アクセスパターン 14 (getProductInventoryByWarehouseId)、15 (getInvoiceByCustomerIdForDateRange)、および 16 (getProductsByCustomerIdForDateRange) に対処する

AnOnlineShop_13.json をインポートして、次のアクセスパターンセットに関連するデータを追加します。アクセスパターン 14 (getProductInventoryByWarehouseId) に対処するには、GSI2-PK=warehouseId および GSI2-SK begins_with “p#” を使用して GSI2 に対してクエリを実行します。

GSI2:

アクセスパターン 14 に対処するための warehouseId と productId をパーティションキーおよびソートキーとして含む GSI2 設計。

アクセスパターン 15 (getInvoiceByCustomerIdForDateRange) に対処するには、GSI2-PK=customerId および GSI2-SK between (i#date1, i#date2) を使用して GSI2 に対してクエリを実行します。

GSI2:

アクセスパターン 15 に対処するための customerId と請求書の日付範囲をパーティションキーおよびソートキーとして含む GSI2 設計。

アクセスパターン 16 (getProductsByCustomerIdForDateRange) に対処するには、GSI2-PK=customerId および GSI2-SK between (p#date1, p#date2) を使用して GSI2 に対してクエリを実行します。

GSI2:

アクセスパターン 16 に対処するための customerId と製品の日付範囲をパーティションキーおよびソートキーとして含む GSI2 設計
注記

NoSQL Workbench では、ファセットは DynamoDB に対するアプリケーションのさまざまなデータアクセスパターンを表します。ファセットを使用すると、ファセットの制約を満たさないレコードを表示することなく、テーブル内のデータのサブセットを表示できます。プロビジョンドキャパシティの引き上げがファセットはビジュアルデータモデリングツールと見なされ、アクセスパターンのモデリングを純粋に補助するものであるため、DynamoDB で使用できるコンストラクトとしては存在しません。

AnOnlineShop_facets.json をインポートして、このユースケースのファセットを確認します。

すべてのアクセスパターンと各アクセスパターンにスキーマ設計で対処する方法を次の表にまとめています。

アクセスパターン ベーステーブル/GSI/LSI 操作 パーティションキー値 ソートキー値
getCustomerByCustomerId ベーステーブル GetItem PK=customerId SK=customerId
getProductByProductId ベーステーブル GetItem PK=productId SK=productId
getWarehouseByWarehouseId ベーステーブル GetItem PK=warehouseId SK=warehouseId
getProductInventoryByProductId ベーステーブル Query PK=productId SK begins_with "w#"
getOrderDetailsByOrderId ベーステーブル Query PK=orderId
getProductByOrderId ベーステーブル Query PK=orderId SK begins_with "p#"
getInvoiceByOrderId ベーステーブル Query PK=orderId SK begins_with "i#"
getShipmentByOrderId ベーステーブル Query PK=orderId SK begins_with "sh#"
getOrderByProductIdForDateRange GSI1 Query PK=productId SK between date1 and date2
getInvoiceByInvoiceId GSI1 Query PK=invoiceId SK=invoiceId
getPaymentByInvoiceId GSI1 Query PK=invoiceId SK=invoiceId
getShipmentDetailsByShipmentId GSI1 Query PK=shipmentId SK=shipmentId
getShipmentByWarehouseId GSI2 Query PK=warehouseId SK begins_with "sh#"
getProductInventoryByWarehouseId GSI2 Query PK=warehouseId SK begins_with "p#"
getInvoiceByCustomerIdForDateRange GSI2 Query PK=customerId SK between i#date1 and i#date2
getProductsByCustomerIdForDateRange GSI2 Query PK=customerId SK between p#date1 and p#date2

オンラインショップの最終スキーマ

最終的なスキーマ設計は次のとおりです。このスキーマ設計を JSON ファイルとしてダウンロードするには、GitHub の「DynamoDB 設計パターン」を参照してください。

ベーステーブル

EntityName や Name などの属性を持つオンラインショップのベーステーブルの最終スキーマ。

GSI1

EntityType などの属性を持つオンラインショップのベーステーブルの最終 GSI1 スキーマ。

GSI2

EntityType などの属性を持つオンラインショップのベーステーブルの最終 GSI2 スキーマ。

このスキーマ設計での NoSQL Workbench の使用

この最終スキーマを、DynamoDB のデータモデリング、データ視覚化、クエリ開発機能を提供するビジュアルツールである NoSQL Workbench にインポートして、新しいプロジェクトを詳しく調べたり編集したりできます。使用を開始するには、次の手順に従います。

  1. NoSQL Workbench をダウンロードします。詳細については、「DynamoDB 用の NoSQL Workbench のダウンロード」を参照してください。

  2. 上記の JSON スキーマファイルをダウンロードします。このファイルは既に NoSQL Workbench モデル形式になっています。

  3. JSON スキーマファイルを NoSQL Workbench にインポートします。詳細については、「既存のデータモデルのインポート」を参照してください。

  4. NOSQL Workbench にインポートしたら、データモデルを編集できます。詳細については、「既存のデータモデルの編集」を参照してください。

  5. データモデルの視覚化、サンプルデータの追加、CSV ファイルからのサンプルデータのインポートを行うには、NoSQL Workbench のデータビジュアライザー機能を使用します。