2016-08-04 33 views
5

我需要在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属性的项目。

我做错了什么?

回答

8

从您引用文档:

如果您同时提供FilterExpression值,DynamoDB将返回 项目在第6也匹配滤波器的要求

通过结合限制和FilterExpression,您已告知DynamoDB仅查看表中的前两项,并针对这些项目评估FilterExpression。 DynamoDB中的限制可能会引起混淆,因为它与RDBMS中的SQL表达式中的limit不同。

+0

谢谢你的回答!我不明白该文件,你向我澄清。你有关于如何在RDBMS中使用'limit'的提示吗? –

+1

对此有一些疑惑:https://github.com/clarkie/dynogels/issues/12这种有用的行为如何?确定扫描,直到你有6个物品与过滤器相匹配,或者你到达表格的最后会更有用? – Clarkie

+0

@Clarkie这很有用,因为它允许您限制扫描操作评估的记录数,这是出于性能原因。仅仅因为它不像RDBMS一样工作并不意味着它没有用处。另外,你对Github的评论关于“对文档所说的一些混淆”似乎对我不正确。文档(正如我在我的回答中引用的)非常清楚。混淆来自那些认为'limit'在DynamoDB中的工作方式与RDBMS中的方式相同,而无需花时间阅读文档。 –

1

你也许能够得到你所需要的使用辅助指标。使用传统的RDB示例,客户订单示例:客户有一张表,订单有一张。订单表有一个由客户 - 哈希,订单 - 范围组成的密钥。所以如果你想获得最新的10个订单,没有扫描就没有办法做到这一点

但是,如果你创建一个全球二级索引的订单“某些常量” - HASH,日期范围和查询针对该索引,他们的查询会做你想做的事情,并且只收取与返回的记录有关的RCU的费用。不需要昂贵的扫描。请注意,写入操作会更加昂贵,但在大多数情况下,读取操作比写入操作要多得多。

如果您想要获得大于1000美元的一天中的10个最大订单,现在您有您的原始问题。该查询将返回最后10个订单,然后过滤出价值低于1000美元的订单。

在这种情况下,您可以创建Date-OrderAmount的计算密钥,并且针对该索引的查询将返回所需内容。

它不像SQL那么简单,但是您也需要考虑SQL中的访问模式。如果您有大量数据,则需要在SQL中创建索引,否则数据库将很乐意代表您进行表扫描,这会影响性能并提高成本。

请注意,我提出的所有事情都是在只有一个事实根源的意义上归一化的。您没有复制数据 - 您只是重新编写数据视图,以便从DynamoDB获得所需的信息。

请记住,CONSTANT作为HASH的受限于每个分区10GB的限制,因此如果您有大量活动数据,则需要围绕它进行设计。例如,根据您预期的访问模式,您可以使用Customer而不是常量作为HASH。或者使用STreams以其他方式组织数据(或子集)。

相关问题