背景
我正在构建一个论坛,并研究使用DynamoDB和邻接列表对数据进行建模。一些顶级实体(比如用户)可能会与其他顶级实体(比如评论)拥有多种关系。
需求
例如,假设我们想要能够执行以下操作:
- 用户可以点赞评论
- 用户可以关注评论
- 评论可以显示喜欢它的用户
- 评论可以显示关注它的用户
- 用户资料页面可以显示他们所喜欢的评论
- 用户资料页面可以显示他们所关注的评论
因此,我们基本上有一个多对多(用户 <=> 评论)对多个(喜欢或关注)的情况。
注意:这个示例是故意简化的,在实际情况中将有更多的关系需要建模,因此我正试图思考一些可扩展性的东西。
基线
以下顶级数据在任何邻接列表表示中都很常见:
First_id(Partition key) Second_id(Sort Key) Data
------------- ---------- ------
User-Harry User-Harry User data
User-Ron User-Ron User data
User-Hermione User-Hermione User data
Comment-A Comment-A Comment data
Comment-B Comment-B Comment data
Comment-C Comment-C Comment data
此外,对于下面每个表格,都会有一个等价的全局二级索引,其中分区键和排序键被交换。
示例数据
这是我想在 DynamoDB 中建模的内容:
- Harry 喜欢评论 A
- Harry 喜欢评论 B
- Harry 关注评论 A
- Ron 喜欢评论 B
- Hermione 喜欢评论 C
选项1
使用第三个属性来定义关系类型:
First_id(Partition key) Second_id(Sort Key) Data
------------- ---------- ------
Comment-A User-Harry "LIKES"
Comment-B User-Harry "LIKES"
Comment-A User-Harry "FOLLOWS"
Comment-B User-Ron "LIKES"
Comment-C User-Hermione "FOLLOWS"
这种方法的缺点是查询结果中存在冗余信息,因为它们会返回一些多余的条目,而这些条目可能并不是你关心的。例如,如果你想查询所有喜欢给定评论的用户,你也必须处理所有关注该评论的用户。同样,如果你想查询一个用户喜欢的所有评论,你需要处理该用户关注的所有评论。
选项二
修改键以表示关系:
First_id(Partition key) Second_id(Sort Key)
------------- ----------
LikeComment-A LikeUser-Harry
LikeComment-B LikeUser-Harry
FollowComment-A FollowUser-Harry
LikeComment-B LikeUser-Ron
FollowComment-C FollowUser-Hermione
这使得查询变得更加高效:
- 评论点赞
- 评论关注
- 用户点赞
- 用户关注
缺点是同一个顶级实体现在有多个键,随着添加更多关系可能会变得更加复杂。
选项3
完全跳过邻接列表,并使用单独的表,也许一张表用于用户,另一张表用于点赞,还有一张表用于关注。
选项4
传统的关系型数据库。虽然我不打算走这条路,因为这是一个个人项目,我想探索DynamoDB,但如果这是正确的思考方式,我很想知道原因。
结论
感谢阅读到这里!如果有任何可以简化问题或澄清任何事情的方法,请告诉我:)
我查看了AWS最佳实践和这篇many-to-many SO post,似乎都没有涉及到多对多(具有多个)关系,因此非常感谢任何资源或指导。