I want to update or create DynamoDB item to get next element:
{
"id": 156,
"date": 12323233.000,
"countries": {
"ua": 1,
"ru": 2}
}
I use python and boto3. So I can check if field countries
exist and if not add it. But that will mean 2 DB requests.
table.update_item(
Key={
'id': 156,
'date': date,
},
UpdateExpression='SET countries = if_not_exists(countries, :countries)',
ExpressionAttributeValues={
':countries': {},
},
)
table.update_item(
Key={
'id': 156,
'date': date,
},
UpdateExpression='ADD countries.#country :inc',
ExpressionAttributeNames={"#country": country},
ExpressionAttributeValues={
':inc': 1
},
)
Is there any way to merge this 2 requests in one?
To update an existing item in an Amazon DynamoDB table, you use the UpdateItem operation. You must provide the key of the item that you want to update. You must also provide an update expression, indicating the attributes that you want to modify and the values that you want to assign to them.
Edits an existing item's attributes, or adds a new item to the table if it does not already exist.
The main difference between the two is, PutItem will Replace an entire item while UpdateItem will Update it.
DynamoDB provides four operations for basic create, read, update, and delete (CRUD) functionality. All these operations are atomic.
I had to do something like this recently, and took a while to figure out. I've got a count I want to increment if a page doesn't already exist in my set of "done" pages. If not, it increments and adds the page number to the set. Took a while to realize you can 'append' to a list, but have to 'add' to a set.
try:
res = dbt.update_item(
Key={'pk': 'doc3', 'sk': 'na'},
ReturnConsumedCapacity='INDEXES', ReturnValues='ALL_NEW',
ExpressionAttributeNames={
'#count': 'count',
'#done': 'done',
},
ExpressionAttributeValues={
':1': 1,
':page': page,
':pagelist': set([page]),
},
ConditionExpression="(NOT contains(done, :page))",
UpdateExpression="ADD #done :pagelist, #count :1",
)
print(f'rand int page={page} count={res["Attributes"]["count"]}'
f' CU={res["ConsumedCapacity"]["Table"]}')
except ClientError as err:
if err.response['Error']['Code'] == 'ConditionalCheckFailedException':
print('Already got page=%s (%s)' % (page, err))
else:
raise
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With