Java 使用QuerySpec.withMaxPageSize()时在DynamoDB中分页
我想使用QuerySpec.withMaxPageSize(int-limit)实现分页。我是这样使用它的:Java 使用QuerySpec.withMaxPageSize()时在DynamoDB中分页,java,pagination,amazon-dynamodb,Java,Pagination,Amazon Dynamodb,我想使用QuerySpec.withMaxPageSize(int-limit)实现分页。我是这样使用它的: QuerySpec querySpec = new QuerySpec() .withKeyConditionExpression("id = :v_id") .withValueMap(new ValueMap() .withString(":v_id", "1234")) .withScanIndexForwar
QuerySpec querySpec = new QuerySpec()
.withKeyConditionExpression("id = :v_id")
.withValueMap(new ValueMap()
.withString(":v_id", "1234"))
.withScanIndexForward(false)
.withMaxPageSize(Integer.parseInt(5));
ItemCollection<QueryOutcome>items = table.query(querySpec);
int startPage = 0;
for (Page<Item, QueryOutcome> page : items.pages()) {
System.out.println("Page: " + ++startPage);
Iterator<Item> iterator = page.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
QuerySpec querySpec = new QuerySpec()
.withKeyConditionExpression("id = :v_id")
.withFilterExpression("eventType = :v_eventType")
.withValueMap(new ValueMap()
.withString(":v_id", "1234")
.withString(":v_eventType", "event"))
.withScanIndexForward(false)
.withMaxPageSize(Integer.parseInt(5));
那么结果是完全错误的:
Page: 1
{ Item: {id=1234, timestamp=1489480336243, eventType=starRating} }
{ Item: {id=1234, timestamp=1489476430129, eventType=starRating, }
{ Item: {id=1234, timestamp=1489460649642, eventType=starRating, }
Page: 2
{ Item: {id=1234, timestamp=1489137400014, eventType=starRating} }
Page: 3
{ Item: {id=1234, timestamp=1489137294383, eventType=starRating} }
Page: 4
{ Item: {id=1234, timestamp=1489137046331, eventType=starRating} }
Page: 5
{ Item: {id=1234, timestamp=1489137030983, eventType=starRating} }
{ Item: {id=1234, timestamp=1489137022138, eventType=starRating} }
Page: 6
{ Item: {id=1234, timestamp=1489136930427, eventType=starRating} }
Page: 7
{ Item: {id=1234, timestamp=1489136782467, eventType=starRating} }
{ Item: {id=1234, timestamp=1489136765162, eventType=starRating} }
{ Item: {id=1234, timestamp=1489136669765, eventType=starRating} }
Page: 8
{ Item: {id=1234, timestamp=1489136478857, eventType=starRating} }
{ Item: {id=1234, timestamp=1489136453453, eventType=starRating} }
{ Item: {id=1234, timestamp=1489136435202, eventType=starRating} }
{ Item: {id=1234, timestamp=1489136384098, eventType=starRating} }
Page: 9
{ Item: {id=1234, timestamp=1489136253163, eventType=starRating} }
每一页都有不同的项目。当我添加过滤器表达式时,似乎会出现这个问题。但我不知道为什么。有人知道这件事吗?这里有一段摘录,解释了为什么每页的行数不同:
在响应中,DynamoDB返回
限制值的范围。例如,如果发出查询或扫描
限制值为6且没有筛选器表达式的请求,
DynamoDB返回表中与
请求中指定的关键条件(或仅前六项)
在无过滤器的扫描情况下)。如果您还提供
FilterExpression值,DynamoDB将返回第一个
六个也符合筛选要求(结果数量
返回的值将小于或等于6)
所以基本上,当您在查询中使用FilterExpression和Limit时,DynamoDB从表中最多读取Limit
记录,然后过滤掉与FilterExpression
不匹配的记录
UPD:为了获得每页记录的确切数量,您必须使用更复杂的方法。在获得第一个查询结果后,如果返回的子集包含少于
Limit
项,
将记录保存到缓冲区并继续读取,直到项目总数达到>=限制。如果缓冲区中的记录数超过限制,请丢弃超过限制的记录。
这就是如何获得第一页的确切大小Limit
项(在您的情况下为5项)
要获得第二个页面,可以运行一个新的查询,提供KeyConditionExpression,如
id=:v_id和#timestamp<:timestamp
,并使用上一页最后一条记录的timestamp值作为:timestamp
。同样,您必须多次读取,直到缓冲区中的项目总数变成>=您首选的页面大小。使用相同的方法获取所有后续页面。以下是一段摘录,解释了为什么每页的行数不同:
在响应中,DynamoDB返回
限制值的范围。例如,如果发出查询或扫描
限制值为6且没有筛选器表达式的请求,
DynamoDB返回表中与
请求中指定的关键条件(或仅前六项)
在无过滤器的扫描情况下)。如果您还提供
FilterExpression值,DynamoDB将返回第一个
六个也符合筛选要求(结果数量
返回的值将小于或等于6)
所以基本上,当您在查询中使用FilterExpression和Limit时,DynamoDB从表中最多读取Limit
记录,然后过滤掉与FilterExpression
不匹配的记录
UPD:为了获得每页记录的确切数量,您必须使用更复杂的方法。在获得第一个查询结果后,如果返回的子集包含少于
Limit
项,
将记录保存到缓冲区并继续读取,直到项目总数达到>=限制。如果缓冲区中的记录数超过限制,请丢弃超过限制的记录。
这就是如何获得第一页的确切大小Limit
项(在您的情况下为5项)
要获得第二个页面,可以运行一个新的查询,提供KeyConditionExpression,如
id=:v_id和#timestamp<:timestamp
,并使用上一页最后一条记录的timestamp值作为:timestamp
。同样,您必须多次读取,直到缓冲区中的项目总数变成>=您首选的页面大小。使用相同的方法获取所有后续页面。上述结果有一个错误:“eventType”的值应为“event”。我只是举一个例子说明我的问题。我没有看到任何一页有超过5个项目。是的,我知道答案。因为我使用FilterExpression。因此,结果将首先划分为多个页面,然后根据FilterExpression过滤每个页面中的结果。谢谢@efekctive!如果我使用上面的第二个querySpec
,您知道如何实现分页吗?@xtx给出的解释似乎是合理的。如果我能想到任何其他的事情,我会发布上面的结果有一个错误:“eventType”的值应该是“event”。我只是举一个例子说明我的问题。我没有看到任何一页有超过5个项目。是的,我知道答案。因为我使用FilterExpression。因此,结果将首先划分为多个页面,然后根据FilterExpression过滤每个页面中的结果。谢谢@efekctive!如果我使用上面的第二个querySpec
,您知道如何实现分页吗?@xtx给出的解释似乎是合理的。如果我能想到别的,我会发一封感谢信lot@xtx. 你完全解决了我的问题。另外,如果我想使用FilterExpression,我如何实现分页?Hi@xtx,我认为这个解决方案有点复杂,当我有大量项目时,这将非常缓慢。我想使用LastEvaluatedKey
,但它似乎不支持QuerySpec
或ScanSpec
。QuerySpec和ScanSpec都支持ExclusiveStartKey,这是您从上一个结果传递LastEvaluatedKey值的地方。无论您是否使用和ExclusiveStartKey
,或者使用附加时间戳条件的KeyConditionExpression来开始检索下一页的数据,为了获得每页相同的行数,您需要对每一页发出多个请求