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

Time:03-07

I have a lambda function that needs to retrieve an item from DynamoDB and update the counter of that item. But..

The DynamoDB table is structured as:

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

I need to first retrieve the item of the table that has a certain id and a certain option listed as a key in the options.

Then I want to increment that counter by some value.

Here is what I have so far:

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?

My issues is how to update the record now and more importantly will such solution cause data races? Could 2 simultaneous lambda calls that try to update the same item at the same option cause data races? If so what's the way to solve this?

Any pointers/help is appreciated.

CodePudding user response:

Ok, I found the answer:

All I need is:

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"
)

This is inspired from Step 3.4: Increment an Atomic Counter which provides an atomic approach to increment values. According to the documentation:

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.)

CodePudding user response:

will such solution cause data races?

Yes, it can cause data races. To overcome this, DynamoDB provides conditional writes. As the documentation says, "conditional write succeeds only if the item attributes meet one or more expected conditions". This means that you can have a condition which will force the update to succeed only the value was not modified by somebody else.

Example from the AWS docs for conditional writes using Boto3: example.

  • Related