Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DynamoDB: How can I create a table with nested JSON structure?

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.

like image 222
Amit Avatar asked Sep 30 '14 10:09

Amit


People also ask

Does DynamoDB support nested objects?

A high-level representation of a DynamoDB nested attribute name that can be used in various situations where the API requires or accepts a nested attribute name. The nested attributes are represented by a list of strings where each element corresponds to a nesting level.

Can we store JSON in DynamoDB?

You can store a JSON document as an attribute in a DynamoDB table. To do this, use the withJSON method of Item . This method parses the JSON document and maps each element to a native DynamoDB data type.

How do I add a table to DynamoDB?

In Amazon DynamoDB, you can use either the DynamoDB API, or PartiQL, a SQL-compatible query language, to add an item to a table. With the DynamoDB API, you use the PutItem operation to add an item to a table. The primary key for this table consists of Artist and SongTitle. You must specify values for these attributes.


2 Answers

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"
}
like image 102
sendon1982 Avatar answered Sep 16 '22 16:09

sendon1982


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

like image 43
Laura Avatar answered Sep 20 '22 16:09

Laura