DynamoDB UpdateExpression Functionality

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!

+1 for upsert