本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
使用 DynamoDB 做為線上商店的資料存放區
此使用案例說明如何將 DynamoDB 做為線上商店 (或電子商店) 的資料存放區。
使用案例
使用者可在線上商店瀏覽各種產品,並進行購買。結帳時客戶可以使用折扣碼或禮品卡付款,並用信用卡支付剩餘金額。從數個倉庫中找出購買產品後,便會運送到客戶提供的地址。線上商店存放區的典型存取模式包括:
-
取得具指定 CustomerID 的客戶
-
取得具指定 ProductID 的產品
-
取得具指定 WarehouseID 的倉庫
-
透過 ProductID 取得所有倉庫的產品庫存
-
取得具指定 OrderID 的訂單
-
取得具指定 OrderID 的所有產品
-
取得具指定 OrderID 的發票
-
取得具指定 OrderID 的所有運送貨物
-
取得指定日期範圍內,具指定 ProductID 的所有訂單
-
取得具指定 InvoiceID 的發票
-
取得具指定 InvoiceID 的所有付款
-
取得具指定 ShipmentID 的所有運送詳細資訊
-
取得具指定 WarehouseID 的所有運送貨物
-
取得具指定 WarehouseID 的所有產品庫存
-
取得指定日期範圍內,具指定 CustomerID 的所有發票
-
取得指定日期範圍內,由指定 CustomerID 訂購的所有產品
實體關係圖
針對如何使用 DynamoDB 做為線上商店的資料存放區,這是用於建模的實體關係圖 (ERD)。
存取模式
針對如何使用 DynamoDB 做為線上商店的資料存放區,這些是可採用的存取模式。
-
getCustomerByCustomerId -
getProductByProductId -
getWarehouseByWarehouseId -
getProductInventoryByProductId -
getOrderDetailsByOrderId -
getProductByOrderId -
getInvoiceByOrderId -
getShipmentByOrderId -
getOrderByProductIdForDateRange -
getInvoiceByInvoiceId -
getPaymentByInvoiceId -
getShipmentDetailsByShipmentId -
getShipmentByWarehouseId -
getProductInventoryByWarehouseId -
getInvoiceByCustomerIdForDateRange -
getProductsByCustomerIdForDateRange
架構設計演進
使用 DynamoDB 專用 NoSQL Workbench,匯入 AnOnlineShop_1.jsonAnOnlineShop 的新資料模型,和一個命名為 OnlineShop 的新資料表。請注意,我們將分割區索引鍵和排序索引鍵命名為通用名稱 PK 和 SK,藉此可在同一個資料表中儲存不同類型的實體。
步驟 1:位址存取模式 1 (getCustomerByCustomerId)
匯入 AnOnlineShop_2.jsongetCustomerByCustomerId)。某些實體與其他實體並無關聯,因此我們將針對這些實體使用相同的 PK 和 SK 值。在範例資料中,請注意索引鍵字首為 c#,以和稍後會從其他實體新增的 customerId 進行區別。也請於其他實體重複執行此做法。
若要處理此存取模式,可以利用 PK=customerId 和 SK=customerId 執行 GetItem 操作。
步驟 2:位址存取模式 2 (getProductByProductId)
匯入 AnOnlineShop_3.jsonproduct 實體處理存取模式 2 (getProductByProductId)。產品實體字首為 p#,並且已使用相同的排序索引鍵屬性來儲存 customerID 與 productID。透過通用命名和垂直分割建立項目集合,可設計有效的單一資料表。
若要處理此存取模式,可以利用 PK=productId 和 SK=productId 執行 GetItem 操作。
步驟 3:位址存取模式 3 (getWarehouseByWarehouseId)
匯入 AnOnlineShop_4.jsongetWarehouseByWarehouseId 實體處理存取模式 3 (warehouse)。目前我們已將 customer、product 與 warehouse 實體加入同一個資料表,且這些實體均使用字首和 EntityType 屬性。類型屬性 (或字首命名) 能提升模型的可讀性。如果只單純將不同實體的英數 ID 儲存在同一屬性中,閱讀上會相當困難。若少了識別符,就會難以分辨不同實體。
若要處理此存取模式,可以利用 PK=warehouseId 和 SK=warehouseId 執行 GetItem 操作。
基礎資料表:
步驟 4:位址存取模式 4 (getProductInventoryByProductId)
匯入 AnOnlineShop_5.jsongetProductInventoryByProductId)。而 warehouseItem 實體會用於追蹤每個倉庫中的產品數量。當倉庫新增或移除產品時,通常會更新此項目。正如在 ERD 所看到的,product 和 warehouse 之間存在多對多關係。在此處,從 product 至 warehouse 的一對多關係已建立模型 warehouseItem。接著,從 product 至 warehouse 的一對多關係也會進行建模。
可透過查詢 PK=ProductId 和 SK begins_with “w#“ 處理存取模式 4。
關於 begins_with() 和其他可套用至排序索引鍵的表達式,詳細資訊請參閱索引鍵條件表達式。
基礎資料表:
步驟 5:位址存取模式 5 (getOrderDetailsByOrderId) 和 6 (getProductByOrderId)
透過匯入 AnOnlineShop_6.jsoncustomer、product 和 warehouse 項目新增至資料表。然後,匯入 AnOnlineShop_7.jsonorder 建立項目集合以處理存取模式 5 (getOrderDetailsByOrderId) 和 6 (getProductByOrderId)。您可以看到 order 和 product 之間的一對多關係已建模為 orderItem 實體。
若想處理存取模式 5 (getOrderDetailsByOrderId),請透過 PK=orderId 查詢資料表,了解與訂單相關的所有資訊,包括 customerId 和已訂購產品。
基礎資料表:
若想處理存取模式 6 (getProductByOrderId),僅能以 order 讀取產品,此方法可透過利用 PK=orderId 和 SK begins_with “p#” 查詢資料表完成。
基礎資料表:
步驟 6:位址存取模式 7 (getInvoiceByOrderId)
匯入 AnOnlineShop_8.jsoninvoice 實體到訂單項目集合,以處理存取模式 7 (getInvoiceByOrderId)。若要處理此存取模式,可以利用 PK=orderId 和 SK begins_with
“i#” 執行查詢操作。
基礎資料表:
步驟 7:位址存取模式 8 (getShipmentByOrderId)
匯入 AnOnlineShop_9.jsonshipment 實體到訂單項目集合,以處理存取模式 8 (getShipmentByOrderId)。我們可透過在單一資料表設計中新增更多實體類型,擴展同一個的垂直分割模型。請注意,訂單項目集合中項目間的關係,並不同於 order、shipment、orderItem 及 invoice 實體間所擁有的關係。
若想透過 orderId 取得運送貨物,您可以利用 PK=orderId 和 SK begins_with “sh#” 執行查詢操作。
基礎資料表:
步驟 8:位址存取模式 9 (getOrderByProductIdForDateRange)
在上個步驟中,我們建立了訂單項目集合。此存取模式具有新的查詢維度 (ProductID 和 Date),會要求您掃描整個資料表並篩選相關記錄,以擷取目標項目。為處理這類存取模式,必須建立全域次要索引 (GSI)。匯入 AnOnlineShop_10.jsonorderItem 資料。目前資料內有 GSI1-PK 和 GSI1-SK,分別為 GSI1 的分割區索引鍵和排序索引鍵。
DynamoDB 會自動將資料表中包含 GSI 索引鍵屬性的項目填入 GSI,不須額外手動插入 GSI。
若想處理存取模式 9,請利用 GSI1-PK=productId 和 GSI1SK between (date1,
date2) 查詢 GSI1。
基礎資料表:
GSI1:
步驟 9:位址存取模式 10 (getInvoiceByInvoiceId) 和 11 (getPaymentByInvoiceId)
匯入 AnOnlineShop_11.jsoninvoice 相關的存取模式 10 (getInvoiceByInvoiceId) 和 11 (getPaymentByInvoiceId)。即使這兩種存取模式並不相同,仍須透過索引鍵條件以實現。Payments 的定義為 invoice 實體上具地圖資料類型的屬性。
注意
為了儲存不同實體的資訊,GSI1-PK 和 GSI1-SK 會進行多載,以便從同一個 GSI 取得多個存取模式。如需 GSI 多載的詳細資訊,請參閱 在 DynamoDB 中多載全域次要索引。
若想處理存取模式 10 和 11,請利用 GSI1-PK=invoiceId 和 GSI1-SK=invoiceId 查詢 GSI1。
GSI1:
步驟 10:位址存取模式 12 (getShipmentDetailsByShipmentId) 和 13 (getShipmentByWarehouseId)
匯入 AnOnlineShop_12.jsongetShipmentDetailsByShipmentId) 和 13 (getShipmentByWarehouseId)。
請注意,shipmentItem 實體已新增至基礎資料表上的訂單項目集合,以在單一查詢作業中擷取訂單的所有詳細資訊。
基礎資料表:
GSI1 分割區和排序索引鍵已用於建立 shipment 和 shipmentItem 之間的一對多關係模型。若想處理存取模式 12 (getShipmentDetailsByShipmentId),請利用 GSI1-PK=shipmentId 和 GSI1-SK=shipmentId 查詢 GSI1。
GSI1:
針對存取模式 13 (getShipmentByWarehouseId),我們必須建立另一個 GSI (GSI2),來為 warehouse 和 shipment 之間新的一對多關係建立模型。若想處理此存取模式,請利用 GSI2-PK=warehouseId 和 GSI2-SK
begins_with “sh#” 查詢 GSI2。
GSI2:
步驟 11:位址存取模式 14 (getProductInventoryByWarehouseId)、15 (getInvoiceByCustomerIdForDateRange) 和 16 (getProductsByCustomerIdForDateRange)
匯入 AnOnlineShop_13.jsongetProductInventoryByWarehouseId),請利用 GSI2-PK=warehouseId 和 GSI2-SK
begins_with “p#” 查詢 GSI2。
GSI2:
若想處理存取模式 15 (getInvoiceByCustomerIdForDateRange),請利用 GSI2-PK=customerId 和 GSI2-SK between
(i#date1, i#date2) 查詢 GSI2。
GSI2:
若想處理存取模式 16 (getProductsByCustomerIdForDateRange),請利用 GSI2-PK=customerId 和 GSI2-SK between
(p#date1, p#date2) 查詢 GSI2。
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 設計模式
基礎資料表
GSI1
GSI2
使用 NoSQL Workbench 與此結構描述設計
您可以將此最終結構描述匯入 NoSQL Workbench,這是為 DynamoDB 提供資料建模、資料視覺化,和查詢開發功能的視覺化工具,以進一步探索和編輯新專案。請依照下列步驟以開始使用:
-
下載 NoSQL Workbench。如需更多詳細資訊,請參閱 下載 DynamoDB 專用 NoSQL Workbench。
-
下載上面列出的 JSON 結構描述檔案,該檔案已經是 NoSQL Workbench 模型格式。
-
將 JSON 結構描述檔案匯入到 NoSQL Workbench。如需更多詳細資訊,請參閱 匯入現有的資料模型。
-
一旦您匯入到 NOSQL Workbench 後,便可以編輯資料模型。如需更多詳細資訊,請參閱 編輯現有的資料模型。
-
若要視覺化您的資料模型、新增範例資料,或從 CSV 檔案匯入範例資料,請使用 NoSQL Workbench 的資料視覺化工具功能。