为什么使用Limit和FilterExpression进行DynamoDB扫描不会返回符合过滤器要求的项目?
我需要在DynamoDB上进行限制和条件扫描。为什么使用Limit和FilterExpression进行DynamoDB扫描不会返回符合过滤器要求的项目?
的docs说:
在响应,DynamoDB返回限制值的范围内的所有匹配的结果。例如,如果您发出限值为6且没有过滤器表达式的查询或扫描请求,则DynamoDB会返回表中与请求中指定的关键条件匹配的前六个项目(或者仅返回前六个项目扫描不带过滤器的情况)。如果您还提供FilterExpression值,那么DynamoDB将返回前六个中也与过滤器要求相匹配的项目(返回结果的数量将小于或等于6)。
的代码(的NodeJS):
var params = {
ExpressionAttributeNames: {"#user": "User"},
ExpressionAttributeValues: {":user": parseInt(user.id)},
FilterExpression: "#user = :user and attribute_not_exists(Removed)",
Limit: 2,
TableName: "XXXX"
};
DynamoDB.scan(params, function(err, data) {
if (err) {
dataToSend.message = "Unable to query. Error: " + err.message;
} else if (data.Items.length == 0) {
dataToSend.message = "No results were found.";
} else {
dataToSend.data = data.Items;
console.log(dataToSend);
}
});
表XXXX定义:
- 主分区键:用户(数量)
- 主排序关键字:标识符(字符串)
- INDEX:
- 指数名称:RemovedIndex
- 类型:GSI
- 分区键:删除(号码)
- 排序键: -
- 属性:ALL
在上面的代码中,如果我删除Limit
参数,DynamoDB将返回符合过滤器要求的项目。所以,条件是好的。但是当我用Limit
参数扫描时,结果是空的。
该XXXX表,有5个项目。只有2个第一个具有Removed
属性。当我在没有Limit
参数的情况下扫描时,DynamoDB将返回3个不带Removed
属性的项目。
我做错了什么?
从您引用文档:
如果您同时提供FilterExpression值,DynamoDB将返回 项目在第6也匹配滤波器的要求
通过结合限制和FilterExpression,您已告知DynamoDB仅查看表中的前两项,并针对这些项目评估FilterExpression。 DynamoDB中的限制可能会引起混淆,因为它与RDBMS中的SQL表达式中的limit
不同。
也遇到了这个问题,我想你就只能全表扫描,以1个MB
扫描 结果从扫描设置仅限于每次通话1 MB的最大。您可以使用扫描响应中的LastEvaluatedKey
来检索更多结果。
http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Limits.html
你也许能够得到你所需要的使用辅助指标。使用传统的RDB示例,客户订单示例:客户有一张表,订单有一张。订单表有一个由客户 - 哈希,订单 - 范围组成的密钥。所以如果你想获得最新的10个订单,没有扫描就没有办法做到这一点
但是,如果你创建一个全球二级索引的订单“某些常量” - HASH,日期范围和查询针对该索引,他们的查询会做你想做的事情,并且只收取与返回的记录有关的RCU的费用。不需要昂贵的扫描。请注意,写入操作会更加昂贵,但在大多数情况下,读取操作比写入操作要多得多。
如果您想要获得大于1000美元的一天中的10个最大订单,现在您有您的原始问题。该查询将返回最后10个订单,然后过滤出价值低于1000美元的订单。
在这种情况下,您可以创建Date-OrderAmount的计算密钥,并且针对该索引的查询将返回所需内容。
它不像SQL那么简单,但是您也需要考虑SQL中的访问模式。如果您有大量数据,则需要在SQL中创建索引,否则数据库将很乐意代表您进行表扫描,这会影响性能并提高成本。
请注意,我提出的所有事情都是在只有一个事实根源的意义上归一化的。您没有复制数据 - 您只是重新编写数据视图,以便从DynamoDB获得所需的信息。
请记住,CONSTANT作为HASH的受限于每个分区10GB的限制,因此如果您有大量活动数据,则需要围绕它进行设计。例如,根据您预期的访问模式,您可以使用Customer而不是常量作为HASH。或者使用STreams以其他方式组织数据(或子集)。
谢谢你的回答!我不明白该文件,你向我澄清。你有关于如何在RDBMS中使用'limit'的提示吗? –
对此有一些疑惑:https://github.com/clarkie/dynogels/issues/12这种有用的行为如何?确定扫描,直到你有6个物品与过滤器相匹配,或者你到达表格的最后会更有用? – Clarkie
@Clarkie这很有用,因为它允许您限制扫描操作评估的记录数,这是出于性能原因。仅仅因为它不像RDBMS一样工作并不意味着它没有用处。另外,你对Github的评论关于“对文档所说的一些混淆”似乎对我不正确。文档(正如我在我的回答中引用的)非常清楚。混淆来自那些认为'limit'在DynamoDB中的工作方式与RDBMS中的方式相同,而无需花时间阅读文档。 –