Amazon dynamodb DynamoDB邻接列表是否应该使用离散分区键来建模每种类型的关系? 上下文

Amazon dynamodb DynamoDB邻接列表是否应该使用离散分区键来建模每种类型的关系? 上下文,amazon-dynamodb,forum,adjacency-list,Amazon Dynamodb,Forum,Adjacency List,我正在建立一个论坛,并研究使用DynamoDB和邻接列表对数据进行建模。一些顶级实体(如用户)可能与其他顶级实体(如注释)具有多种类型的关系 要求 例如,假设我们希望能够做到以下几点: 用户可以喜欢评论 用户可以关注评论 评论可以显示喜欢它的用户 注释可以显示跟随它的用户 用户配置文件可以显示他们喜欢的注释 用户配置文件可以显示他们遵循的注释 因此,我们基本上有一个多对多(用户评论)对多(喜欢或跟随) 注意:这个例子是故意精简的,在实践中会有更多的关系需要建模,所以我试图在这里考虑一些可扩展

我正在建立一个论坛,并研究使用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中建立的模型:

  • 哈里喜欢评论
  • 哈里喜欢评论B
  • 哈里遵循一条评论
  • 罗恩喜欢评论B
  • 赫敏喜欢评论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
    
    这种方法的缺点是查询结果中存在冗余信息,因为它们将返回您可能不关心的额外项目。例如,如果要查询所有喜欢某个给定注释的用户,还必须处理所有跟随该注释的用户。同样,如果要查询用户喜欢的所有注释,则需要处理用户遵循的所有注释

    选择2 修改键以表示关系:

    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,但如果这是思考问题的正确方式,我很想知道为什么

    结论 谢谢你读到这里!如果我能做些什么来简化问题或澄清问题,请让我知道:)


    我已经查看了和这两个选项,它们似乎都没有解决多对多(多)关系,因此非常感谢任何资源或指导。

    您的选项1不可能,因为它没有唯一的主键。在示例数据中,您可以看到
    (Comment-A,User Harry)
    有两个条目

    解决方案1

    实现所需功能的方法是为表和GSI使用稍微不同的属性。如果Harry喜欢评论A,那么您的属性应该是:

    hash_key: User-Harry
    gsi_hash_key: Comment-A
    sort_key_for_both: Likes-User-Harry-Comment-A
    
    现在,表和GSI中的顶级实体只有一个分区键值,您可以使用
    begins\u with
    操作符查询特定的关系类型

    解决方案2

    您可以使关系成为顶级实体。例如,
    Likes-User-Harry-Comment-A
    在数据库中会有两个条目,因为它与
    用户Harry
    注释A都“相邻”

    如果您希望对未来关系的更复杂信息建模(包括描述关系之间关系的能力,例如
    喜欢用户Ron User Harry
    原因
    追随用户Ron User Harry

    但是,这种策略需要在数据库中存储更多的项,这意味着保存“like”(以便查询)不是一个原子操作。(但您可以通过只编写关系实体来解决这个问题,然后使用dynamodbstream+Lambda为我在本解决方案开头提到的两个条目编写条目。)


    更新:使用DynamoDB事务,以这种方式保存“like”实际上是一个完全酸性的操作。

    这太棒了!非常感谢您的详细回复。我真的很喜欢你的
    想法所带来的可能性!