DynamoDB:如何创建具有嵌套JSON结构的表?

时间:2014-09-30 10:04:44

标签: amazon-dynamodb

我想在dynamoDB中创建一个具有以下结构的表。

{
    "CartId": 123,
    "UserId": 356,
    "CartItems": [
     {
        "ProductId":100,
        "Quantity": 50
     },
     {
        "ProductId": 121,
        "Quantity": 51
     }
     ]
}

教程和文档中的任何地方都表示我们只能在表格中使用以下类型的属性:

  1. 字符集

  2. 数字集

  3. 二进制集

  4. 我想不出在DynamoDB中存储上述结构的方法。你能帮忙吗?

    我正在使用java的对象映射器Api。如果你还能告诉我如何创建一个可以映射到这个特定表结构的类,那将是很棒的。

6 个答案:

答案 0 :(得分:11)

最简单的方法是使用@DynamoDBDocument

  1. 添加Maven依赖

    <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-java-sdk-dynamodb</artifactId>
            <version>1.11.186</version>
    </dependency>
    
  2. 创建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;
    }
    
  3. 创建存储库

    @EnableScan
    public interface CustomerRepository extends CrudRepository<Customer,String>
    

    然后致电customerRepository.save(customer)。结果将是这样的:

    {
      "firstName": "Test",
      "fooList": [
        {
          "name": "foo"
        },
        {
          "name": "foo2"
        }
      ],
      "id": "e57dd681-8608-4712-a39a-f3e0f31a5e27",
     ]
    }
    

答案 1 :(得分:4)

发布一个旧问题,因为我认为解决方案很容易找到。希望这有助于某人。

步骤1:创建一个反映所需结构的复杂Java对象。

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

步骤2:使用复杂对象更新DynamoDB项目。

我使用辅助方法:

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

然后打电话:

updateAttribute(123, "CartItems", cartItems);

新添加的购物车商品属性显示在DynamoDB中,如:

  "CartItems": [
    {
      "ProductId": 100,
      "Quantity": 50
    },
    {
      "ProductId": 121,
      "Quantity": 51
    }
  ],

我还没有测试一个upsert场景。过去,似乎没有upsert功能:https://forums.aws.amazon.com/thread.jspa?threadID=162907

关于深层嵌套项目的读取:http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.AccessingItemAttributes.html#DocumentPaths

答案 2 :(得分:1)

您可以将JSON作为字符串存储在Dynamodb中。这一切都取决于您想要对数据做什么以及如何检索它。

例如,DynamoDB Java API引入了Marshaller对象,可以将任何Java对象转换为String,因此您可以存储它并从DynamoDB属性自动获取它。

答案 3 :(得分:0)

当询问这个问题时,不确定这些数据类型是否可用(它们很可能不存在)但是现在您使用CartItems的List数据类型,并且每个购物车项目都是Map数据类型。

参考:DynamoDB Data Types

答案 4 :(得分:0)

如果字符串中包含JSON,则只需调用

table.putItem(Item.fromJSON(jsonString));

JSON需要包含分区和排序键的键/值。对于条件看跌期权,请使用

table.putItem(Item.fromJSON(jsonString), conditionString, nameMap, valueMap)

答案 5 :(得分:-5)

从您给出的JSON结构中,我认为您正在尝试将DynamoDB设置为关系数据库,而实际上您应该将DynamoDB视为一个简单的平键值存储。因此,不是像您建议的那样使用表格结构,而是将其展平,并为客户在购物车中的每件商品添加许多行。

例如

Primary hashkey (UserId) | Hash range key (CartId) | ProductId | Qty
356                        123                       100         50
356                        123                       121         51

通过这种方式,您可以通过提供356的主键以及范围键123来获取购物车中的所有项目。这是DynamoDB存储可索引和可​​查询数据的方式。这确实意味着您要存储两个单独的行。

这样的格式有许多优点,特别是它使您能够在ProductId上创建Local Secondary索引,以了解有多少客户将特定产品放入购物车。它还应该可以很容易地看到对象映射器如何使用这个表结构。