我需要在DynamoDB上使用限制和条件进行扫描。
docs说:
在响应中,DynamoDB返回Limit值范围内的所有匹配结果。例如,如果发出限制值为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定义:
在上面的代码中,如果我删除Limit
参数,DynamoDB将返回符合过滤条件要求的项目。所以,条件还可以。但是当我使用Limit
参数进行扫描时,结果为空。
XXXX表有5个项目。只有2个第一个具有Removed
属性。当我在没有Limit
参数的情况下进行扫描时,DynamoDB会返回没有Removed
属性的3个项目。
我做错了什么?
答案 0 :(得分:15)
来自您引用的文档:
如果您还提供FilterExpression值,DynamoDB将返回 项目在前六个中也符合过滤条件
通过组合Limit和FilterExpression,您已告知DynamoDB仅查看表中的前两项,并针对这些项评估FilterExpression。 DynamoDB中的限制可能会令人困惑,因为它与RDBMS中的SQL表达式中的limit
的工作方式不同。
答案 1 :(得分:1)
还遇到了这个问题,我想你只需扫描整个表格最多1 MB
扫描
扫描的结果集限制为每次调用1 MB。您可以使用扫描回复中的LastEvaluatedKey
来检索更多结果。
http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Limits.html
答案 2 :(得分:1)
您可以使用辅助索引获得所需内容。使用经典的RDB示例,客户订单示例:您有一个表用于客户,一个用于订单。 Orders表有一个Key,包括Customer - HASH,Order - RANGE。因此,如果您想获得最新的10个订单,那么没有扫描就无法做到这一点
但是如果您在“Some Constant” - HASH,Date RANGE的订单上创建一个全局二级索引,并查询该索引,他们会查询您想做的事情,只收取与返回的记录有关的RCU 。无需昂贵的扫描。注意,写入会更昂贵,但在大多数情况下,读取次数多于写入次数。
如果你想获得一天大于1000美元的10大订单,那么现在你有了原来的问题。查询将返回最后10个订单,然后过滤掉不到1000美元的订单。
在这种情况下,您可以创建Date-OrderAmount的计算键,并且针对该索引的查询将返回您想要的内容。
它不像SQL那么简单,但您也需要考虑SQL中的访问模式。如果您有大量数据,则需要在SQL中创建索引,否则数据库将很乐意代表您进行表扫描,这会影响性能并增加成本。
请注意,我提出的所有内容都是标准化的,因为只有一个真实来源。您不是在复制数据 - 您只是重新构建它的视图以从DynamoDB获得所需的内容。
请记住,CONSTANT作为HASH的每个分区限制为10GB,因此如果您有大量活动数据,则需要围绕它进行设计。例如,根据您预期的访问模式,您可以使用Customer而不是常量作为HASH。或者使用STream以其他方式组织数据(或子集)。
答案 3 :(得分:-1)
小技巧-迭代直到获得结果
lastEvaluatedKey = null;
do {
if(lastEvaluatedKey != null) {
// query or scan data with last evaluated key
} else {
// query or scan data WITHOUT last evaluated key
}
lastEvaluatedKey == key of last item retrieved
} while(lastEvaluatedKey != null && retrievedResultSize == 0); // == 0 or < yourLimit
如果检索到的项目数为0并且lastEvaluatedKey不为null,则表示它已扫描或查询了与您的限制匹配的行数。 (结果大小为零,因为它们与过滤器表达式不匹配)