Reputation: 569
I want to create a table in dynamoDB with below structure.
{
"CartId": 123,
"UserId": 356,
"CartItems": [
{
"ProductId": 100,
"Quantity": 50
},
{
"ProductId": 121,
"Quantity": 51
}
]
}
Everywhere in tutorials and documents it says that we can only have below type of attributes in the table:
Set of Strings
Set of Numbers
Set of Binary
I can't think of a way to store above structure in DynamoDB. Could you please help out?
I am using object mapper Api of java. It would be great if you can also tell me how can I create a class which can be mapped to this particular table structure.
Upvotes: 21
Views: 53109
Reputation: 2426
The following is the annotated way of doing it in V2
(Equivalent of @DynamoDBDocument). For more information check their GitHub Issue Page.
@DynamoDbBean
public class Cart {
private String cartId;
private String userId;
private List<CartItem> cartItems;
}
@DynamoDbBean
public class CartItem {
private String productId;
private Integer quantity;
}
Upvotes: 0
Reputation: 3361
If you have the JSON in a string, you can simply call
table.putItem(Item.fromJSON(jsonString));
The JSON needs to contain keys/values for the partition and sort key. For a conditional put, use
table.putItem(Item.fromJSON(jsonString), conditionString, nameMap, valueMap)
Upvotes: 2
Reputation: 11234
Simplest way is use @DynamoDBDocument
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-dynamodb</artifactId>
<version>1.11.186</version>
</dependency>
@DynamoDBTable(tableName = "Customer")
public class Customer
{
@DynamoDBHashKey
@DynamoDBAutoGeneratedKey
private String id;
private String firstName;
private List<Foo> fooList;
}
@DynamoDBDocument
public static class Foo {
private String name;
}
@EnableScan
public interface CustomerRepository extends CrudRepository<Customer,String>
Then call customerRepository.save(customer)
. The result will be like this:
{
"firstName": "Test",
"fooList": [
{
"name": "foo"
},
{
"name": "foo2"
}
],
"id": "e57dd681-8608-4712-a39a-f3e0f31a5e27"
}
Upvotes: 23
Reputation: 545
Posting to an old question because I did not think the solution was easy to find. Hope this helps someone.
Step 1: Create a complex Java object that mirrors the structure desired.
List<HashMap<String, Integer>> cartItems = new ArrayList<HashMap<String, Integer>>();
HashMap<String, Integer> item1 = new HashMap<String, Integer>();
item1.put("ProductId", 100);
item1.put("Quantity", 50);
cartItems.add(item1);
HashMap<String, Integer> item2 = new HashMap<String, Integer>();
item2.put("ProductId", 121);
item2.put("Quantity", 51);
cartItems.add(item2);
Step 2: Update DynamoDB item with the complex object.
I use a helper method:
private void updateAttribute(int id, String newAttribute, Object newValue){
Map<String, Object> newValues = new HashMap<String, Object>();
newValues.put(":value", newValue);
UpdateItemSpec updateItemSpec = new UpdateItemSpec()
.withPrimaryKey("id", id)
.withUpdateExpression("set " + newAttribute + " = :value")
.withValueMap(newValues);
siteTable.updateItem(updateItemSpec);
}
and then call thus:
updateAttribute(123, "CartItems", cartItems);
The newly added cart items attribute displays in DynamoDB like:
{
"CartItems": [
{
"ProductId": 100,
"Quantity": 50
},
{
"ProductId": 121,
"Quantity": 51
}
]
}
I have not tested an upsert scenario. In the past, upsert functionality did not seem to be present: https://forums.aws.amazon.com/thread.jspa?threadID=162907
Regarding reads of deeply nested items: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.AccessingItemAttributes.html#DocumentPaths
Upvotes: 4
Reputation: 492
Bit Late to the party but would like to share this. I was able to store a deep nested Json Doc by defining the column attribute as below in my Java Entity.
@DynamoDBAttribute
@DynamoDBTypeConvertedJson
private List<Map<String,Object>> pageData;
Input Json:
{
"userId": 359628,
"platform": "learn-web",
"inactive_duration": 0,
"total_time": 15,
"device_type": "web",
"page_data": [{
"page_details": {
"page_type": "segmentView",
"time": 15,
"segment_id": 65590,
"session_id": 13140,
"module_id": 4363
},
"items": [{
"type": "component",
"id": 267307,
"sub_type": "video",
"time": 10,
"metadata": {
"lastPlaybackRate": 1,
"currentTime": 0,
"isLocked": false,
"video": {
"videoType": "BRIGHTCOVE",
"viewingTime": 156,
"videoSize": 7120441,
"url": "5378655747001",
"URL": "5378655747001"
}
}
}]
}]
}
Upvotes: 5
Reputation: 1930
Not sure if these data types were available when this question was asked (there is a good chance that they were not) but these days you'd use the List datatype for the CartItems
and each cart item would be of Map datatype.
Reference: DynamoDB Data Types
Upvotes: 0
Reputation: 10052
You can store JSONs in Dynamodb as Strings. It all depends on what you want to do with the data and how to retrieve it.
The DynamoDB Java API for instance, introduces Marshaller objects that transforms any Java object into a String so you can store it and fetch it automagically from a DynamoDB attribute.
Upvotes: 1