Currently DynamoDB does not offer the functionality natively within n8n to update an existing item and add additional attributes. I think this would be very helpful to use as a datastore if needed.
UpdateExpression would need to be added to allow for items to be updated during an upsert.
I’ve addressed this for the time being with an AWS Lambda (see code below) as well as the sample event that allows me to update the table contents without a complete overwrite. It admittedly feels a little hacky, but hopefully it’s enough of a solution to help others in the foreseeable future.
import boto3
from boto3.dynamodb.conditions import Key
from botocore.exceptions import ClientError
def lambda_handler(event, context):
# Extract the table name, key, and updates from the event
table_name = event['table_name']
key = event['key']
updates = event['updates'] # Expecting a list of dictionaries with 'attribute_name', 'value_to_add', and 'value_type'
# Initialize a DynamoDB client
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table(table_name)
# Build the update expression and attribute values dynamically
update_expression_parts = []
expression_attribute_values = {}
expression_attribute_names = {}
for i, update in enumerate(updates):
attr = update['attribute_name']
val = update['value_to_add']
value_type = update.get('value_type', 'numeric') # Assume numeric if value_type is not provided
placeholder = f"#attr{i}"
value_placeholder = f":val{i}"
if value_type == 'numeric':
update_expression_parts.append(f"{placeholder} = if_not_exists({placeholder}, :zero) + {value_placeholder}")
expression_attribute_values[':zero'] = 0 # Set the initial value to 0 for numeric attributes
else:
update_expression_parts.append(f"{placeholder} = if_not_exists({placeholder}, :empty) + {value_placeholder}")
expression_attribute_values[':empty'] = '' # Set the initial value to an empty string for string attributes
expression_attribute_values[value_placeholder] = val
expression_attribute_names[placeholder] = attr
final_update_expression = "SET " + ", ".join(update_expression_parts)
# Update the item in DynamoDB
try:
response = table.update_item(
Key=key,
UpdateExpression=final_update_expression,
ExpressionAttributeNames=expression_attribute_names,
ExpressionAttributeValues=expression_attribute_values,
ReturnValues='UPDATED_NEW'
)
return response
except ClientError as e:
print(e.response['Error']['Message'])
return e.response['Error']['Message']
Sample Input Event
updates = [
{"attribute_name": "Prompt Tokens", "value_to_add": 427, "value_type": "numeric"},
{"attribute_name": "Completion Tokens", "value_to_add": 108, "value_type": "numeric"},
{"attribute_name": "Total Tokens", "value_to_add": 535, "value_type": "numeric"},
{"attribute_name": "Log", "value_to_add": "New log entry", "value_type": "string"}
]```
If anyone has questions, feel free to reach out!
still i think it’s best n8n “DynamoDB official” node should support the proper UPSERT without remove those fields which are not requested. Million thanks!