

# DynamoDB でのソーシャルネットワークのスキーマ設計
<a name="data-modeling-schema-social-network"></a>

## ソーシャルネットワークのビジネスユースケース
<a name="data-modeling-schema-social-network-use-case"></a>

このユースケースでは、DynamoDB をソーシャルネットワークとして使用する方法について説明します。ソーシャルネットワークは、さまざまなユーザーが相互に交流できるオンラインサービスです。これから設計するソーシャルネットワークでは、ユーザーの投稿、フォロワー、フォローしている相手、およびフォローしている相手による投稿で構成されるタイムラインをユーザーが表示できるようにします。このスキーマ設計のアクセスパターンは以下のとおりです。
+ 特定のユーザー ID のユーザー情報を取得する。
+ 特定のユーザー ID のフォロワーリストを取得する。
+ 特定のユーザー ID のフォローリストを取得する。
+ 特定のユーザー ID の投稿リストを取得する。
+ 特定の投稿 ID による投稿に「いいね\!」したユーザーのリストを取得する。
+ 特定の投稿 ID の「いいね\!」数を取得する。
+ 特定のユーザー ID のタイムラインを取得する。

## ソーシャルネットワークエンティティ関係図
<a name="data-modeling-schema-social-network-erd"></a>

これは、ソーシャルネットワークのスキーマ設計に使用するエンティティ関係図 (ERD) です。

![ユーザー、投稿、フォロワーなどのエンティティを示すソーシャルネットワークアプリケーションの ERD。](http://docs.aws.amazon.com/ja_jp/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`) に対処する**

特定のユーザーに関する情報を取得するには、キー条件を `PK=<userID>` にしてベーステーブルに [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html) を実行する必要があります。クエリ操作では、結果をページ分割できます。これは、ユーザーに多数のフォロワーがいる場合に便利です。Query の詳細については、「[DynamoDB のテーブルに対するクエリの実行](Query.md)」を参照してください。

この例では、ユーザーの「count」と「info」の 2 種類のデータを追跡します。ユーザーの「count」は、ユーザーのフォロワー数、フォローしている相手の数、相手が作成した投稿の数を反映します。ユーザーの「info」は、名前などの個人情報を反映します。

これら 2 種類のデータは、以下の 2 つの項目で表されます。ソートキー (SK) に「count」が含まれている項目は、「info」が含まれている項目よりも変更される可能性が高くなります。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 であるユーザーの Query オペレーションの結果、カウントおよび情報データ。](http://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/images/DataModeling/SocialNetwork1.png)


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

特定のユーザーのフォロワーリストを取得するには、キー条件を `PK=<userID>#follower` にしてベーステーブルに `Query` を実行する必要があります。

![ID が u#12345 であるユーザーのフォロワーを一覧表示するテーブルへの Query オペレーションの結果。](http://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/images/DataModeling/SocialNetwork2.png)


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

特定のユーザーがフォローしている相手のリストを取得するには、キー条件を `PK=<userID>#following` にしてベーステーブルに `Query` を実行する必要があります。次に、[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 のフォロワー数を 1 つ増やします。
+ ユーザー B をユーザー A のフォロワーリストに追加し、ユーザー A のフォロワー数を 1 つ増やします

![ID が u#12345 であるユーザーがフォローしているすべてのユーザーを一覧表示するテーブルへの Query オペレーションの結果。](http://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/images/DataModeling/SocialNetwork3.png)


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

特定のユーザーが作成した投稿のリストを取得するには、キー条件を `PK=<userID>#post` にしてベーステーブルに `Query` を実行する必要があります。ここで注意すべき重要な点の 1 つは、ユーザーの postID はインクリメンタルでなければならないということです。つまり、2 番目の PostID 値は 1 番目の PostID 値よりも大きくなければなりません (ユーザーは自分の投稿を並べ替えて表示したいはずです)。これを行うには、Universally Unique Lexicographically Sortable Identifier (ULID) などの時間値に基づいて postID を生成できます。

![特定のユーザーが作成した投稿のリストを取得するためのキー条件を使用した Query オペレーションの結果。](http://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/images/DataModeling/SocialNetwork4.png)


**ステップ 5: アクセスパターン 5 (`getUserLikesByPostID`) に対処する**

特定のユーザーの投稿に「いいね\!」を付けた人のリストを取得するには、キー条件を `PK=<postID>#likelist` にしてベーステーブルに `Query` を実行する必要があります。このアプローチは、アクセスパターン 2 (`getFollowerListByUserID`) とアクセスパターン 3 (`getFollowingListByUserID`) でフォロワーリストとフォローしている相手のリストを取得するときに使用したのと同じパターンです。

![特定のユーザーの投稿に「いいね!」をしたユーザーのリストを取得するためのキー条件を使用した Query オペレーションの結果。](http://docs.aws.amazon.com/ja_jp/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) 操作を実行する必要があります。このアクセスパターンでは、パーティションのスループットが 1 秒あたり 1000 WCU を超えるとスロットリングが発生するため、フォロワーの多いユーザー (有名人など) が投稿を作成するたびにスロットリングの問題が発生する可能性があります。この問題は DynamoDB が原因ではなく、DynamoDB  がソフトウェアスタックの最後にあるため、DynamoDB に現れるだけです。

すべてのユーザーに「いいね\!」の数を同時に表示することが本当に必要か、それとも時間の経過と共に徐々に表示できるかを評価する必要があります。一般的に、投稿の「いいね\!」の数はすぐに 100% 正確である必要はありません。この戦略を実装するには、アプリケーションと DynamoDB の間にキューを置き、更新が定期的に行われるようにします。

![特定の投稿の「いいね!」の数を取得するためのキー条件を使用した GetItem オペレーションの結果。](http://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/images/DataModeling/SocialNetwork6.png)


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

特定のユーザーのタイムラインを取得するには、キー条件を `PK=<userID>#timeline` にしてベーステーブルに `Query` 操作を実行する必要があります。ユーザーのフォロワーが自分の投稿を同期的に表示する必要があるシナリオを考えてみましょう。ユーザーが投稿を書くたびに、フォロワーリストが読み取られ、useIDと 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 コールでタイムラインを読み取ることはできませんが、投稿が頻繁に編集される可能性がある場合、これはより費用対効果の高いソリューションです。

タイムラインは最近の投稿を表示する場所なので、古い投稿をクリーンアップする方法が必要です。WCU を使用して削除する代わりに、DynamoDB の [TTL](TTL.md) 機能を使用して無料で削除できます。

![特定のユーザーの最近の投稿を示すタイムラインを取得するためのキー条件を使用した Query オペレーションの結果。](http://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/images/DataModeling/SocialNetwork7.png)


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


| アクセスパターン | ベーステーブル/GSI/LSI | Operation | パーティションキー値 | ソートキー値 | その他の条件/フィルター | 
| --- | --- | --- | --- | --- | --- | 
| getUserInfoByUserID | ベーステーブル | クエリ | PK=<userID> |  |  | 
| getFollowerListByUserID | ベーステーブル | クエリ | PK=<userID>\#follower |  |  | 
| getFollowingListByUserID | ベーステーブル | クエリ | PK=<userID>\#following |  |  | 
| getPostListByUserID | ベーステーブル | クエリ | PK=<userID>\#post |  |  | 
| getUserLikesByPostID | ベーステーブル | クエリ | PK=<postID>\#likelist |  |  | 
| getLikeCountByPostID | ベーステーブル | GetItem | PK=<postID>\#likecount |  |  | 
| getTimelineByUserID | ベーステーブル | クエリ | 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)を参照してください。

**ベーステーブル:**

![前述の Query および GetItem オペレーションの結果を含むテーブルの最終スキーマ設計。](http://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/images/DataModeling/SocialNetwork8.png)


## このスキーマ設計での NoSQL Workbench の使用
<a name="data-modeling-schema-social-network-nosql"></a>

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

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)」を参照してください。