在 UpdateExpression 上使用 DELETE 集更新 DynamoDB 记录失败并显示 node.js

Updating DynamoDB record with DELETE Set on UpdateExpression fails with node.js

我正在尝试对 DynamoDB.DocumentClient 实例执行更新调用,使用 AWS SDK 和以下代码片段中的负载:

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])
      }
})...

我收到此错误结果:

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":[...]
}

有趣的是,如果将 operation 更改为 ADD 效果很好。

任何可能有助于理解为什么 ADD 有效而不是 DELETE 的线索 and/or 如何修复 and/or 但与此更新操作兼容的替代方法是高度赞赏!

此处唯一可行的解​​决方法是不使用 DELETE 操作,而是查询该项目,在数组中找到要删除的索引,然后通过 REMOVE 操作将其删除:

在这种情况下,arrayField 包含一个用户数组,我想按用户的电话号码删除。

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;
            });
    }

结果是我没有注意的语义错误。

${operation}ADD 时,UpdateExpressionversion 字段将起作用,因为它是一个数字增量。

${operation}DELETE 时,version 不起作用,因为错误指出它是 Incorrect operand type for operator or function,因为它仅适用于 [=20] =] 根据文档。

错误一开始有点误导,但当我尝试使用其他 SDK 实现时,我最终遇到了同样的错误,然后我尝试关注 UpdateExpression 部分,发现我必须重构为这样的东西才能工作:

// 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])
     }
})

希望以后对其他人有用!