无法更新DynamoDB表的映射列

I am currently developing a skill for Amazon's echo dot which requires the use of persistent data. I ran into an issue when developing a web interface for my skill where I was not able to easily update the mapAttr column of the DynamoDB table used by the skill.

I've been trying to work this out for the last 2 days, I've looked everywhere including the documentation but can't seem to find anything that'll help me.

This is the code I am using:

        $result = $client->updateItem([
            'TableName' => 'rememberThisDBNemo',
            'Key' => [
                'userId' => [ 'S' => $_SESSION['userDataAsk'] ]
            ],
            'ExpressionAttributeNames' => [
                '#attr' => 'mapAttr.ReminderJSON'
            ],
            'ExpressionAttributeValues' => [
                ':val1' => json_encode($value)
            ],
            'UpdateExpression' => 'SET #attr = :val1'
        ]);

I have tried many different things so this might be just absolutely wrong, but nothing that I have found has worked.

The table has 2 columns, userId and mapAttr, userId is a string and mapAttr is a map. Originally I thought it was simply a JSON string but it was not like that as when I tried to update it with a JSON string directly it would stop working when read by Alexa.

I am only trying to update 1 out of the 2 attributes of mapAttr. That is ReminderJSON which is a string.

Any help would be appreciated. Thanks.

Try calling updateItem like this

    $result = $client->updateItem([
        'TableName' => 'rememberThisDBNemo',
        'Key' => [
            'userId' => [ 'S' => $_SESSION['userDataAsk'] ]
        ],
        'ExpressionAttributeNames' => [
            '#mapAttr' => 'mapAttr',
            '#attr' => 'ReminderJSON'
        ],
        'ExpressionAttributeValues' => [
            ':val1' => ['S' => json_encode($value)]
        ],
        'UpdateExpression' => 'SET #mapAttr.#attr = :val1'
    ]);

However, please be aware that in order for this to work, attribute mapAttr must already exist. If it doesn't, you'll get ValidationException saying The document path provided in the update expression is invalid for update...

As a workaround, you may want to add a ConditionExpression => 'attribute_exists(mapAttr)' to your params, catch possible exception, and then perform another update adding a new attribute mapAttr:

  try {
    $result = $client->updateItem([
        'TableName' => 'rememberThisDBNemo',
        'Key' => [
            'userId' => [ 'S' => $_SESSION['userDataAsk'] ]
        ],
        'ExpressionAttributeNames' => [
            '#mapAttr' => 'mapAttr'
            '#attr' => 'ReminderJSON'
        ],
        'ExpressionAttributeValues' => [
            ':val1' => ['S' => json_encode($value)]
        ],
        'UpdateExpression' => 'SET #mapAttr.#attr = :val1'
        'ConditionExpression' => 'attribute_exists(#mapAttr)'
    ]);

  } catch (\Aws\Exception\AwsException $e) {
    if ($e->getAwsErrorCode() == "ConditionalCheckFailedException") {
      $result = $client->updateItem([
          'TableName' => 'rememberThisDBNemo',
          'Key' => [
              'userId' => [ 'S' => $_SESSION['userDataAsk'] ]
          ],
          'ExpressionAttributeNames' => [
              '#mapAttr' => 'mapAttr'
          ],
          'ExpressionAttributeValues' => [
              ':mapValue' => ['M' => ['ReminderJSON' => ['S' => json_encode($value)]]]
          ],
          'UpdateExpression' => 'SET #mapAttr = :mapValue'
          'ConditionExpression' => 'attribute_not_exists(#mapAttr)'
      ]);
    }
  }