From the API docs dynamo db does support pagination for scan and query operations. The catch here is to set the ExclusiveStartIndex
of current request to the value of the LastEvaluatedIndex
of previous request to get next set (logical page) of results.
从API文档中,dynamo db确实支持扫描和查询操作的分页。这里的问题是将当前请求的ExclusiveStartIndex设置为先前请求的LastEvaluatedIndex的值,以获得结果的下一组(逻辑页)。
I'm trying to implement the same but I'm using DynamoDBMapper
, which seems to have lot more advantages like tight coupling with data models. So if I wanted to do the above, I'm assuming I would do something like below:
我正在尝试实现相同但我正在使用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);
I hope my above understanding is correct on paginating using DynamoDBMapper. Secondly, how would I know that I've reached the end of results. From the docs if I use the following api:
我希望我的上述理解在使用DynamoDBMapper进行分页时是正确的。其次,我怎么知道我已经达到了结果。如果我使用以下api,请从文档中:
QueryResult result = dynamoDBClient.query((QueryRequest) request);
boolean isEndOfResults = StringUtils.isEmpty(result.getLastEvaluatedKey());
Coming back to using DynamoDBMapper, how can I know if I've reached end of results in this case.
回到使用DynamoDBMapper,我怎么知道在这种情况下我是否达到了结果的结尾。
1 个解决方案
#1
24
You have a couple different options with the DynamoDBMapper
, depending on which way you want go.
DynamoDBMapper有几个不同的选项,具体取决于你想要的方式。
-
query
- returns aPaginatedQueryList
- query - 返回PaginatedQueryList
-
queryPage
- returns aQueryResultPage
- queryPage - 返回QueryResultPage
-
scan
- returns aPaginatedScanList
- scan - 返回PaginatedScanList
-
scanPage
- returns aScanResultPage
- scanPage - 返回ScanResultPage
The part here is understanding the difference between the methods, and what functionality their returned objects encapsulate.
这里的部分是理解方法之间的区别,以及它们返回的对象封装的功能。
I'll go over PaginatedScanList
and ScanResultPage
, but these methods/objects basically mirror each other.
我将介绍PaginatedScanList和ScanResultPage,但这些方法/对象基本上是相互镜像的。
The PaginatedScanList
says the following, emphasis mine:
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.
List接口的实现,表示AWS DynamoDB中扫描的结果。当用户执行需要它们的操作时,按需加载分页结果。某些操作(例如size())必须获取整个列表,但是在可能的情况下逐页延迟获取结果。
This says that results are loaded as you iterate through the list. When you get through the first page, the second page is automatically fetched with out you having to explicitly make another request. Lazy loading the results is the default method, but it can be overridden if you call the overloaded methods and supply a DynamoDBMapperConfig
with a different DynamoDBMapperConfig.PaginationLoadingStrategy
.
这表示在迭代列表时会加载结果。当您浏览第一页时,将自动获取第二页,而您必须明确地发出另一个请求。延迟加载结果是默认方法,但是如果调用重载方法并使用不同的DynamoDBMapperConfig.PaginationLoadingStrategy提供DynamoDBMapperConfig,则可以覆盖它。
This is different from the ScanResultPage
. You are given a page of results, and it is up to do deal with the pagination yourself.
这与ScanResultPage不同。您将获得一页结果,并且您可以自己处理分页。
Here is quick code sample showing an example usage of both methods that I ran with a table of 5 items using DynamoDBLocal:
下面是快速代码示例,显示了我使用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);
And the output:
并输出:
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
#1
24
You have a couple different options with the DynamoDBMapper
, depending on which way you want go.
DynamoDBMapper有几个不同的选项,具体取决于你想要的方式。
-
query
- returns aPaginatedQueryList
- query - 返回PaginatedQueryList
-
queryPage
- returns aQueryResultPage
- queryPage - 返回QueryResultPage
-
scan
- returns aPaginatedScanList
- scan - 返回PaginatedScanList
-
scanPage
- returns aScanResultPage
- scanPage - 返回ScanResultPage
The part here is understanding the difference between the methods, and what functionality their returned objects encapsulate.
这里的部分是理解方法之间的区别,以及它们返回的对象封装的功能。
I'll go over PaginatedScanList
and ScanResultPage
, but these methods/objects basically mirror each other.
我将介绍PaginatedScanList和ScanResultPage,但这些方法/对象基本上是相互镜像的。
The PaginatedScanList
says the following, emphasis mine:
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.
List接口的实现,表示AWS DynamoDB中扫描的结果。当用户执行需要它们的操作时,按需加载分页结果。某些操作(例如size())必须获取整个列表,但是在可能的情况下逐页延迟获取结果。
This says that results are loaded as you iterate through the list. When you get through the first page, the second page is automatically fetched with out you having to explicitly make another request. Lazy loading the results is the default method, but it can be overridden if you call the overloaded methods and supply a DynamoDBMapperConfig
with a different DynamoDBMapperConfig.PaginationLoadingStrategy
.
这表示在迭代列表时会加载结果。当您浏览第一页时,将自动获取第二页,而您必须明确地发出另一个请求。延迟加载结果是默认方法,但是如果调用重载方法并使用不同的DynamoDBMapperConfig.PaginationLoadingStrategy提供DynamoDBMapperConfig,则可以覆盖它。
This is different from the ScanResultPage
. You are given a page of results, and it is up to do deal with the pagination yourself.
这与ScanResultPage不同。您将获得一页结果,并且您可以自己处理分页。
Here is quick code sample showing an example usage of both methods that I ran with a table of 5 items using DynamoDBLocal:
下面是快速代码示例,显示了我使用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);
And the output:
并输出:
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