使用"查询"查询DynamoDB项目

时间:2018-02-08 12:13:54

标签: amazon-dynamodb

我们说我有一个DynamoDB表,例如

TableName: 'Items'
Key: {Hash: 'Id'}

每个项目都有一个名称,属于一个客户,所以我也有一个索引

{Hash: CustomerId, Range:Name}

我们说我有这些数据:

Id    CustomerId    Name
1     18            Milk
2     42            Orange juice
3     42            Apple juice
4     42            Coffee
5     54            Tomato juice

现在,我想查询特定客户的所有项目,并过滤部分名称的结果(本质上是搜索操作)。例如,给我所有属于客户42的物品,其中包含" juice"以它的名字(橙汁和苹果汁是预期的结果)。

如果我查询CustomerId = '42' AND contains(Name, 'juice'),我会收到错误消息,指出KeyConditionExpression不支持contains。我可以理解这个限制,因为contains表示必须扫描所有项目(在给定的哈希键内),但是,你可以查询所有 CustomerId = '42'的项目也是该哈希内的完整扫描,因此我不确定我是否理解此限制。像begins_with这样的东西得到了正常的支持(这很有意义,因为很容易从排序的集合中快速返回一个子集)。

无论如何,所以我诅咒了一下,然后说我只是使用FilterExpression而是与浪费的RCU:s一起生活,导致查询

KeyConditionExpression: CustomerId = '42'
FilterExpression: contains(Name, 'juice')

但现在我收到一条错误消息,说我不允许在我的FilterExpression中包含主键属性("请改用KeyConditionExpression!")。

这让我陷入了两难境地。我无法使用contains中的KeyCondition进行过滤,因此无法在我Name的{​​{1}}内进行过滤。我是否必须仅在CustomerId 上创建一个单独的索引才能实现我的用例,或者还有其他方法可以解决这个问题吗?

5 个答案:

答案 0 :(得分:1)

对于这样的事情,你应该考虑复合键 GSI重载的概念,并重新设计你的表以适应你的访问模式。

根据https://aws.amazon.com/blogs/database/choosing-the-right-dynamodb-partition-key/

  

使用复合属性。尝试将多个属性组合到一起   如果符合您的访问模式,则形成唯一密钥。例如,   考虑使用customerid + productid + countrycode作为的订单表   partition key和order_date作为排序键。

所以你可以做一些事情,比如设计你的表以保持索引为customerid#name

答案 1 :(得分:0)

DynamoDB仅允许在关键条件下使用begin_with,因此不支持contains,但是对于您而言,可以按如下分层顺序排列rangeKey: CustomerId Name 18 Milk 42 juice.Orange 42 juice.Apple 42 Coffee 54 Tomato juice

因此查询的结构可以像  KeyConditionExpression: CustomerId = '42' AND Name BEGINS_WITH 'juice'

答案 2 :(得分:0)

对于DynamoDB,我认为最好的解决方案是以您以后打算读取的形状存储数据。

如果发现自己需要复杂的读取查询,则可能陷入了期望DynamoDB像RDBMS那样的陷阱,事实并非如此。在 write 上转换和整形数据,使读取保持简单。

答案 3 :(得分:0)

此查询的行为类似于在关系数据库中的查询

database.scan() 
     .filterExpression('begins_with(#name ,:name) or begins_with(#someno,:name)') 
    .expressionAttributeNames({ "#name": "name","#someno":"someno"}) 
    .expressionAttributeValues({ ":name" : data}) 
    .exec().promise(); 

答案 4 :(得分:0)

只需复制属性并对其应用过滤器