【发布时间】:2023-01-18 03:18:55
【问题描述】:
我在执行大量本机 DynamoDB 更新操作的项目中有一些 TypeScript 代码:
import { nativeDocumentClient, nativeDynamo } from '../utils/aws';
// snipped code
// updatedProducts is of type `{ id: string; siteId: string; state: ProductState }[]`
await Promise.all(
updatedProducts.map(({ id, siteId, state }) =>
nativeDocumentClient
.update({
TableName,
Key: {
id,
siteId,
},
ExpressionAttributeNames: {
'#s': 'state',
},
ExpressionAttributeValues: {
':state': state,
':updatedAt': new Date().toISOString(),
},
UpdateExpression: 'SET #s = :state, updatedAt = :updatedAt',
ReturnValues: 'ALL_NEW',
})
.promise()
)
);
现在我们总是希望这条记录(及其复合键)存在,但我们发现了一种罕见的情况,情况并非如此(这可能只是非产品环境中的不良数据,而不是具体的错误)。不幸的是,它看起来像底层UpdateItemCommand 做的是更新而不是更新,尽管它的名字。来自the official docs:
编辑现有项目的属性,或将新项目添加到表中(如果尚不存在)
我们可以做一个 TypeScript
ifguard 子句,它在记录中获取,如果它不存在则跳过更新插入。然而,这感觉就像是对竞争条件的邀请——.update()上是否有一个选项可以让我们在没有单独条件的情况下得到我们想要的东西?
【问题讨论】:
-
啊,我想知道我们是否可以做
ConditionExpression: 'attribute_exists(id)'或类似的事情 - 基本上如果旧对象设置了其中一个键,那么这是一个更新而不是更新插入,操作可以继续进行。 -
这个想法有点混乱,但为了完整起见:设置
ReturnValues: 'ALL_OLD',如果旧的返回记录为空,则删除新记录。
标签: amazon-web-services amazon-dynamodb upsert