1

I'm trying to perform a update call to a DynamoDB.DocumentClient instance using AWS SDK with the payload on the code snippet below:

const AWS = require('aws-sdk')
const DynamoDB = new AWS.DynamoDB.DocumentClient()
...

const TableName = 'MyTable'
const Key = { PK: 'MyPK', SK: 'MySK' }
const operation = 'DELETE'
const myId = 'abcde'
const currentRecord = await DynamoDB.get({TableName, Key)

DynamoDB.update({
      TableName,
      Key,
      UpdateExpression: `
        ${operation} myIds :valuesToModify,
        version :incrementVersionBy
      `,
      ConditionExpression: `version = :version`,
      ExpressionAttributeValues: {
        ":version": currentRecord.version,
        ":incrementVersionBy": 1,
        ":valuesToModify": DynamoDB.createSet([myId])
      }
})...

I get this error as result:

ERROR Invoke Error 
{
  "errorType":"Error",
  "errorMessage":"ValidationException: Invalid UpdateExpression: Incorrect operand type for operator or function;
   operator: DELETE, operand type: NUMBER, typeSet: ALLOWED_FOR_DELETE_OPERAND",
  "stack":[...]
}

Interestingly, if operation is changed to ADD it works well.

Any clues that could be helpful to understand why ADD works and not DELETE and/or how to fix and/or yet alternative approaches compatible with this update operation are highly appreciated!

2 Answers 2

2

The only workaround possible here is not to use a DELETE operation, instead, you gotta query the item, find the index in the array you wish to delete, and remove it a REMOVE operation:

like in this case, arrayField contains an array of Users, and I want to delete by user's phoneNumber.

const dataStore = await dynamodb.get(queryParams).promise();
    let i=0; //save the index
    for(i = 0; i < dataStore.Item.myTable.length; i++){
      if(dataStore.Item.arrayField[i].phone === phoneNumber)
      {
        break;
      }
    }
    if(i < dataStore.Item.arrayField.length){
        const updateStoreParams = {
            TableName: tableName,
            Key: storeTableKey,
            UpdateExpression: `REMOVE arrayField[${i}]`,
        }
        await dynamodb.update(updateStoreParams).promise().catch((err) => {
            console.log(err); 
            throw err;
            });
    }
Sign up to request clarification or add additional context in comments.

1 Comment

thanks for pointing that. I am posting below the actual solution that I've found! Keep Rocking!
2

It ended up being a semantic error I didn't pay attention to.

When ${operation} was ADD the version field of the UpdateExpression would work because it is a numeric increment.

When ${operation} was DELETE, the version didn't work because, as the error states it was Incorrect operand type for operator or function as it will only work for Removing Elements From a Set as per the docs.

The error was a bit misleading at first but when I tried to implement with other SDK I ended up with the same error then I tried to focus within the UpdateExpression part and found that I had to refactor to something like this in order to it to work:

// Notice below that I inject ADD if operation is DELETE and a comma otherwise
DynamoDB.update({
      TableName,
      Key,
      UpdateExpression: `
        ${operation} socketIds :valuesToModify
        ${operation == 'DELETE' ? 'ADD' : ','} version :incrementVersionBy
      `,
      ConditionExpression: `version = :version`,
      ExpressionAttributeValues: {
        ':version': channelRecord.version,
        ':incrementVersionBy': 1,
        ':valuesToModify': DynamoDB.createSet([socketId])
     }
})

Hopefully it will become useful to others in the future!

1 Comment

It did ! Thank you very much, I was realy confused with updating Sets of string

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.