使用 DynamoDBMapper Java AWS 开发工具包进行分页
Posted
技术标签:
【中文标题】使用 DynamoDBMapper Java AWS 开发工具包进行分页【英文标题】:Pagination with DynamoDBMapper Java AWS SDK 【发布时间】:2015-12-23 16:28:19 【问题描述】:来自 API 文档 dynamo db 确实支持用于扫描和查询操作的分页。这里的问题是将当前请求的ExclusiveStartIndex
设置为上一个请求的LastEvaluatedIndex
的值,以获取下一组(逻辑页面)结果。
我正在尝试实现相同的功能,但我使用的是DynamoDBMapper
,它似乎具有更多优势,例如与数据模型的紧密耦合。因此,如果我想执行上述操作,我假设我会执行以下操作:
// Mapping of hashkey of the last item in previous query operation
Map<String, AttributeValue> lastHashKey = ..
DynamoDBQueryExpression expression = new DynamoDBQueryExpression();
...
expression.setExclusiveStartKey();
List<Table> nextPageResults = mapper.query(Table.class, expression);
我希望我的上述理解对于使用 DynamoDBMapper 进行分页是正确的。 其次,我怎么知道我已经达到了结果的终点。如果我使用以下 api,请从文档中获取:
QueryResult result = dynamoDBClient.query((QueryRequest) request);
boolean isEndOfResults = StringUtils.isEmpty(result.getLastEvaluatedKey());
回到使用 DynamoDBMapper,在这种情况下,我如何知道我是否已达到结果的末尾。
【问题讨论】:
【参考方案1】:DynamoDBMapper
有几个不同的选项,具体取决于您想要的方式。
query
- 返回PaginatedQueryList
queryPage
- 返回QueryResultPage
scan
- 返回PaginatedScanList
scanPage
- 返回ScanResultPage
这里的部分是理解方法之间的区别,以及它们返回的对象封装了什么功能。
我会介绍PaginatedScanList
和ScanResultPage
,但这些方法/对象基本上是相互镜像的。
PaginatedScanList
表示以下内容,强调我的:
实现表示 AWS DynamoDB 中扫描结果的 List 接口。 当用户执行需要它们的操作时,会按需加载分页结果。 某些操作,例如 size(),必须获取整个列表,但结果会尽可能地逐页获取。
这表示在您遍历列表时会加载结果。当您浏览第一页时,会自动获取第二页,而无需您明确提出另一个请求。延迟加载结果是默认方法,但如果您调用重载方法并提供具有不同 DynamoDBMapperConfig.PaginationLoadingStrategy
的 DynamoDBMapperConfig
,它可以被覆盖。
这与ScanResultPage
不同。您将获得一页结果,由您自己处理分页。
这是一个快速代码示例,显示了我使用 DynamoDBLocal 对包含 5 个项目的表运行的两种方法的示例用法:
final DynamoDBMapper mapper = new DynamoDBMapper(client);
// Using 'PaginatedScanList'
final DynamoDBScanExpression paginatedScanListExpression = new DynamoDBScanExpression()
.withLimit(limit);
final PaginatedScanList<MyClass> paginatedList = mapper.scan(MyClass.class, paginatedScanListExpression);
paginatedList.forEach(System.out::println);
System.out.println();
// using 'ScanResultPage'
final DynamoDBScanExpression scanPageExpression = new DynamoDBScanExpression()
.withLimit(limit);
do
ScanResultPage<MyClass> scanPage = mapper.scanPage(MyClass.class, scanPageExpression);
scanPage.getResults().forEach(System.out::println);
System.out.println("LastEvaluatedKey=" + scanPage.getLastEvaluatedKey());
scanPageExpression.setExclusiveStartKey(scanPage.getLastEvaluatedKey());
while (scanPageExpression.getExclusiveStartKey() != null);
还有输出:
MyClasshash=2
MyClasshash=1
MyClasshash=3
MyClasshash=0
MyClasshash=4
MyClasshash=2
MyClasshash=1
LastEvaluatedKey=hash=N: 1,
MyClasshash=3
MyClasshash=0
LastEvaluatedKey=hash=N: 0,
MyClasshash=4
LastEvaluatedKey=null
【讨论】:
如果limit
在使用query
时设置为2,仍然返回所有记录。为什么会这样?
@user7 它似乎只返回所有记录,而实际上底层实现(PaginatedQueryList
)正在为您处理分页。查看PaginatedQueryList
的文档。它的行为方式与我在上面发布的关于 scan
的方式相同。基本上,如果你遍历它,它最终会获取所有元素,因为它会自动执行分页调用。
所以withLimit
不申请了?
根据我在执行扫描限制时所读到的内容,并不是指结果数量,而是指允许的吞吐量。
PaginatedQueryList 进行多次调用以获取完整的项目集。该限制用于指定每个请求要获取的项目数。以上是关于使用 DynamoDBMapper Java AWS 开发工具包进行分页的主要内容,如果未能解决你的问题,请参考以下文章
[拓扑排序] aw3696. 构造有向无环图(拓扑排序+memset使用坑点+aw周赛004_3)
angularjs, HighCharts (Aw, Snap!) 崩溃