DynamoDB邻接列表主键

Mik*_*ike 4 adjacency-list nosql amazon-dynamodb

我正在使用DynamoDB完成一个练习来模拟多对多的关系.我需要允许帖子和标签之间的多对多关系.每个帖子可以有很多标签,每个标签可以有很多帖子.

我有一个主键id和主排序关键字type,然后另一个全球指数iddata,我增加了另一个全球指数idtype再次,但我认为这是多余的.

这是我到目前为止所拥有的.

id(Partition key)      type(Sort Key)       target       data
-------------          ----------           ------       ------
1                      post                 1            cool post
tag                    tag                  tag          n/a
1                      tag                  tag          orange

---------------------------------------------
---- inserting another tag will overwrite ---
---------------------------------------------

1                      tag                  tag          green
Run Code Online (Sandbox Code Playgroud)

我正在从这个精彩的演讲https://www.youtube.com/watch?v=jzeKPKpucS0和这些不那么棒的文档中获取建议https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-adjacency -graphs.html

我遇到的问题是,如果我尝试添加另一个带有id"1"和type"tag"的标记,它将覆盖现有标记,因为它将具有相同的复合键.我在这里错过了什么?看起来建议是将主键和排序键设为idtype.我的类型应该更像"tag#orange"吗?在这种情况下,我可以target在类型上使用排序键放置全局索引.通过查询target ="tag",我可以通过"tag"获取带有特定标签的所有帖子.

只是寻找一些关于使用Dynamo处理这种邻接列表数据的建议,因为它看起来非常有趣.谢谢!

Ren*_*rro 18

邻接列表的基本准则

您需要对建模方式进行一些修改.在邻接列表中,您有两种类型的项目:

  1. 顶级(这些是您的帖子标签)
  2. 关联(表示哪些标签与每个帖子相关联,反之亦然)

要构建此邻接列表,您必须遵循两个简单的准则(我认为在您的示例中缺少这些准则):

  • 必须使用主键表示每个顶级项(在您的情况下为PostTag).此外,这些项在sort-key和primary-key中应具有相同的值
  • 对于关联,使用主键表示(或)和sort-key来表示目标(或).

从我在示例中看到的,您将帖子标签的主键设置为项目ID,同时您还应该使用其类型 ; 例如Post-1Tag-3.在表示关联的项目中,我也没有看到您存储目标ID.

假设你有:

  • 三个帖子:"hello world","foo bar""Whatever ......"
  • 还有三个标签:"酷","棒极了"," 极了"
  • 帖子"你好世界"有一个标签:"酷"
  • 帖子"foo bar"有两个标签:"酷"" "
  • 发布"Whatever ..."没有任何标签

你需要在Dynamo中以这种方式建模:

PRIMARY-KEY   | SORT-KEY    | SOURCE DATA  | TARGET DATA
--------------|-------------|--------------|-------------
Post-1        | Post-1      | hello world  |
Post-2        | Post-2      | foo bar      |
Post-3        | Post-3      | Whatever...  |
Tag-1         | Tag-1       | cool         |
Tag-2         | Tag-2       | awesome      |
Tag-3         | Tag-3       | great        |
Post-1        | Tag-1       | hello world  | cool
Post-2        | Tag-1       | foo bar      | cool
Post-2        | Tag-3       | foo bar      | great
Tag-1         | Post-1      | cool         | hello world
Tag-1         | Post-2      | cool         | foo bar
Tag-3         | Post-2      | great        | foo bar
Run Code Online (Sandbox Code Playgroud)

如何查询此邻接列表

1)你需要一个特定的项目,比如Post-1:

查询primary-key == "Post-1" & sort-key == "Post-1"- 返回:仅Post-1

2)您需要与Post-2相关的所有标签:

查询依次primary-key == "Post-2" & sort-key BEGINS_WITH "Tag-"- 返回:Tag-1Tag-3关联.

查看有关begin_with键条件表达式的文档.

3)你需要所有与之相关的帖子,比如Tag-1:

查询依据primary_key == "Tag-1" & sort-key BEGINS_WITH "Post-"- 返回:Post-1Post-2关联.

请注意,如果更改给定帖子的内容,则还需要更改所有关联项目中的值.

您也可以不将帖子和标签内容存储在关联项中,这样可以节省存储空间.但是,在这种情况下,您需要在上面的示例查询2和3中使用两个查询:一个用于检索关联,另一个用于检索每个源项数据.由于查询比存储数据更昂贵,我更喜欢复制存储.但这实际上取决于您的应用程序是读密集型还是写密集型.如果读取密集,则关联中的重复内容可以减少读取查询.如果写入密集型,则不复制内容会在更新源项时保存写入查询以更新关联.

希望这可以帮助!;)

  • 是的,您可以使用GSI。但是,它将以相同的方式复制数据。要使用GSI,我建议您利用稀疏索引。仅将属性添加到关联项,这样顶级项就不会在GSI中复制。 (2认同)