使用 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

这里的部分是理解方法之间的区别,以及它们返回的对象封装了什么功能。

我会介绍PaginatedScanListScanResultPage,但这些方法/对象基本上是相互镜像的。

PaginatedScanList 表示以下内容,强调我的:

实现表示 AWS DynamoDB 中扫描结果的 List 接口。 当用户执行需要它们的操作时,会按需加载分页结果。 某些操作,例如 size(),必须获取整个列表,但结果会尽可能地逐页获取。

这表示在您遍历列表时会加载结果。当您浏览第一页时,会自动获取第二页,而无需您明确提出另一个请求。延迟加载结果是默认方法,但如果您调用重载方法并提供具有不同 DynamoDBMapperConfig.PaginationLoadingStrategyDynamoDBMapperConfig,它可以被覆盖。

这与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)

自动化测试中的AW的分类

java 换包

angularjs, HighCharts (Aw, Snap!) 崩溃

plsql中dbms_aw$_columnlist_t是什么,有什么作用?

[单调栈] aw3780. 构造数组(递推+单调栈+枚举+aw周赛009_3)