21

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:

  1. Set of Strings

  2. Set of Numbers

  3. 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.

7 Answers 7

23

Simplest way is use @DynamoDBDocument

  1. Add Maven dependency
<dependency>
        <groupId>com.amazonaws</groupId>
        <artifactId>aws-java-sdk-dynamodb</artifactId>
        <version>1.11.186</version>
</dependency>
  1. Create POJO
@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;
}
  1. Create a repository
@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"
}
Sign up to request clarification or add additional context in comments.

3 Comments

Hi, when we use this solution, what happens if we add new fields to the inner class, will they be present in dynamo db?
Yes, it is going to be there
How to map generic json in pojo using @DynamoDBDocument..like i have key,value pair with different value object.
5

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"
                }
            }
        }]
    }]
}

As stored in Dynamo DB-Snap

1 Comment

@DynamoDBAttribute - this is not applicable to fields... have you tried this before ?
4

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

Comments

2

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)

Comments

1

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.

3 Comments

How can we achieve this?
You said DynamoDB wants sets of strings, but it can also save strings. Which SDK/programming language are you using?
i have json file with nested objects, i'm trying to import it in my table created in aws dynamo, i'm running aws dynamodb put-item but failed to import data, any help?
0

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

Comments

0

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;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.