DynamoDB如何更新地图,如果属性存在,否则默默忽略

问题描述:

我有一个表产品,其关键是范围:orgzviceid + productid。它有一个名为“结账”地图属性,并称为“prod_stk_qty_i_i”数量将存储属性。假设检验ID是5,并且检验了产品ID 34中的2个数量,则对于具有产品ID 34的产品,总可用数量是10.一旦推车检验发生,假设检验ID是5,产品(为的productid 34) “结账” 映射项和 “prod_stk_qty_i_i” 在DynamoDB会是这样的:DynamoDB如何更新地图,如果属性存在,否则默默忽略

"checkout" : { "5" : 2 }, 
"prod_stk_qty_i_i" : 8 

如果另一个结账发生同样的产品(比如1个数量),并且如果该结账ID是7,那么n如此的结帐:

"checkout" : { "5" : 2, "7" : 1 }, 
"prod_stk_qty_i_i" : 7 

如果付款,结帐条目被删除,数量增加。

现在,我的要求是定期在超时(30分钟)之后,发布已签出但未发布的产品数量。我通过

  • 做到这一点通过增加数量“结账”的价值
  • 取出结账。 map条目

即使多次尝试此操作(幂等),此操作也不会失败,这一点很重要,所以它必须只在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

如果我的要求是做一个“更新IF条件”? – Ouroboros

+0

条件表达式的要点是对操作强加一个条件。这可能是失败/断言用户想要的任何东西。 – Rahul

您的方法不起作用,因为您在条件表达式中混合了“Attribute”和“AttributeValue”。让我来解释:

"ConditionExpression": "attribute_exists(#checkout.#checkoutID)" 

在你的桌子,结账是发电机dB的属性,而checkoutID绝不相关的表模式。因此对于发电机数据库,checkoutID是属性值的一部分,而不是属性本身。

因此,有条件,你做不会工作。 您的用例的条件表达式将表示属性检出存在,它的值是。但是,为了做到这一点,您需要传递预计的地图,这可以归结为在更新之前读取记录。

我确实认为阅读记录,更新值并坚​​持它应该是在这种情况下继续前进的方式(并不一定是个坏主意) 在这种情况下,考虑使用某种乐观锁防止脏读取和写入。