当要更新的值位于映射字段中时,增加 DynamoDB 中的计数器

Incrementing a counter in DynamoDB when value to be updated is in a map field

我有一个 lambda 函数需要从 DynamoDB 中检索一个项目并更新该项目的计数器。但是..

DynamoDB table 的结构为:

id: int
options: map
    some_option: 0
    some_other_option: 0

我需要先检索 table 中具有特定 id 和特定选项的项目,这些选项列为 options 中的键。

然后我想将该计数器增加一些 value

这是我目前的情况:

dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('options')

response = None
try:
    response = table.get_item(Key={'id': id})
except ClientError as e:
    print(e.response['Error']['Message'])

option = response.get('Item', None)
if option:
    option['options'][some_option] = int(option['options'][some_option]) + some_value
    # how to update item in DynamoDB now?

我的问题是现在如何更新记录,更重要的是这样的解决方案会导致数据竞争吗?尝试在同一选项下更新同一项目的 2 个同时 lambda 调用是否会导致数据争用?如果有,有什么办法可以解决?

任何 pointers/help 不胜感激。

好的,我找到答案了:

我只需要:

response = table.update_item(
    Key={
        'id': my_id,
    }, 
    UpdateExpression='SET options.#s = options.#s + :val',  
    ExpressionAttributeNames={
        "#s": my_option
    },  
    ExpressionAttributeValues={
        ':val': Decimal(some_value)
    },
    ReturnValues="UPDATED_NEW"
)

这受到 Step 3.4: Increment an Atomic Counter 的启发,它提供了一种原子方法来递增值。根据文档:

DynamoDB supports atomic counters, which use the update_item method to increment or decrement the value of an existing attribute without interfering with other write requests. (All write requests are applied in the order in which they are received.)