Amazon dynamodb 使用“查询DynamoDB项目”;包括「;

Amazon dynamodb 使用“查询DynamoDB项目”;包括「;,amazon-dynamodb,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

假设我有一个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且名称中包含“果汁”的项目(橙汁和苹果汁是预期结果)

如果我查询
CustomerId='42'并包含(Name,'juice')
我将得到一个错误,说明
KeyConditionExpression
不支持
contains
。我可以理解这个限制,因为
包含
意味着必须扫描所有项目(在给定的散列键内),但是,您可以使用
CustomerId='42'
查询所有项目,这也是该散列中的完全扫描,所以我不确定是否理解这个限制。像
开头这样的事情也像预期的那样得到支持(这很有意义,因为很容易从排序集快速返回子集)

不管怎么说,我诅咒了一点,说我将只使用FilterExpression来代替,并使用浪费的RCU:s,从而产生一个带有

KeyConditionExpression: CustomerId = '42'
FilterExpression: contains(Name, 'juice')
但是现在我得到一个错误,说我不允许在我的FilterExpression中包含主键属性(“改用KeyConditionExpression!”)


这让我有些进退两难。我无法在我的
KeyCondition
中使用
contains
进行筛选,也无法在我的
FilterExpression中使用
Name
进行筛选。为了实现我的用例,我是否必须创建一个单独的索引,或者有其他的方法来解决这个问题吗?

< P>对于这样的东西,你应该考虑组合键和GSI重载的概念,并重新设计你的表来适应你的访问模式。< /P> 依照

使用复合属性。尝试将多个属性组合到 如果符合您的访问模式,则形成唯一密钥。例如 考虑使用Cuffer-ID+CudiTiD+国家代码的订单表 分区键和订单日期作为排序键


因此,您可以做一些事情,例如将表设计为包含
customerid\35name
索引,DynamoDB仅允许在关键字条件下使用begin\u,因此不支持contains,但对于您的情况,可以按分层顺序排列rangeKey,如:

客户ID名称
18牛奶
42.橙汁
42.苹果汁
42咖啡
54番茄汁

因此,查询的结构可以如下所示
KeyConditionExpression:CustomerId='42',名称以'juice'开头

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


如果您发现自己需要复杂的读取查询,那么您可能会陷入期望DynamoDB像RDBMS一样工作的陷阱,而事实并非如此。在写操作中转换和塑造数据,使读操作保持简单。

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

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

只需复制属性并在其上应用过滤器即可

谢谢,但不确定这有何帮助。使用contains的唯一方法似乎是在filter表达式中,filter表达式只能对非键进行操作。如果我将customerId和name组合成一个字符串并将其用作散列键,则无法查询属于特定客户的所有项目,并且仍然无法使用contains。我误解了吗?多么令人沮丧,多么有趣!创建一个全新的索引将非常昂贵。您最好复制Name属性(一个名为NameKey,另一个名为Name)。然后,您可以在非键名称字段上使用FilterExpression,就像第二次尝试时一样。还是垃圾,但是便宜点。谢谢斯图。我确实想到了,但感觉。。像你说的垃圾。不过,这可能是最好的妥协。如果能得到aws的官方回复,那就太酷了,我可能也会把帖子复制到aws论坛上。你是如何最终解决这个问题的,因为我现在面临着同样的问题已经有一段时间了,但如果我的记忆正确的话,我最终做了客户端过滤,因为我每个客户的数据集都相当小。谢谢,这是一个有趣的方法。如果您需要查询的基本上是类别之类的东西,那么这可能会起作用。然而,在我的特定用例中,数据更加复杂,例如查找具有部分URI:s的项等,因此不可能按层次重新排列它。不确定您是否阅读了问题。我知道查询是如何工作的,谢谢,但是我在DynamoDB中遇到了一个限制,因为KeyConditionExpression不支持contains。我不知道你的回答是怎么说的对不起伙计我的错