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

问题描述 投票:8回答:5

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

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

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

  1. 字符串集
  2. 一组数字
  3. 二进制集

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

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

amazon-dynamodb
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索引,以了解有多少客户将特定产品放入购物车。它还应该可以很容易地看到对象映射器如何使用此表结构。


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

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


1
投票

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

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


0
投票

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

参考:DynamoDB Data Types

© www.soinside.com 2019 - 2024. All rights reserved.