I'm working a use case where a dynamoDB update should:
- Dynamically upsert (update if present, insert if not present) an item, without hardcoding the item's components.
- Use the DynamoDB Document Client for simplicity
- And in the same atomic operation, update a simple counter
I started with an excellent utility method by Daniel Barrel at https://stackoverflow.com/a/63511693/15369972 that provides a general utility method for the update with dynamic values, but without the atomic counter.
I've attempted to add the atomic counter capability by adding the counter and its incrementor into the parameter objects after the dynamic values are loaded, but am getting a static value in the counter on update instead of a value that increments by one with each call.
Where is this going wrong? I call the modified update function with a table name, a dynamic javascript object, and an array containing the hash and sort key:
await update(tableName, jsonObjectToStore, ['myHashKey', 'mySortKey'])
And the modified update method that's not incrementing as I'd like, is:
async function update (tableName, item, idAttributeNames) {
var params = {
TableName: tableName,
Key: {},
ExpressionAttributeValues: {},
ExpressionAttributeNames: {},
UpdateExpression: "",
ReturnValues: "UPDATED_NEW"
};
for (const attname of idAttributeNames) {
params["Key"][attname] = item[attname];
}
let prefix = "set ";
let attributes = Object.keys(item);
for (let i=0; i<attributes.length; i++) {
let attribute = attributes[i];
if (!idAttributeNames.includes(attribute)) {
params["UpdateExpression"] += prefix + "#" + attribute + " = :" + attribute;
params["ExpressionAttributeValues"][":" + attribute] = item[attribute];
params["ExpressionAttributeNames"]["#" + attribute] = attribute;
prefix = ", ";
}
}
// Add the counter
params["UpdateExpression"] += ", #nImports = :nImports + :incr";
console.log(params["UpdateExpression"])
console.log(params["ExpressionAttributeValues"])
params["ExpressionAttributeValues"][":incr"] = 1;
params["ExpressionAttributeValues"][":nImports"] = 0;
console.log(params["ExpressionAttributeValues"])
console.log(params["ExpressionAttributeNames"])
params["ExpressionAttributeNames"]["#nImports"] = 'nImports'
console.log(params["ExpressionAttributeNames"])
await docClient.update
return await docClient.update(params).promise();
}