为什么使用Limit和FilterExpression扫描DynamoDB不会返回符合过滤器要求的项目?

时间:2016-08-04 22:42:31

标签: node.js amazon-web-services amazon-dynamodb

我需要在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定义:

  • 主分区键:用户(号码)
  • 主要排序键:标识符(字符串)
  • INDEX:
    • 索引名称:RemovedIndex
    • 类型:GSI
    • 分区键:已删除(号码)
    • 排序键: -
    • 属性:全部


在上面的代码中,如果我删除Limit参数,DynamoDB将返回符合过滤条件要求的项目。所以,条件还可以。但是当我使用Limit参数进行扫描时,结果为空。

XXXX表有5个项目。只有2个第一个具有Removed属性。当我在没有Limit参数的情况下进行扫描时,DynamoDB会返回没有Removed属性的3个项目。

我做错了什么?

4 个答案:

答案 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,则表示它已扫描或查询了与您的限制匹配的行数。 (结果大小为零,因为它们与过滤器表达式不匹配)