Update attributes of DynamoDB table item
While defining my DynamoDB table, I selected filename
as the unique attribute or primary key. In this function, I want to modify some columns of the entry with a particular filename
. I tried this after following another SO answer:
def update_item_in_db(filename, archive_path): table = dynamodb.Table(dynamodb_table_name) try: logger.info(f'Updating dynamo table for filename: {filename}') response = table.update_item( Key={'filename': filename}, AttributeUpdates={ 'archive_path': archive_path, 'archived_on': datetime.today().strftime('%Y-%m-%d-%H:%M:%S') }, ) except Exception as e: raise Exception(f"Unable to insert filename into dynamodb: {e}") return response
but I get an error that:
Parameter validation failed:nInvalid type for parameter AttributeUpdates.archive_path, value: archive/100-ff0-uat/1591282803734/issues_1591282803734.zip, type: <class 'str'>, valid types: <class 'dict'>nInvalid type for parameter AttributeUpdates.archived_on, value: 2021-11-21-15:06:46, type: <class 'str'>, valid types: <class 'dict'>",
Then I also tried:
response = table.update_item( { 'filename': filename, 'archive_path': archive_path, 'archived_on': datetime.today().strftime('%Y-%m-%d-%H:%M:%S') } )
but then I get the following error:
"Unable to insert filename into dynamodb: update_item() only accepts keyword arguments.",
What’s the correct syntax to update an item?
Note that I only want to UPDATE/MODIFY and not delete and re-insert.
Answer
The first approach uses a deprecated syntax. The second one is closer to what you want to do.
Something like this should work:
from datetime import datetime import boto3 dynamodb = boto3.resource("dynamodb") def update_item_in_db(filename, archive_path): table = dynamodb.Table(dynamodb_table_name) table.update_item( Key={ "filename": filename }, UpdateExpression="SET #archive_path = :archive_path, #archived_on = :archived_on", ExpressionAttributeNames={ "#archive_path": "archive_path", "#archived_on": "archived_on" }, ExpressionAttributeValues={ ":archive_path": archive_path, ":archived_on": datetime.today().strftime('%Y-%m-%d-%H:%M:%S') } )
The ExpressionAttributeNames
and ExpressionAttributeValues
allow you to use reserved keywords in the UpdateExpression
, that’s why they’re commonly used.
(I didn’t run the code, there may be typos.)