node.js AWS dynamodb updateItem
You can update attributes dynamically. see below code.
export const update = (item) => {
console.log(item)
const Item = {
note: "dynamic",
totalChild: "totalChild",
totalGuests: "totalGuests"
};
let updateExpression='set';
let ExpressionAttributeNames={};
let ExpressionAttributeValues = {};
for (const property in Item) {
updateExpression += ` #${property} = :${property} ,`;
ExpressionAttributeNames['#'+property] = property ;
ExpressionAttributeValues[':'+property]=Item[property];
}
console.log(ExpressionAttributeNames);
updateExpression= updateExpression.slice(0, -1);
const params = {
TableName: TABLE_NAME,
Key: {
booking_attempt_id: item.booking_attempt_id,
},
UpdateExpression: updateExpression,
ExpressionAttributeNames: ExpressionAttributeNames,
ExpressionAttributeValues: ExpressionAttributeValues
};
return dynamo.update(params).promise().then(result => {
return result;
})
}
This is exactly what AWS.DynamoDB.DocumentClient's update
method does.
There is already a sample code on how to use the update
method here for AWS SDK for JavaScript in Node.js.
For example:
'use strict';
const aws = require('aws-sdk');
// It is recommended that we instantiate AWS clients outside the scope of the handler
// to take advantage of connection re-use.
const docClient = new aws.DynamoDB.DocumentClient();
exports.handler = (event, context, callback) => {
const params = {
TableName: "MYTABLE",
Key: {
"id": "1"
},
UpdateExpression: "set variable1 = :x, #MyVariable = :y",
ExpressionAttributeNames: {
"#MyVariable": "variable23"
},
ExpressionAttributeValues: {
":x": "hello2",
":y": "dog"
}
};
docClient.update(params, function(err, data) {
if (err) console.log(err);
else console.log(data);
});
};
I think some of the examples are a bit confusing. If I have the following table columns
ID | Name | Age
And I want to update the Name
attribute and leave the Age
attribute unchanged.
const updateName = async () => {
const aws = require('aws-sdk');
const docClient = new aws.DynamoDB.DocumentClient();
const newName = 'Bob';
const params = {
TableName: 'myTable',
Key: {
ID: 'myId',
},
UpdateExpression: 'set Name = :r',
ExpressionAttributeValues: {
':r': newName,
},
};
await docClient.update(params).promise();
}
updateName();
This seemed a bit more simple.
Here is a more secure and up-to-date function to achieve this:
const {
DynamoDBClient, UpdateItemCommand,
} = require('@aws-sdk/client-dynamodb');
const { marshall, unmarshall } = require('@aws-sdk/util-dynamodb');
const client = new DynamoDBClient({});
/**
* Update item in DynamoDB table
* @param {string} tableName // Name of the target table
* @param {object} key // Object containing target item key(s)
* @param {object} item // Object containing updates for target item
*/
const update = async (tableName, key, item) => {
const itemKeys = Object.keys(item);
// When we do updates we need to tell DynamoDB what fields we want updated.
// If that's not annoying enough, we also need to be careful as some field names
// are reserved - so DynamoDB won't like them in the UpdateExpressions list.
// To avoid passing reserved words we prefix each field with "#field" and provide the correct
// field mapping in ExpressionAttributeNames. The same has to be done with the actual
// value as well. They are prefixed with ":value" and mapped in ExpressionAttributeValues
// along witht heir actual value
const { Attributes } = await client.send(new UpdateItemCommand({
TableName: tableName,
Key: marshall(key),
ReturnValues: 'ALL_NEW',
UpdateExpression: `SET ${itemKeys.map((k, index) => `#field${index} = :value${index}`).join(', ')}`,
ExpressionAttributeNames: itemKeys.reduce((accumulator, k, index) => ({ ...accumulator, [`#field${index}`]: k }), {}),
ExpressionAttributeValues: marshall(itemKeys.reduce((accumulator, k, index) => ({ ...accumulator, [`:value${index}`]: item[k] }), {})),
}));
return unmarshall(Attributes);
};