10

从API文档中,dynamo db确实支持扫描和查询操作的分页。这里的要点是将当前请求的ExclusiveStartIndex设置为先前请求的LastEvaluatedIndex的值,以获得结果的下一组(逻辑页面)。分页与DynamoDBMapper Java AWS SDK

我试图实现相同的功能,但我使用的是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,我怎么能知道我是否已经达到在这种情况下的结果结束。

回答

22

对于DynamoDBMapper,您有几个不同的选项,具体取决于您想要的方式。

的部分是理解的区别方法以及它们返回的对象的功能封装。

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

PaginatedScanList说下文中,重点煤矿:

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

这就是说,在遍历列表时加载结果。当你通过第一页时,第二页会自动提取,而你不得不明确地提出另一个请求。延迟加载结果是默认方法,但如果您调用重载方法并提供DynamoDBMapperConfig和其他DynamoDBMapperConfig.PaginationLoadingStrategy,则可以覆盖该方法。

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

和输出:

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 
+0

如果'limit'是在使用'query'时设置为2,它仍然返回所有记录。这是为什么? – user7

+1

@ user7实际上,底层实现('PaginatedQueryList')正在为您处理分页时,它只显示它正在返回所有记录。查看['PaginatedQueryList']的文档(https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodbv2/datamodeling/PaginatedQueryList.html)。它的行为与我上面发布'scan'相同。基本上,如果迭代它,它最终将获取所有元素,因为它会自动执行分页调用。 – mkobit

+0

那么'withLimit'不适用于它? – user7