0

我正在编写一个查询来查找其用户名以给定前缀开头的所有用户。我只希望查询最多返回 10 个项目。我现在的查询是

User.scan('username')
  .beginsWith(req.query.prefix)
  .limit(req.query.limit)
  .exec((err, users) => {
    ...
  });

在更仔细地阅读了 dynamoose文档.limit()之后,我意识到限制是它检查的表条目数,而不是它返回的条目数。因此,如果我有 10 个用户,其中 5 个用户的用户名以“m”开头,则类似的查询query: { prefix: 'm', limit: 5}可能会返回 0 个项目。

我知道我可以查询数据库中的所有用户,然后只返回其中的一些,但它是不可扩展的。如何查询数据库,以便在找到 10 个匹配项时停止查看表?

4

1 回答 1

3

在 DynamoDB 中无法直接做您想做的事。正如您所发现的,“限制”选项表示要检查的项目数量 - 而不是要退回的项目数量。当需要出现这种情况时,通常会选择一些合理的页面大小,例如 1000 个项目或(如果您没有指定数字,则默认为 1MB 项目),然后一次读取这样的页面大小。如果第一页已经有超过您想要的 5 个项目,则停止扫描(并且不需要扫描整个表格)。如果第一页只导致一个匹配的项目被退回,您继续阅读其他页面 - 直到您找到总共 5 个项目。

如果您好奇为什么 DynamoDB 没有直接请求“5 个匹配项”的选项,想象一下如果整个数据库的匹配项少于 5 个会发生什么情况。DynamoDB 需要在返回任何内容之前扫描整个表以查找前 5 个项目。如果这需要一个小时,客户将整整一个小时都不会收到任何结果!数据库客户端通常不会以这种方式工作,并且它们会在一个小时过去之前超时。更重要的是,如果服务器在这个小时内重新启动,工作就会丢失并且无法恢复。因此,使用 DynamoDB 的 API,服务器仅读取 1MB(或其他)数据块,并且在每个块之后,服务器向客户端返回“还没有数据”的答案 - 客户端需要恢复扫描。有一些开销,

最后,关于您的用例的另一条评论:全表扫描,就像您正在做的那样,非常昂贵 - 无论是在时间上还是在成本上。如果您有一个包含 100 万个条目的表,并且期望扫描仅产生 5 个条目,那么您将支付读取 100 万个条目以获得仅 5 个条目的费用。如果这些查询很常见,您可能需要重新考虑您的数据模型典型的查询将只需要读取一项 - 或最多只查询一个分区 - 而不是全表扫描。

于 2019-12-11T13:29:07.000 回答