使用嵌套地图更新 DynamoDB 项目的正确示例

Proper example of updating a DynamoDB item with nested map

我一定是漏掉了一些简单的东西。此测试的目标是在现有 Map 中设置新元素。下面的 PHP 测试函数可以很好地更新项目,但它没有将 person 属性(映射)的中间初始值设置为 "T",而是创建了一个名为 "person.mi" 的新顶级属性并将其设置为 "T".

docs for Document Paths 指定访问地图元素的点符号,所以....我不知道我错过了什么。

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

有人看到我哪里错了吗?谢谢

那是因为点被认为是属性名称的一部分。您应该使用 2 个表达式属性名称。来自 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

即使在阅读了文档之后,我仍然对这种情况感到困惑。这是一个实际的代码示例:

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

原始代码与我的代码之间的区别仅在于 UpdateExpression 和 ExpressionAttributeNames。

请注意,虽然我为 person 使用了占位符,但没有为 mi 使用占位符。