DynamoDB邻接表主键

时间:2018-06-26 21:31:51

标签: nosql amazon-dynamodb adjacency-list

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

我在id上有一个主键,在type上有主排序键,然后在iddata上有另一个全局索引,我在{{ 1}}和id,但我认为这是多余的。

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

type

我正在从这个很棒的演讲https://www.youtube.com/watch?v=jzeKPKpucS0中获得建议,而这些文档并不是那么出色的https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-adjacency-graphs.html

我遇到的问题是,如果我尝试添加带有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 “ 1”和id“ tag”的另一个标签,它将覆盖现有标签,因为它具有相同的复合键。我在这里想念什么?似乎建议将主键和排序键设为typeid。我应该让我的类型更像“ tag#orange”吗?在那种情况下,我可以将全局索引放在type上,并将排序键放在类型上。这样,我可以通过查询target =“ tag”并以“ tag”开头来获取带有特定标签的所有帖子。

只需寻找一些有关使用Dynamo处理此类邻接表数据的建议,因为这似乎很有趣。谢谢!

2 个答案:

答案 0 :(得分:15)

邻接表的基本准则

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

  1. 最高级别(即您的 帖子 标签
  2. 关联(表示与每个 Post 关联的 标记 ,反之亦然)

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

  • 每个顶级项目(在您的情况下为 Post Tag )必须使用主键。另外,这些项目在排序键和主键中应该具有相同的值
  • 对于关联,请使用主键代表 source (或 parent ),并使用sort-key代表 target (或 child )。

根据我在示例中看到的内容,设置了 帖子 标签 的主键作为商品ID,同时还应使用其 type ;例如Post-1Tag-3。在表示关联的项目中,我也看不到您存储目标 ID

示例

假设您拥有:

  • 三个帖子:“ hello world” “ foo bar” “ Whatever ...”
  • 和三个标签:“酷” “很棒” “很棒”
  • 发布“ hello world” 有一个标签:“ cool”
  • 发布“ foo bar” 有两个标签:“ cool” “ great”
  • 发布“随便...” 没有任何标签

您需要在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

如何查询此邻接表

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-1 Tag-3 关联。

检查the documentation的关键条件表达式begin_em。

3)您需要所有与 Tag-1 相关的帖子:

通过primary_key == "Tag-1" & sort-key BEGINS_WITH "Post-"查询-返回: Post-1 Post-2 关联。

  

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

     

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

希望这会有所帮助! ;)

答案 1 :(得分:2)

我认为您没有丢失任何东西。这个想法是ID对于项目类型是唯一的。通常,您会为ID生成一个长UUID,而不是使用序列号。另一种选择是使用创建项目的日期时间,可能添加一个随机数,以避免创建项目时发生冲突。

我以前提供的答案可能会有所帮助DynamoDB M-M Adjacency List Design Pattern

请不要删除排序键-这不会使您的商品更加独特。