node.jsamazon-web-servicesamazon-dynamodbdynamodb-queriesamazon-dynamodb-local

update attributes in a dynamodb record


I am trying to update my existing record in my dynamodb table. Like below I have an Item in my table

let params = {
   TableName: proces.env.dynamoDbTable,
   Item: {
      productId: "id",
      att1: val1,
      att2: val2
      }
 }

I want to perform an update. I am using the aws dynamodb sdk's update method and passing it params like below

let aws = require('aws-sdk');
 let dbb = new aws.DynamoDb.DocumentClient();
 let params = {
  TableName: process.env.tableName,
  Key: {productID}
  ExpressionAttributeNames: { "#updatedAt" : "updatedAt" }
  ExpressionAttributeValues: {":u":moment().unix(), ":val1" : a, ":val2": b}
  UpdateExpression: "SET att1 = :val1, att2: val2, #updatedAt: :u"
 }
// a, b are passed as argument to function and are optional
dbb.update(params).promise()

When an argument goes missing the dynamo raises ExpressionAttributeValue missing exception and I know it is straight. Is there a way I can update my Item with the attributes provided


Solution

  • Unfortunately dynamodb does not make this easy. But you can use some fancy js to create the params object dynamically:

      // for some object `attrs` we find which keys we need to update
      const keys = Object.keys(attrs);
      const values = Object.values(attrs);
    
      // get a list of key names and value names to match the dynamodb syntax
      const attributeKeyNames = keys.map((k) => '#key_' + k);
      const attributeValueNames = keys.map((k) => ':val_' + k);
    
      // create individual expressions for each attribute that needs to be updated
      const expressions = attributeValueNames.map((attr, i) => {
        return `${attributeKeyNames[i]} = ${attr}`;
      });
    
      // add the SET keyword to the beginning of the string
      // and join all the expressions with a comma
      const UpdateExpression = 'SET ' + expressions.join(', ');
    
      // I use `zipObject()` from lodash https://lodash.com/docs/4.17.15#zipObject
      // it makes an object map from two arrays where the first is the keys and
      // the second is the values
      const ExpressionAttributeValues = _.zipObject(attributeValueNames, values);
      const ExpressionAttributeNames = _.zipObject(attributeKeyNames, keys);
    
      // now you have all the params
      const params = {
        TableName,
        Key: {
          uuid,
        },
        UpdateExpression,
        ExpressionAttributeValues,
        ExpressionAttributeNames,
      };