新的AWS DynamoDB document API允许2个直接对应于底层JSON表示的新数据类型:Map(又名JSON对象)和List(又称JSON数组)。
但是,我找不到更新这些数据类型属性的方法,而不会完全覆盖它们。相反,可以通过添加另一个数字来更新Number属性,因此在Java中您可以执行以下操作:
new AttributeUpdate("Some numeric attribute").addNumeric(17);
同样,您可以addElements到Set数据类型的属性。 (在旧的API中,您将使用AttributeAction.ADD用于两种目的。)
但对于Map或List,似乎必须在本地更新先前的值,然后将其PUT而不是该值,例如在Java中:
List<String> list = item.getList("Some list attribute");
list.add("new element");
new AttributeUpdate("Some list attribute").put(list);
这种可读性低得多,在某些情况下效率低得多。
所以我的问题是:
有没有办法更新Map或List数据类型的属性而不覆盖以前的值?例如,要将元素添加到List中,还是将元素放入Map?
您将如何使用Java API实现它?
您知道将来支持此计划吗?
答案 0 :(得分:12)
例如,给定一个带有列表的项目:
{
"hashkey": {"S" : "my_key"},
"my_list" : {"L":
[{"N":"3"},{"N":"7"} ]
}
您可以使用以下代码更新列表:
UpdateItemRequest request = new UpdateItemRequest();
request.setTableName("myTableName");
request.setKey(Collections.singletonMap("hashkey",
new AttributeValue().withS("my_key")));
request.setUpdateExpression("list_append(:prepend_value, my_list)");
request.setExpressionAttributeValues(
Collections.singletonMap(":prepend_value",
new AttributeValue().withN("1"))
);
dynamodb.updateItem(request);`
您还可以通过颠倒list_append表达式中参数的顺序来附加到列表中。
像SET user.address.zipcode = :zip
这样的表达式将解决与表达式属性值{":zip" : {"N":"12345"}}
结合的JSON地图元素
答案 1 :(得分:6)
基于DynamoDB示例,这也适用(scala)
val updateItemSpec:UpdateItemSpec = new UpdateItemSpec()
.withPrimaryKey("hashkey", my_key)
.withUpdateExpression("set my_list = list_append(:prepend_value, my_list)")
.withValueMap(new ValueMap()
.withList(":prepend_value", "1"))
.withReturnValues(ReturnValue.UPDATED_NEW)
println("Updating the item...")
val outcome: UpdateItemOutcome = table.updateItem(updateItemSpec)
println("UpdateItem succeeded:\n" + outcome.getItem.toJSONPretty)
答案 2 :(得分:0)
添加或更新键/值对的通用功能。属性updateColumn
的类型应为map。
更新tableName
属性名称应在attributeName
对下作为key:value
传递,其中primaryKey = primaryKeyValue
public boolean insertKeyValue(String tableName, String primaryKey, String
primaryKeyValue, String attributeName, String newKey, String newValue) {
//Configuration to connect to DynamoDB
Table table = dynamoDB.getTable(tableName);
boolean insertAppendStatus = false;
try {
//Updates when map is already exist in the table
UpdateItemSpec updateItemSpec = new UpdateItemSpec()
.withPrimaryKey(primaryKey, primaryKeyValue)
.withReturnValues(ReturnValue.ALL_NEW)
.withUpdateExpression("set #columnName." + newKey + " = :columnValue")
.withNameMap(new NameMap().with("#columnName", attributeName))
.withValueMap(new ValueMap().with(":columnValue", newValue))
.withConditionExpression("attribute_exists("+ attributeName +")");
table.updateItem(updateItemSpec);
insertAppendStatus = true;
//Add map column when it's not exist in the table
} catch (ConditionalCheckFailedException e) {
HashMap<String, String> map = new HashMap<>();
map.put(newKey, newValue);
UpdateItemSpec updateItemSpec = new UpdateItemSpec()
.withPrimaryKey(primaryKey,primaryKeyValue)
.withReturnValues(ReturnValue.ALL_NEW)
.withUpdateExpression("set #columnName = :m")
.withNameMap(new NameMap().with("#columnName", attributeName))
.withValueMap(new ValueMap().withMap(":m", map));
table.updateItem(updateItemSpec);
insertAppendStatus = true;
} catch(Exception e) {
e.printStackTrace();
}
return insertAppendStatus;
}