如何一次更新DynamoDB表中的多个项目

Sta*_*ley 21 amazon-web-services nosql amazon-dynamodb

我正在使用DynamoDB,我需要更新多个记录的特定属性.用伪语言写我的要求我想做一个更新,说"更新表设置relationshipStatus ='结婚',其中personKey IN(key1,key2,key3,...)"(假设personKey是我的KEY) DynamoDB表).

换句话说,我想用IN子句进行更新,或者我想可以将其称为批量更新.我发现链接明确询问是否存在类似批量更新的操作,并且答案是否存在.但是,它没有提到IN子句.的文档表明IN-子句中ConditionalExpressions(100个值可在同一时间内提供)支撑.但是,我不确定这样的IN子句是否适合我的情况,因为我仍然需要提供一个强制的KEY属性(它看起来似乎只有一个值 - 我可能是错的)而且我担心它会做一个每次更新的全表扫描.

所以我的问题是:如何同时实现多个DynamoDB记录的更新?目前几乎看起来我将不得不逐个调用每个密钥的更新声明,这只是感觉真的错了......

Mar*_*k B 25

如您所述,DynamoDB不支持批量更新操作.您需要查询并获取要更新的所有记录的密钥.然后遍历该列表,一次更新一个项目.

  • @prakashtank 您的问题与我在回答中所说的有何不同?您是否尝试过并遇到特定问题? (2认同)

Raj*_*iya 10

您可以使用 TransactWriteItems 操作更新 DynamoDB 表中的多个记录。

提供的官方文档在这里,还可以看到TransactWriteItems的JavaScript /例子的NodeJS这里


小智 9

DynamoDb 并未设计为支持本机事务的关系数据库。最好在设计架构时就避免出现多次更新的情况。或者,如果它在您的情况下不实用,请记住您可以在重组设计时对其进行改进。

同时更新多个项目的唯一方法是使用 DynamoDB 提供的 TransactionWrite 操作。但它有一个限制(例如最多 25 个)。因此请记住这一点,您可能也应该在您的应用程序中进行一些限制。尽管成本非常高(因为实现涉及一些共识算法),但它仍然比简单的循环快得多。它为您提供了 ACID 属性,这可能是我们最需要的。想象一下使用循环的情况,如果其中一个更新失败,你如何处理失败?是否可以回滚所有更改而不引起某些竞争条件?更新是幂等的吗?这实际上取决于您应用原因的性质。当心。

另一种选择是使用线程池来完成网络 I/O 作业,这肯定可以节省大量时间,但它也有同样的失败和回滚问题需要考虑。

  • 不要使用“DynamoDB”,这是正确的答案。 (5认同)

Sim*_*bæk 5

自给出答案以来,我不知道它是否已更改,但现在有可能

请参阅文档:https : //docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_BatchWriteItem.html

我已经在javascript中使用了它(将新块映射到具有所需结构的对象数组:

let params = {}
let tableName = 'Blocks';

params.RequestItems[tableName] = _.map(newBlocks, block => {
    return {
        PutRequest: {
            Item: {
                'org_id': orgId,
                'block_id': block.block_id,
                'block_text': block.block_text
            },
            ConditionExpression: 'org_id <> :orgId AND block_id <> :block_id',
            ExpressionAttributeValues: {
                ':orgId': orgId,
                ':block_id': block.block_id
            }
        }
    }
})

docClient.batchWrite(params, function(err, data) {
   .... and do stuff with the result
Run Code Online (Sandbox Code Playgroud)

您甚至可以混合putsdeletes

而且,如果您使用的是测功机(由于测功机的支持,您不能混合使用em,但是您可以做的就是更新(使用create,因为在幕后它会像投放时一样转换为batchWrite函数)

var item1 = {email: 'foo1@example.com', name: 'Foo 1', age: 10};
var item2 = {email: 'foo2@example.com', name: 'Foo 2', age: 20};
var item3 = {email: 'foo3@example.com', name: 'Foo 3', age: 30};

Account.create([item1, item2, item3], function (err, acccounts) {
  console.log('created 3 accounts in DynamoDB', accounts);
});
Run Code Online (Sandbox Code Playgroud)

请注意DynamoDB的限制(来自docs):

BatchWriteItem操作在一个或多个表中放置或删除多个项目。一次调用BatchWriteItem最多可以写入16 MB的数据,其中可以包含多达25个放置或删除请求。要写入的单个项目最大可以为400 KB。

如果我没记错的话,我认为dynogels将请求分拆成25个小块,然后发送出去,然后将它们收集到一个诺言中并返回(尽管我对此不确定100%) -否则,包装函数将非常容易组装

  • 如果您可以销毁放置请求中的数据,则此方法有效。批量写入不会更新项目,因此任何与现有ID匹配的对象都将完全替换现有对象。在无法覆盖的情况下,需要进行更新...可能在循环中 (17认同)
  • 我想进一步澄清上述评论。上面的例子是一个 PUTRequest。PUT 旨在创建/设置特定键的值(POST 将值创建为键的子项)。此示例不是关于更新记录/文档中的属性,而是关于键的批量 PUT。这就是为什么这“覆盖记录”并且不“更新记录内容”。对于我们这些来自 T-SQL/关系查询世界的人来说,PUT 更像是 INSERT 而不是 UPDATE,因为 INSERT 旨在影响整行,而 UPDATE 旨在更改“行”的一个或多个“列”。 (2认同)