我正在编写查询以查找其用户名以给定前缀开头的所有用户。我只希望查询返回最多10个项目。我现在的查询是
User.scan('username')
.beginsWith(req.query.prefix)
.limit(req.query.limit)
.exec((err, users) => {
...
});
在更仔细地阅读了.limit()
的动态docs之后,我意识到限制在于它检查的表条目的数量,而不是返回的条目的数量。因此,如果我有10个用户,其中5个用户名以'm'开头,则类似query: { prefix: 'm', limit: 5}
之类的查询可能会返回0个项目。
我知道我可以查询数据库中的所有用户,然后只返回其中一些用户,但是它不可扩展。 我如何查询数据库,以便在找到10个匹配项后才停止准确浏览表?
答案 0 :(得分:2)
在DynamoDB中无法直接执行所需的操作。正如您所发现的,“限制”选项指出要检查的项目数量,而不是要退回的项目。出现这种需要时,通常要做的是选择一些合理的页面大小,例如1000个项目或(如果未指定数字,则为默认值)1MB的项目,然后一次读取此类页面大小。如果第一页已包含超过5个所需数目的项目,则停止扫描(无需扫描整个表)。如果第一页仅返回一个匹配的项目,则继续阅读其他页面-直到找到总共5个项目。
如果您好奇DynamoDB为什么没有选择直接要求“ 5个匹配项”的选项,请想象一下,如果整个数据库少于5个匹配项会发生什么。 DynamoDB需要先扫描整个表以查找前5个项目,然后再返回任何内容。如果这需要一个小时,则客户将不会在一个小时内收到任何结果!数据库客户端通常无法以这种方式工作,并且它们会在超时之前超时。更重要的是,如果服务器在这一小时内重新启动,则工作将丢失并且无法恢复。因此,使用DynamoDB的API,服务器仅读取1MB(或任何其他大小)的数据块,在每个数据块之后,服务器将向客户端返回“尚无数据”的答案-客户端需要恢复扫描。有一些开销,但是却不多(大概扫描1MB数据的工作和成本比发送请求要多),并且避免了上述所有问题。
最后,关于用例的另一条评论:就像您所做的那样,全表扫描非常昂贵-在时间和成本上。如果您有一个包含100万个条目的表,并且期望扫描仅产生5个项目,那么您将要花100万条读取100个条目才能得到5个条目。如果这些查询很常见,那么您可能需要重新考虑数据模型,因此典型的查询将只需要读取一项-或最多只查询一个分区-而无需全表扫描。