Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to update a Map or a List on AWS DynamoDB document API?

The new AWS DynamoDB document API allows 2 new data types that correspond directly to the underlying JSON representation: Map (aka JSON object) and List (aka JSON array).

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:

new AttributeUpdate("Some numeric attribute").addNumeric(17);

Similarly you can addElements to an attribute of a Set data type. (In the old API you would use AttributeAction.ADD for both purposes.)

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:

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:

  1. 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?

  2. How would you implement it using the Java API?

  3. Do you know of plans to support this in the future?

like image 802
Roy Fox Avatar asked May 15 '15 17:05

Roy Fox


People also ask

How do I update a DynamoDB item?

To update an existing item in an Amazon DynamoDB table, you use the UpdateItem operation. You must provide the key of the item that you want to update. You must also provide an update expression, indicating the attributes that you want to modify and the values that you want to assign to them.

Does DynamoDB support map?

Maps are ideal for storing JSON documents in DynamoDB. The following example shows a map that contains a string, a number, and a nested list that contains another map.

Can you update partition key value in DynamoDB?

Is it possible to change partition key in DynamoDB? No. Once the table is setup, you cannot modify its Key Schema. You can only provision a new table, move data there, and then remove the first table.


2 Answers

Please take a look at UpdateExpression in the UpdateItem API

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.

An expression like: SET user.address.zipcode = :zip would address a JSON map element combined with expression attribute values {":zip" : {"N":"12345"}}

like image 163
Ben Schwartz Avatar answered Sep 16 '22 14:09

Ben Schwartz


Base on DynamoDB examples, this also work (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)
like image 32
Ivan Gonzalez Avatar answered Sep 18 '22 14:09

Ivan Gonzalez