Java 如何更新 AWS DynamoDB 文档 API 上的地图或列表?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30265355/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to update a Map or a List on AWS DynamoDB document API?
提问by Roy Fox
The new AWS DynamoDB document APIallows 2 new data types that correspond directly to the underlying JSON representation: Map (aka JSON object) and List (aka JSON array).
新的AWS DynamoDB 文档 API允许直接对应于底层 JSON 表示的 2 种新数据类型:Map(又名 JSON 对象)和 List(又名 JSON 数组)。
However, I can't find a way to update attributes of these data types without completely overwriting them. In contrast, a Number attribute can be updated by ADDing another number, so in Java you can do something like:
但是,我找不到一种方法来更新这些数据类型的属性而不完全覆盖它们。相反,可以通过添加另一个数字来更新 Number 属性,因此在 Java 中您可以执行以下操作:
new AttributeUpdate("Some numeric attribute").addNumeric(17);
Similarly you can addElementsto an attribute of a Set data type. (In the old API you would use AttributeAction.ADD for both purposes.)
同样,您可以向 Set 数据类型的属性添加元素。(在旧 API 中,您可以将 AttributeAction.ADD 用于这两个目的。)
But for a Map or a List, it seems you must update the previous value locally, then PUT it instead of that value, for example in Java:
但是对于 Map 或 List,您似乎必须在本地更新先前的值,然后将其代替该值,例如在 Java 中:
List<String> list = item.getList("Some list attribute");
list.add("new element");
new AttributeUpdate("Some list attribute").put(list);
This is much less readable, and under some circumstances much less efficient.
这是可读性低得多,并且在某些情况下效率低得多。
So my questions are:
所以我的问题是:
Is there a way to update an attribute of a Map or a List data type without overwriting the previous value? For example, to add an element to a List, or to put an element in a Map?
How would you implement it using the Java API?
Do you know of plans to support this in the future?
有没有办法在不覆盖以前的值的情况下更新 Map 或 List 数据类型的属性?例如,将一个元素添加到 List 中,或者将一个元素放入 Map 中?
您将如何使用 Java API 实现它?
你知道未来支持这个的计划吗?
采纳答案by Ben Schwartz
Please take a look at UpdateExpression in the UpdateItem API
请看一下UpdateItem API中的UpdateExpression
For example given an item with a list:
例如给定一个带有列表的项目:
{
"hashkey": {"S" : "my_key"},
"my_list" : {"L":
[{"N":"3"},{"N":"7"} ]
}
You can update the list with code like the following:
您可以使用如下代码更新列表:
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);`
You can also append to the list by reversing the order of the arguments in the list_append expression.
您还可以通过颠倒 list_append 表达式中参数的顺序来追加到列表中。
An expression like: SET user.address.zipcode = :zip
would address a JSON map element combined with expression attribute values {":zip" : {"N":"12345"}}
像这样的表达式:SET user.address.zipcode = :zip
将处理与表达式属性值结合的 JSON 映射元素{":zip" : {"N":"12345"}}
回答by Ivan Gonzalez
Base on DynamoDB examples, this also work (scala)
基于 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)
回答by Muhammad Soliman
A generic function to add or update a key/value pairs. attribute updateColumn
should be of type map.
添加或更新键/值对的通用函数。属性updateColumn
应该是映射类型。
Update tableName
attribute name should be passed as attributeName
under key:value
pairs where primaryKey = primaryKeyValue
更新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;
}