假设我有一个 DynamoDB 表,例如
TableName: 'Items'
Key: {Hash: 'Id'}
Run Code Online (Sandbox Code Playgroud)
每个项目都有一个名称并属于一个客户,所以我也有一个索引
{Hash: CustomerId, Range:Name}
Run Code Online (Sandbox Code Playgroud)
假设我有这个数据:
Id CustomerId Name
1 18 Milk
2 42 Orange juice
3 42 Apple juice
4 42 Coffee
5 54 Tomato juice
Run Code Online (Sandbox Code Playgroud)
现在,我想查询特定客户的所有项目并过滤部分名称的结果(本质上是搜索操作)。例如,给我属于客户 42 名称中包含“果汁”的所有项目(橙汁和苹果汁是预期结果)。
如果我查询CustomerId = '42' AND contains(Name, 'juice')我会得到一个错误,KeyConditionExpression说不支持contains. 我可以理解这个限制,因为这contains意味着必须扫描所有项目(在给定的散列键内),但是,好吧,你可以查询在该散列中也是完整扫描的所有项目CustomerId = '42',所以我不确定我理解这个限制。像begins_with预期的那样支持之类的东西(这是有道理的,因为很容易从排序集中快速返回一个子集)。
无论如何,所以我有点诅咒并说我将只使用 FilterExpression 并与浪费的 RCU:s 一起生活,从而导致查询
KeyConditionExpression: CustomerId = '42'
FilterExpression: contains(Name, 'juice')
Run Code Online (Sandbox Code Playgroud)
但是现在我收到一条错误消息,说我不允许在我的 FilterExpression 中包含主键属性(“改用 KeyConditionExpression!”)。
这让我有些进退两难。我无法contains在我的中过滤,KeyCondition也无法Name在我的FilterExpression. 我是否应该只在 CustomerId 上创建一个单独的索引才能实现我的用例,还是有其他方法可以解决这个问题......?
小智 11
DynamoDB仅允许begin_with()关键条件。因此contains()不支持,但对于您的情况,可以按分层顺序排列 rangeKey,如下所示:
CustomerId Name
18 Milk
42 juice.Orange
42 juice.Apple
42 Coffee
54 Tomato juice
Run Code Online (Sandbox Code Playgroud)
所以查询的结构可以是这样的
KeyConditionExpression: CustomerId = '42' AND Name BEGINS_WITH 'juice'
Run Code Online (Sandbox Code Playgroud)
笔记:
contains()似乎是在过滤表达式中,并且过滤表达式只能对非键进行操作。Llo*_*oyd 11
对于 DynamoDB,我认为最好的解决方案是以您以后打算阅读的形状存储数据。
如果您发现自己需要复杂的读取查询,您可能会陷入期望 DynamoDB 表现得像 RDBMS 的陷阱,而事实并非如此。在写入时转换和整形您的数据,保持读取简单。
对于这样的东西,您应该考虑复合键和GSI 重载的概念,并重新设计您的表以适应您的访问模式。
根据https://aws.amazon.com/blogs/database/choosing-the-right-dynamodb-partition-key/
使用复合属性。如果符合您的访问模式,请尝试组合多个属性来形成唯一的键。例如,考虑一个订单表,其中 customerid+productid+countrycode 作为分区键,order_date 作为排序键。
所以你可以做一些事情,比如设计你的表来保存索引customerid#name
| 归档时间: |
|
| 查看次数: |
18257 次 |
| 最近记录: |