当要更新的值位于映射字段中时,增加 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.)
我有一个 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.)