Reputation: 520
I'm using DynamoDBMapper from the AWS Java SDK and working with a fairly simple item: it has a string attribute (used as the hash key) and a map attribute.
@DynamoDBTable(tableName = "MyTable")
public class MyItem {
private String myStringAttr;
private Map<String, String> myMapAttr;
@DynamoDBHashKey(attributeName = "MyStringAttribute")
public String getMyKeyAttr() { return myKeyAttr; }
public void setMyKeyAttr(String myKeyAttr) { this.myKeyAttr = myKeyAttr; }
@DynamoDBAttribute(attributeName = "MyMapAttribute")
public Map<String, String> getMyMapAttr() { return myMapAttr; }
public void setMyMapAttr(Map<string, string> myMapAttr) { this.myMapAttr = myMapAttr; }
}
I can read and write my object using the load()
and save()
methods just fine. The issue I'm running into is when I need to update or add a single entry in the map for an existing item in the table. Without knowing the existing entries of the map for said item (and I don't want to perform a load()
each time before I attempt to update or add), the best I seem to be able to do is wipe out the entire map and replace it with the single entry I'm trying to update or add. Is it possible to add/update a single entry to an existing item's map attribute using the DynamoDBMapper?
I've looked at the various options provided by DynamoDBSaveExpression
and DynamoDBMapperConfig
. The closest option I can find is DynamoDBMapperConfig.SaveBehavior.APPEND_SET
, but this is for set type attributes rather than the map type I'm using.
I'm able to achieve this exact use case using the Document API's updateItem()
method along with an UpdateItemSpec
containing an UpdateExpression as shown below. This will add a new entry to the map if the given key doesn't yet exist, or update the value to the one specific if an existing entry does exist, all without touching the other entries in the map. However, I have found the Document API rather cumbersome to work with and would prefer to stick with the DynamoDBMapper
if at all possible.
Table table = dynamoDB.getTable("MyTable");
UpdateItemSpec updateItemSpec = new UpdateItemSpec()
.withPrimaryKey("MyStringAttribute", 1)
.withUpdateExpression("set #mma.#mek = :mev")
.withNameMap(new NameMap()
.with("#mma", "MyMapAttribute")
.with("#mek", "SomeMapEntryKey")
.withValueMap(new ValueMap()
.withString(":mev", "Some map entry value"));
UpdateItemOutcome outcome = table.updateItem(updateItemSpec);
Upvotes: 1
Views: 2967
Reputation: 39226
One possible solution would be:-
1) Get the data from the table "MyTable" using DynamoDBMapper load
2) Add new entries to the map in the object retrieved in step 1 and save that object using DynamoDBMapper with config as mentioned below
DynamoDBMapperConfig dynamoDBMapperConfig = new DynamoDBMapperConfig(SaveBehavior.UPDATE);
I know that this is a two step process. However, when I was in the same situation, I have tried a lot and couldn't find any solution with single direct update for "Map" data type using DynamoDBMapper.
Hope this helps!
Upvotes: 0