2014-09-30 106 views
3

我想在dynamoDB中创建一个具有以下结构的表。DynamoDB:如何创建一个嵌套JSON结构的表?

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

无处不在的教程和文件,它说,我们只能有下表中的属性类型:

  1. 组字符串

  2. 组数字的

  3. 一套二进制

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

我使用java的对象映射器Api。如果你也可以告诉我如何创建一个可以映射到这个特定表结构的类,那将是非常好的。

回答

-4

从您提供的JSON结构中,我认为您正在尝试使DynamoDB像关系数据库一样,当时您应该将DynamoDB看作简单的平面键值存储。所以,而不是像你建议的表结构,我会把它压平,并且对于客户在购物车中的每件商品都有许多行。

例如

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

通过这种方式,你可以通过提供的356主键获得一个购物车的所有项目,具有范围键123.这是存储可转位和可查询数据的DynamoDB方式。这确实意味着您要存储两个单独的行,但是。

像这样的格式有很多优点,特别是它使您能够在ProductId上创建本地二级索引,以找出有多少客户将特定产品放入购物车。它也应该很容易看出对象映射器如何与这个表结构一起工作。

+0

嘿非常感谢,你的建议解决了我的问题:)。我现在使用你指定的格式。另外,我的印象是HashKey应该是唯一的。感谢澄清。 – Amit 2014-10-01 23:57:31

+0

相对于您的总数据集,Hashkey应该是唯一的。如果你只有五个用户,但你有数百万行,你将遭受性能损失。对于这个特定的用例,主哈希键是非唯一的。如果感兴趣,您可以阅读更多关于Amazon DynamoDB如何对数据进行性能分区的内容。 – kurtzbot 2014-10-02 15:19:28

+6

这个答案是错误的。 DynamoDB表不能包含具有非唯一主键的项目,无论是简单(仅分区键)还是复合(分区键和排序键)。 *分区密钥=散列密钥;排序键=范围键 – golem 2016-12-05 01:33:38

1

您可以将JSON作为字符串存储在Dynamodb中。这完全取决于您想要如何处理数据以及如何检索数据。

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

+0

我们怎样才能做到这一点? – Amit 2014-10-01 00:05:08

+0

你说DynamoDB需要一组字符串,但它也可以保存字符串。你使用哪种SDK /编程语言? – 2014-10-01 06:12:13

+0

我正在使用Java – Amit 2014-10-01 06:36:24

0

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

参考:DynamoDB Data Types

2

发布到一个老问题,因为我不认为解决的办法也很容易找到。希望这可以帮助某人。

第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

4

简单的方法是使用@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", 
    ] 
    } 
    
+0

嗨,当我们使用这个解决方案时,如果我们向内部类添加新字段会发生什么,它们会出现在Dynamo数据库中吗? – Bhargav 2017-12-07 09:10:19

+0

是的,它会在那里 – sendon1982 2017-12-08 03:45:19