多对多关系:全球二级索引与邻接列表

时间:2018-11-04 14:11:31

标签: amazon-dynamodb adjacency-list amazon-dynamodb-index

为了表示Dynamo DB中的多对多关系,我通常看到两种方法:全局二级索引(GSI)和邻接列表。现在我的问题是,什么时候使用哪个?

基本上,使用GSI的状态是翻转分区键和排序键,以便在两种情况下都可以有效地查询数据。示例显示了诸如与玩家在线游戏之类的东西,例如

Players table
--------------
Partition | Sort
-----------------
Player 1  | Game 1
Player 1  | Game 2
Player 2  | Game 1
Player 3  | Game 2

Games GSI
-----------
Partition | Sort
-----------------
Game 1    | Player 2
Game 1    | Player 2
Game 2    | Player 1
Game 2    | Player 3 

我假设这些都是同一游戏平台内的所有会话,即与有限数量的玩家匹配。

这一切看起来都是直截了当且逻辑合理的……直到数据变得更加复杂为止。如果玩家和游戏都有自己的属性集怎么办?假设游戏具有启动时间的属性,而玩家具有用户名和个人游戏得分等属性。如何将这些投影到Table和GSI上?

例如,所需的投影应该是这样的

让玩家参与游戏

// query made with game id
{
  start_date: '2018-11-04T13:00Z',
  status: 'IN_PROGRESS',
  players: [
    {
      username: 'starkshark',
      points: 200
    },
    {
      username: 'coldshot',
      points 300
    }
  ]
}

获取玩家参与的游戏

// query made with player id
{
  username: 'starkshark',
  games: [
    {
      status: 'IN_PROGRESS',
      start_date: '....'
    },
    {
      status: 'ENDED',
      start_date: '...',
      end_date: '...'
    }
  ]
}

或者这是当需要使用邻接列表模式时的临界情况吗?从我大致阅读的有关邻接列表的内容来看,实现简单的多对多关系似乎很复杂,就像上面的在线游戏示例一样。据我所知,它的意思是对具有多个相互链接的节点的图形进行建模。当然,在这种情况下,节点将是“游戏”和“玩家”(以及模型中可能需要的任何其他实体)

TLDR :因此归结为最后一个问题,当拥有自己属性集的实体之间具有多对多关系时,邻接表是寻找的选项还是模型的数据结构不太复杂?

1 个答案:

答案 0 :(得分:2)

当一个实体拥有自己的一组属性时,您可以在邻接列表中对其进行建模,使其成为一个环回自身的边。

Id1       | Id2     | Data
- - - - - - - - - - - - - - - - - - - 
User1     | User1   | {email=...}

或者,您可以将属性建模为从实体到属性类型的边。

Id1       | Id2     | Data
- - - - - - - - - - - - - - - - - - - 
User1     | Email   | bob@...

这完全取决于您希望如何查询数据。第二种方法的优点是您可以拥有一个GSI,其中Id2是分区键,而Data是范围键,这将使您能够有效地找到与某个属性值匹配的所有用户。 。

对于GSI,邻接模式通常具有一个GSI,该GSI包含与表相同的主键属性,但是顺序进行了转置,因此您可以轻松地在任一方向上查询邻接表。