我试图找出如何在源数据包含映射值的项目上执行原子更新,其中这些映射的键是动态的。
如果您查看下面的示例数据,我试图找出如何在同一项目上对BSSentDestIp和BSRecvDestIp中的值进行原子更新。我正在阅读文档,但我唯一能找到的是 list_append ,它会给我一个附加的键/值列表,我需要遍历并稍后求和。
http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html
输入数据示例:
{
"RecordId": 31,
"UUID": "170ae748-f8cf-4df9-6e08-c0c8a5f029d4",
"UserId": "username",
"DeviceId": "e0:cb:4e:53:ae:ff",
"ExpireTime": 1501445446,
"StartTime": 1501441846,
"EndTime": 1501441856,
"MinuteId": 10,
"PacketCount": 1028,
"ByteSum": 834111,
"BSSent": 98035,
"BSRecv": 736076,
"BSSentDestIp": {
"151.101.129.69": 2518,
"192.168.1.254": 4780,
"192.168.1.80": 14089,
"192.33.31.162": 2386,
"54.239.30.232": 21815,
"54.239.31.129": 6423,
"54.239.31.69": 3255,
"54.239.31.83": 18447,
"98.138.253.109": 3020
},
"BSRecvDestIp": {
"151.101.129.69": 42414,
"151.101.57.174": 20792,
"192.230.66.108": 130175,
"192.33.31.162": 56398,
"23.194.140.100": 26209,
"54.239.26.209": 57210,
"54.239.31.129": 188747,
"54.239.31.69": 41115,
"98.138.253.109": 111775
}
}
NodeJS函数通过Lambda执行以更新Dynamo:
function updateItem(UserIdValue, MinuteIdValue) {
var UpdateExpressionString = "set PacketCount = PacketCount + :PacketCount, \
ByteSum = ByteSum + :ByteSum, \
BSSent = BSSent + :BSSent, \
BSRecv = BSRecv + :BSRecv";
var params = {
TableName: gDynamoTable,
Key: {
"UserId": UserIdValue,
"MinuteId": MinuteIdValue
},
UpdateExpression: UpdateExpressionString,
ExpressionAttributeValues: {
":PacketCount": gRecordObject.PacketCount,
":ByteSum": gRecordObject.ByteSum,
":BSSent": gRecordObject.BSSent,
":BSRecv": gRecordObject.BSRecv
},
ReturnValues: "UPDATED_NEW"
};
dynamo.updateItem(params, function(err, data) {
if (err) {
console.log("updateItem Error: " + err);
} else {
console.log("updateItem Success: " + JSON.stringify(data));
}
});
}
答案 0 :(得分:2)
如果你读取一个项目,那么在DynamoDB中更新一个单项是原子的,并且调用PutItem它保证是原子的。它要么更新所有字段,要么不更新任何字段。
现在,我看到的唯一问题是你可能有写冲突。假设一个进程读取一个项目,更新一个映射,而另一个并行进程执行相同的操作,将导致一个PutItem覆盖最近的更新,并且您可能丢失数据。
要解决此问题,您可以使用conditional updates。简而言之,它允许您仅在满足指定条件时更新项目。您可以做的是保持每个项目的版本号。更新项目时,可以增加版本属性,并在编写项目时检查版本号是否符合预期。否则,您需要再次阅读该项目(有人在您使用它时更新它)再次执行更新并尝试再次写入。