使用 DynamoDBMapper Java AWS SDK 进行分页

Pagination with DynamoDBMapper Java AWS SDK

来自 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,在这种情况下我如何知道我是否已达到结果的结尾。

DynamoDBMapper 有几个不同的选项,具体取决于您要走的路。

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

我会复习 PaginatedScanListScanResultPage,但这些 methods/objects 基本上是相互镜像的。

PaginatedScanList 说了以下内容,强调我的:

Implementation of the List interface that represents the results from a scan in AWS DynamoDB. Paginated results are loaded on demand when the user executes an operation that requires them. Some operations, such as size(), must fetch the entire list, but results are lazily fetched page by page when possible.

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

DynamoDBMapperConfig,则可以覆盖它

这与 ScanResultPage 不同。给你一页结果,由你自己处理分页。

这里是快速代码示例,显示了我 运行 使用 DynamoDBLocal table 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);

并且输出:

MyClass{hash=2}
MyClass{hash=1}
MyClass{hash=3}
MyClass{hash=0}
MyClass{hash=4}

MyClass{hash=2}
MyClass{hash=1}
LastEvaluatedKey={hash={N: 1,}}
MyClass{hash=3}
MyClass{hash=0}
LastEvaluatedKey={hash={N: 0,}}
MyClass{hash=4}
LastEvaluatedKey=null