拥有git提交的DynamoDB表的最佳数据模型是什么?

时间:2015-11-30 23:35:30

标签: amazon-dynamodb

我正在为DynamoDB寻找最合适的表结构 将由存储库提交(git)提交的表。

系统中有两个同样受欢迎的请求:

  1. 提交unique(repository + sha) [拒绝,如果不是唯一的]
  2. 通过repository + sha
  3. 获取特定提交
  4. 按升序/降序获取存储库的第一个n提交
  5. 我尝试创建一个包含hash: repository, range: sha KeySchema的表 以及hash: repository, range: createdAt, projection: ALL

    的二级索引

    这具有能够以原子方式拒绝提交的优点 如果它与另一个提交具有相同的存储库+ sha(通过ConditionExpression)。 它的缺点是需要2倍的尺寸(因为我需要能够投射) 第三个查询的所有键。)

    有没有办法在没有2x尺寸要求的情况下支持上述三个查询。

    这是代码,澄清:

    async function createCommitsTable() {
      await dyn.createTable({
        ProvisionedThroughput,
        TableName: COMMITS,
        AttributeDefinitions: [
          {AttributeName: 'repository', AttributeType: 'S'},
          {AttributeName: 'sha', AttributeType: 'S'},
          {AttributeName: 'createdAt', AttributeType: 'N'},
        ],
        KeySchema: [
          {AttributeName: 'repository', KeyType: 'HASH'},
          {AttributeName: 'sha', KeyType: 'RANGE'},
        ],
        LocalSecondaryIndexes: [{
          IndexName: 'CreatedAtIndex',
          Projection: {ProjectionType: 'ALL'},
          KeySchema: [
            {AttributeName: 'repository', KeyType: 'HASH'},
            {AttributeName: 'createdAt', KeyType: 'RANGE'},
          ]
        }]
      })
    }
    

    将提交放入表中:

    async function putCommits() {
      await dc.put({
        TableName: COMMITS,
        Item: {
          repository: 'linux',
          sha: '6a13feb9c82803e2b815eca72fa7a9f5561d7861',
          createdAt: Date.now()
        },
        ConditionExpression:
          'attribute_not_exists(repository) and attribute_not_exists(sha)'
      })
    }
    

    在表中查询单个和多个提交(按createdAt排序):

    async function queryCommits() {
      console.log('[single commit]:\n', await dc.get({
        TableName: COMMITS,
        Key: {
          repository: 'linux',
          sha: '6a13feb9c82803e2b815eca72fa7a9f5561d7861'
        }
      }));
    
      console.log('[commits by repo]:\n', await dc.query({
        TableName: COMMITS,
        IndexName: 'CreatedAtIndex',
        KeyConditionExpression: 'repository = :repository',
        ExpressionAttributeValues: {
          ':repository': 'linux'
        }
      }));
    }
    

1 个答案:

答案 0 :(得分:2)

尝试使用createdAt和sha的复合键,如下所示:

async function createCommitsTable() {
    await dyn.createTable({
        ProvisionedThroughput,
        TableName: COMMITS,
        AttributeDefinitions: [
            {AttributeName: 'repository', AttributeType: 'S'},
            {AttributeName: 'createdAt-sha', AttributeType: 'S'},
        ],
        KeySchema: [
            {AttributeName: 'repository', KeyType: 'HASH'},
            {AttributeName: 'createdAt-sha', KeyType: 'RANGE'},
        ]
    })
}

如果使用可排序的时间戳字符串,它允许您将createdAt-sha连接用作排序键,并在写入中使用contains作为条件,如下所示:

async function putCommits() {
    await dc.put({
        TableName: COMMITS,
        Item: {
          repository: 'linux',
          createdAt-sha: Date.now() + '-6a13feb9c82803e2b815eca72fa7a9f5561d7861'
        },
        ConditionExpression:
          'attribute_not_exists(repository) and NOT contains("createdAt-sha", sha)'
    })
}

然后,您可以按日期查询表中的已排序提交。不确定所有这些格式是否正确,但这应该是一般的想法。