我有一个名为Products的表,其Key是一个范围: orgzviceid + productid 。它有一个名为" 结帐 "的地图属性和数量存储属性名为" prod_stk_qty_i_i "。
首先说,对于产品ID为34的产品,总可用数量为10.一旦购物车结帐,假设结帐ID为5,并且已检查产品ID 34中的2个数量,那么产品& #39; s(适用于productid 34)" 结帐 "地图条目和" prod_stk_qty_i_i "在DynamoDB中将是这样的:
"checkout" : { "5" : 2 },
"prod_stk_qty_i_i" : 8
如果同一产品发生了另一次结账(比如1个数量),如果该结账ID为7,那么结帐可以这样:
"checkout" : { "5" : 2, "7" : 1 },
"prod_stk_qty_i_i" : 7
如果付款,则结帐条目将被删除,数量会增加。
现在,我的要求是在一些超时(30分钟)后定期发布已检出但未发布的产品数量。我这样做是
即使多次尝试此操作(幂等),此操作也不会失败,因此只有在checkout.checkoutID字段存在时才需要更新。如果没有,它应该简单地忽略。
我尝试了以下内容:
[
"UpdateItem",
[
{
"TableName": "Products",
"Key": {
"orgzviceid": {
"N": "3000161710"
},
"productid": {
"N": "11"
}
},
"UpdateExpression": "REMOVE #checkout.#checkoutID SET #prod_stk_qty_i_i = #prod_stk_qty_i_i + #checkout.#checkoutID",
"ExpressionAttributeNames": {
"#checkout": "checkout",
"#checkoutID": "235",
"#prod_stk_qty_i_i": "prod_stk_qty_i_i"
},
"ConditionExpression": "attribute_exists(#checkout.#checkoutID)",
"ReturnValues": "ALL_NEW"
}
]
]
但是,如果没有找到结帐ID 235的结账条目,它会给我一个错误。请注意,我已经写过ConditionExpression只在属性" condition.235"存在。
错误日志:
com.amazonaws.dynamodb.v20120810#ConditionalCheckFailedException""消息":"该 条件请求失败..."
那么,我如何编写一个查询,如果映射条目存在,那么执行上述操作,其他方面不会失败? 显然,一个糟糕的黑客是首先检查GetItem查询是否存在提供的CheckoutID的结帐条目,然后只执行此操作,但是,它似乎不正确
答案 0 :(得分:0)
我相信您错误地使用条件表达式。如果不满足某些标准,条件的要点就是失败。你有什么条件吗?没有条件,它只会执行更新表达式,如果该项不存在,我不希望你得到一个错误。就像查询不存在的项目一样。你应该简单地得到一个空的套装。不是错误。
答案 1 :(得分:0)
您的方法无效,因为您在条件表达式中混合了“Attribute”和“AttributeValue”。让我解释一下:
"ConditionExpression": "attribute_exists(#checkout.#checkoutID)"
在您的表中,checkout是dynamo db中的一个属性,而checkoutID与表模式无关。因此对于dynamo DB,checkoutID是属性值的一部分,而不是属性本身。
因此,拥有你所做的条件是行不通的。 您的用例的条件表达式将表示属性检查存在且值为。但是,为了做到这一点,你需要传递预期的地图,在更新之前将其归结为阅读记录。
我确实认为阅读记录,更新价值并坚持下去应该是在这种情况下继续前进的方式(并不一定是个坏主意) 在这种情况下,请考虑使用某种乐观锁定来防止脏读写。