使用嵌套地图更新 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 使用占位符。
我一定是漏掉了一些简单的东西。此测试的目标是在现有 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 forMyMap.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 thatMyMap.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 使用占位符。