4

我正在使用 AWS 托管 API 与 API Gateway 和 DynamoDB 直接集成。

我现在正在尝试为我的应用程序添加分页功能,但我很难 100% 地实现它。我面临的问题是当我向后扫描时,我会给你一个例子来更好地理解这个问题。

想象一下,我有一个包含 20 个项目和一个页面大小为 5 的列表。

  1. 当我查询我的表时,第一个查询将返回1, 2, 3, 4, 5. 预期行为!
  2. 当我查询我的表时,将第五个元素中的 lastEvaluatedKey 传递给它,它返回6, 7, 8, 9, 10. 预期的行为。
  3. 现在,当我使用 flag 进行查询时,我的问题就出现了ScanIndexForward=false。这意味着我不想继续前进。相反,我想要lastEvaluatedKey. 问题是,如果我使用lastEvaluatedKey从上次查询中检索到的内容,而不是类似5, 4, 3, 2, 1,我有4, 3, 2, 1.

如果需要,将跳过来自lastEvaluatedKey或调用它的元素。head

如果您想象在一个表格中的正常行为,您单击next pageprevious page,这意味着当您转到第二页并返回第一页时,您将只得到 4 个项目,而不是一个,因为提议的情景。

最后,我尝试了相同的查询,AWS CLI结果是一样的。在与支持人员聊天后,他们确认这是预期的行为。

我只是想知道人们如何看待这种情况,因为我知道亚马逊在生产中使用它,所以应该有办法做到这一点。

4

1 回答 1

2

要了解您看到的行为,您需要了解最初的目的LastEvaluatedKey不是以您想要使用的方式对查询中间的某个位置进行随机访问 - 而是在查询停止后恢复查询在页面边界处。考虑到这一点,当ScanIndexForward=false它假设它正在继续一个正在进行的反向查询时;因此,如果您通过LastEvaluatedKey=5它假定先前返回的序列是 10、9、8、7、6、5(最后返回的项目是 5) - 现在将继续为 4、3、2、1。正如您所指出的那样。

如果出于您的目的您还需要“5”项,您可以在单独的请求中单独阅读该项。它不会花费您更多,因为亚马逊会根据读取的商品大小向您收费——在同一个查询中返回多个商品时,它并不便宜。如果您并行执行读取和查询,延迟也不会增加。

更新:

正如查尔斯在下面的评论中指出的那样,对于短项目和短页面,额外的 GetItem 请求“5”实际上会让您花费另一个 RCU,这可能很重要,所以这不是一个好主意。

所以还有另一种选择,根本不使用LastEvaluatedKey。相反,QueryKeyConditionExpression不仅可以指定所需的分区键,还可以指定一系列排序键。您可以指定范围“sort <= 5”,这将获取排序 <= 5 - 包括 5 的项目的最后一页(当 ScanIndexForward=false 时)。我认为这确实是比我提出的更好的解决方案上面,因为它不会浪费额外的 RCU。

于 2019-10-24T08:08:28.643 回答