Geek Stocks Geek Stocks - 1 year ago 422
PHP Question

Proper example of updating a DynamoDB item with nested map

I must be missing something simple here. The goal of this test is to set a new element in an existing Map. The following PHP test function works fine to update the item, but instead of setting the person attribute's (a Map) middle initial value to "T", it creates a new top level attribute called "person.mi" and sets it to "T".

The docs for Document Paths specify dot notation for accessing Map elements, so....I don't know what I am missing.

public function Z() {

$ddb = DynamoDbClient::factory(array('region' => 'us-east-1')); // EC2 role security

try {
$response = $ddb->updateItem(array(
"TableName" => "test",
"Key" => array("id" => array("N" => 1)),
"UpdateExpression" => "SET #fieldName = :value",
"ExpressionAttributeNames" => array("#fieldName" => "person.mi"),
"ExpressionAttributeValues" => array(":value" => array("S" => "T"))
} catch (Exception $e) {
throw new DDBException("Call to TestDDB->Z failed: " . $e->getMessage());

Anyone see where I am going wrong? Thanks.

Answer Source

That is because the dot is thought to be a part of the attribute name. You should use 2 expression attribute names. From the documentation:

But what if you decided to use an expression attribute name instead? For example, what would happen if you were to define #mmmk as a substitute for MyMap.MyKey? DynamoDB would return an empty result, instead of the expected string. This is because DynamoDB interprets a dot in an expression attribute value as a character within an attribute's name. When DynamoDB evaluates the expression attribute name #mmmk, it determines that MyMap.MyKey refers to a scalar attribute—which is not what was intended.

The correct approach would be to define two expression attribute names, one for each element in the document path:

  • #mm — MyMap

  • #mk — MyKey

You could then use the following projection expression:

  • #mm.#mk