5

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.

2 Answers 2

2

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
Sign up to request clarification or add additional context in comments.

2 Comments

However, this ceases to be an issue if attribute names are inserted directly into the update expression rather than being bound to it, so "UpdateExpression" => "SET person.mi = :value" would recognise that "mi" is an attribute for "person" in the way that the OP had intended.
@petercoles True in this case, but I tend to favor using placeholders. There are a quite a few reserved words that I don't want to look up every time I want to use an expression. A few common ones being ID, NAME, and GROUP, which will all require you to use expressions anyways!
0

Even after reading the documentation, I had trouble with this case. Here is an actual code sample:

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.mi = :value",
            "ExpressionAttributeNames" => array("#fieldName" => "person"),
            "ExpressionAttributeValues" => array(":value" => array("S" => "T"))
        ));
    } catch (Exception $e) {
        throw new DDBException("Call to TestDDB->Z failed: " . $e->getMessage());
    }
}

The difference between the original code and mine is in the UpdateExpression and ExpressionAttributeNames only.

Note that while I am using a placeholder for person, I am not using a placeholder for mi.

Comments

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.