Amazon web services 如何一次更新DynamoDB表中的多个项

Amazon web services 如何一次更新DynamoDB表中的多个项,amazon-web-services,amazon-dynamodb,nosql,Amazon Web Services,Amazon Dynamodb,Nosql,我正在使用DynamoDB,需要更新多个记录上的特定属性。在用伪语言编写我的需求时,我想做一个更新,即“更新表personset relationshipStatus=‘已婚’,其中personKey in(key1,key2,key3,…)”(假设personKey是我的DynamoDB表中的键) 换句话说,我想用In子句进行更新,或者我想可以称之为批处理更新。我发现了一个链接,它明确询问是否存在像批处理更新这样的操作,而答案是它不存在。但是,在条款中没有提到。显示条件表达式中支持IN子句(一

我正在使用DynamoDB,需要更新多个记录上的特定属性。在用伪语言编写我的需求时,我想做一个更新,即“更新表personset relationshipStatus=‘已婚’,其中personKey in(key1,key2,key3,…)”(假设personKey是我的DynamoDB表中的键)

换句话说,我想用In子句进行更新,或者我想可以称之为批处理更新。我发现了一个链接,它明确询问是否存在像批处理更新这样的操作,而答案是它不存在。但是,在条款中没有提到。显示条件表达式中支持IN子句(一次可提供100个值)。但是,我不确定这样一个IN子句是否适合我的情况,因为我仍然需要提供一个强制键属性(它似乎只需要一个值——我可能错了),并且我担心它会对每个更新进行完整的表扫描


所以我的问题是:如何同时更新多个DynamoDB记录?目前看来,我必须逐个调用每个键的update语句,这感觉真的不对…

正如您所指出的,DynamoDB不支持批量更新操作。您需要查询并获取要更新的所有记录的密钥。然后循环浏览该列表,一次更新一个项目。

我不知道答案给出后是否有变化,但现在可以了

见文件:

我在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
请注意DynamoDB限制():

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


如果我没记错的话,我认为dynogels是在发送请求之前将请求分为25块,然后在一个承诺和返回中收集请求(尽管我对此不是100%确定)-否则包装器函数的组装将非常简单

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


官方文档可用,您也可以查看TransactionWriteItems javascript/nodejs示例。

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

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


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

我可以使用for循环并将我的主id作为密钥传递来更新多个记录吗?@prakashtank你的问题与我在回答中所说的有什么不同?你试过了吗d这并遇到了一个特定的问题?谢谢你的回复。我不确定在for循环中的多个项目是否会被更新。但它确实起作用了。@prakash tank,那么你能在查询中使用in吗?或者你只是在循环中进行了多个更新?@Forest:我在循环中更新了我的值。我没有尝试,因为我没有找到much。如果您确定清除put请求上的数据,则此操作有效。批写入不会更新项,因此任何与现有ID匹配的对象都将完全替换现有ID。如果覆盖不正确,则需要进行更新…可能是在循环中。我想进一步澄清上述注释。上面的示例是PUTRequest。PUT用于创建/设置特定键的值(POST将该值创建为键的子项)。此示例不是关于更新记录/文档中的属性,而是关于键的批量PUT。这就是为什么此操作“覆盖记录”,而不“更新记录内容”。对于我们这些来自T-SQL/关系查询世界的人来说,PUT更像是INSERT而不是UPDATE,因为INSERT旨在影响整行,而UPDATE旨在更改“行”的一个或多个“列”@rainabba所以只要你不使用补丁请求,这是有用的,但做完整的数据obj帖子,那么应该一个接一个地完成。嗨,我正试图解决同样的问题,并考虑使用TransactionWriteItems。但我很困惑。Transaction写入可以同时更新多个记录,还是可以在一个记录上执行多个操作?例如添加、获取,更新等。我只能从文档中了解。感谢advanceHi,TransactionWriteItems是一个同步写入操作,最多可将25个操作请求分组。
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);
});