

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# DynamoDB 中的社交網路結構描述設計
<a name="data-modeling-schema-social-network"></a>

## 社交網路商業使用案例
<a name="data-modeling-schema-social-network-use-case"></a>

此使用案例討論如何使用 DynamoDB 做為社交網路。社交網絡是一種線上服務，可以讓不同的使用者與彼此互動。我們將設計的社交網路會讓使用者看到一個時間軸，其中包括他們的文章、他們的跟隨者、他們跟隨的人，以及他們跟隨的人撰寫的文章。此結構描述設計的存取模式為：
+ 取得指定 userID 的使用者資訊 
+ 取得指定 userID 的跟隨者清單
+ 取得指定 userID 的跟隨清單
+ 取得指定 userID 的文章清單
+ 取得指定 postID 中喜歡該篇文章的使用者清單
+ 取得指定 postID 的喜歡計數
+ 取得指定 userID 的時間軸

## 社交網路實體關係圖
<a name="data-modeling-schema-social-network-erd"></a>

這是我們將用於社交網路結構描述設計的實體關係圖 (ERD)。

![顯示使用者、文章和跟隨者等實體的社交網路應用程式 ERD。](http://docs.aws.amazon.com/zh_tw/amazondynamodb/latest/developerguide/images/DataModeling/SocialNetworkERD.png)


## 社交網路存取模式
<a name="data-modeling-schema-social-network-access-patterns"></a>

這些是我們針對社交網路結構描述設計考量的存取模式。
+ `getUserInfoByUserID`
+ `getFollowerListByUserID`
+ `getFollowingListByUserID`
+ `getPostListByUserID`
+ `getUserLikesByPostID`
+ `getLikeCountByPostID`
+ `getTimelineByUserID`

## 社交網路結構描述設計演變
<a name="data-modeling-schema-social-network-design-evolution"></a>

DynamoDB 是一種 NoSQL 資料庫，因此它不允許您執行聯結，這是一種結合多個資料庫資料的操作。不熟悉 DynamoDB 的客戶可能會在不需要時，將關聯式資料庫管理系統 (RDBMS) 設計理念 (例如為每個實體建立資料表) 套用至 DynamoDB。DynamoDB 的單一資料表設計之目的，是根據應用程式的存取模式，以預先聯結的形式寫入資料，然後立即使用資料，無需額外運算。如需詳細資訊，請參閱 [DynamoDB 中的單一資料表與多資料表設計](https://aws.amazon.com/blogs/database/single-table-vs-multi-table-design-in-amazon-dynamodb/)。

現在，讓我們逐步介紹如何發展結構描述設計以解決所有存取模式。

**步驟 1：位址存取模式 1 (`getUserInfoByUserID`)**

為了取得特定使用者的資訊，我們需要 [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html) 基礎資料表，索引鍵條件為 `PK=<userID>`。查詢操作可讓您將結果分頁，這在使用者有許多跟隨者的情況下很實用。如需查詢的詳細資訊，請參閱 [在 DynamoDB 中查詢資料表](Query.md)。

在我們的範例中，我們追蹤使用者的兩種類型資料：他們的「計數」和他們的「資訊」。使用者的「計數」反映他們有多少追隨者，他們追隨的使用者數量以及他們建立了多少文章。使用者的「資訊」反映了他們的個人資訊，例如他們的姓名。

我們看到這兩種資料由以下的兩個項目來表示。排序索引鍵 (SK) 中有「計數」的項目比含有「資訊」的項目更有可能變更。DynamoDB 會將項目的大小視為更新前後所顯示的大小，消耗的佈建輸送量將反映這些項目大小中較大的部分。因此即使您只更新一小部分項目的屬性，[https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateItem.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateItem.html) 還是會使用完整數量的佈建輸送量 (之前和之後項目大小中較大的一個)。您可以透過單一 `Query` 操作取得項目，並使用 `UpdateItem` 從現有的數字屬性中新增或減去。

![ID u#12345 使用者的查詢操作結果及其計數和資訊資料。](http://docs.aws.amazon.com/zh_tw/amazondynamodb/latest/developerguide/images/DataModeling/SocialNetwork1.png)


**步驟 2：位址存取模式 2 (`getFollowerListByUserID`)**

若要取得跟隨指定使用者的使用者清單，我們需要 `Query` 基礎資料表，索引鍵條件為 `PK=<userID>#follower`。

![資料表的查詢操作結果，列出 ID u#12345 使用者的跟隨者。](http://docs.aws.amazon.com/zh_tw/amazondynamodb/latest/developerguide/images/DataModeling/SocialNetwork2.png)


**步驟 3：位址存取模式 3 (`getFollowingListByUserID`)**

若要取得指定使用者跟隨的使用者清單，我們需要 `Query` 基礎資料表，索引鍵條件為 `PK=<userID>#following`。然後您可以使用 [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactWriteItems.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactWriteItems.html) 操作將多項請求結合為一組，並執行以下操作：
+ 將使用者 A 新增到使用者 B 的跟隨者清單中，然後將使用者 B 的跟隨者計數增加一。
+ 將使用者 B 新增到使用者 A 的跟隨者清單中，然後將使用者 A 的跟隨者計數增加一。

![資料表的查詢操作結果，列出 ID u#12345 使用者跟隨的所有使用者。](http://docs.aws.amazon.com/zh_tw/amazondynamodb/latest/developerguide/images/DataModeling/SocialNetwork3.png)


**步驟 4：位址存取模式 4 (`getPostListByUserID`)**

若要取得指定使用者建立的文章清單，我們需要 `Query` 基礎資料表，索引鍵條件為 `PK=<userID>#post`。這裡需要注意的一件重要事情是，使用者的 postID 必須是增量的：第二個 postID 值必須大於第一個 postID 值 (因為使用者希望以排序方式查看自己的貼文)。您可以透過根據時間值 (例如通用唯一字典順序排序識別符 (ULID)) 產生 postID 來實現此目的。

![使用索引鍵條件的查詢操作結果，以取得特定使用者建立的文章清單。](http://docs.aws.amazon.com/zh_tw/amazondynamodb/latest/developerguide/images/DataModeling/SocialNetwork4.png)


**步驟 5：位址存取模式 5 (`getUserLikesByPostID`)**

若要取得對指定使用者貼文按下喜歡的使用者清單，我們需要 `Query` 基礎資料表，索引鍵條件為 `PK=<postID>#likelist`。這種方法是我們用於擷取跟隨者和跟隨清單中存取模式 2 (`getFollowerListByUserID`) 和存取模式 3 (`getFollowingListByUserID`) 相同的模式。

![使用索引鍵條件的查詢操作結果，以取得喜歡特定使用者文章的使用者清單。](http://docs.aws.amazon.com/zh_tw/amazondynamodb/latest/developerguide/images/DataModeling/SocialNetwork5.png)


**步驟 6：位址存取模式 6 (`getLikeCountByPostID`)**

要取得指定文章的喜歡計數，我們需要透過 `PK=<postID>#likecount` 的索引鍵條件在基礎資料表上執行 [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_GetItem.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_GetItem.html) 操作。每當有許多跟隨者 (例如名人) 的使用者建立文章時，此存取模式就會造成限流問題，因為當分割區的輸送量超過每秒 1000 WCU 時，就會發生限流問題。這個問題不是 DynamoDB 的結果，它只是出現在 DynamoDB 中，因為它位於軟體堆疊的末端。

您應該評估它是否對所有使用者同時查看類似計數真的很重要，或者是否可以隨著時間的推移逐漸發生。一般來說，文章的類似計數不需要立即 100% 準確。您可以在應用程式和 DynamoDB 之間放置佇列，以便定期進行更新以實作此策略。

![使用索引鍵條件的 GetItem 操作結果，以取得特定文章的喜歡計數。](http://docs.aws.amazon.com/zh_tw/amazondynamodb/latest/developerguide/images/DataModeling/SocialNetwork6.png)


**步驟 7：位址存取模式 7 (`getTimelineByUserID`)**

如要取得指定使用者的時間軸，我們需要透過 `PK=<userID>#timeline` 的索引鍵條件在基礎資料表上執行 `Query` 操作。讓我們考慮一個場景，即使用者的追隨者需要同步查看他們的文章。每次使用者寫一篇文章時，他們的跟隨者清單都會被讀取，並且他們的 userID 和 postID 會慢慢輸入到其所有跟隨者的時間軸索引鍵中。然後，當您的應用程式啟動時，您可以使用 `Query` 操作讀取時間軸索引鍵，並使用任何新項目的 [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_BatchGetItem.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_BatchGetItem.html) 操作來使用 userID 和 postID 的組合填充時間軸畫面。您無法使用 API 呼叫讀取時間軸，但是如果文章可以經常編輯，則這是一個更具成本效益的解決方案。

時間軸是一個顯示最近文章的地方，因此我們需要一種清理舊文章的方法。您可以使用 DynamoDB 的 [TTL](TTL.md) 功能免費執行此操作，而不是使用 WCU 刪除它們。

![使用索引鍵條件的查詢操作結果，以取得特定使用者顯示最近文章的時間軸。](http://docs.aws.amazon.com/zh_tw/amazondynamodb/latest/developerguide/images/DataModeling/SocialNetwork7.png)


下表摘要整理了所有存取模式，以及結構描述設計處理這些模式的方式：


| 存取模式 | 基礎資料表/GSI/LSI | 作業 | 分割區索引鍵值 | 排序索引鍵值 | 其他條件/篩選條件 | 
| --- | --- | --- | --- | --- | --- | 
| getUserInfoByUserID | 基礎資料表 | Query | PK=<userID> |  |  | 
| getFollowerListByUserID | 基礎資料表 | Query | PK=<userID>\#follower |  |  | 
| getFollowingListByUserID | 基礎資料表 | Query | PK=<userID>\#following |  |  | 
| getPostListByUserID | 基礎資料表 | Query | PK=<userID>\#post |  |  | 
| getUserLikesByPostID | 基礎資料表 | Query | PK=<postID>\#likelist |  |  | 
| getLikeCountByPostID | 基礎資料表 | GetItem | PK=<postID>\#likecount |  |  | 
| getTimelineByUserID | 基礎資料表 | Query | PK=<userID>\#timeline |  |  | 

## 社交網路最終結構描述
<a name="data-modeling-schema-social-network-final-schema"></a>

這是最終的結構描述設計。若要將此結構描述設計下載為 JSON 檔案，請參閱 GitHub 上的 [DynamoDB 範例](https://github.com/aws-samples/aws-dynamodb-examples/blob/master/schema_design/SchemaExamples/SocialNetwork/SocialNetworkSchema.json)。

**基礎資料表：**

![資料表的最終結構描述設計，其中包含上述查詢和 GetItem 操作的結果。](http://docs.aws.amazon.com/zh_tw/amazondynamodb/latest/developerguide/images/DataModeling/SocialNetwork8.png)


## 使用 NoSQL Workbench 與此結構描述設計
<a name="data-modeling-schema-social-network-nosql"></a>

您可以將此最終結構描述匯入 [NoSQL Workbench](workbench.md)，這是為 DynamoDB 提供資料建模、資料視覺化，和查詢開發功能的視覺化工具，以進一步探索和編輯新專案。請依照下列步驟以開始使用：

1. 下載 NoSQL Workbench。如需詳細資訊，請參閱[下載 DynamoDB 專用 NoSQL Workbench](workbench.settingup.md)。

1. 下載上面列出的 JSON 結構描述檔案，該檔案已經是 NoSQL Workbench 模型格式。

1. 將 JSON 結構描述檔案匯入到 NoSQL Workbench。如需詳細資訊，請參閱[匯入現有的資料模型](workbench.Modeler.ImportExisting.md)。

1. 一旦您匯入到 NOSQL Workbench 後，便可以編輯資料模型。如需詳細資訊，請參閱[編輯現有的資料模型](workbench.Modeler.Edit.md)。