问题描述
我有一个名为"product"的DynamoDB表,其全局二级索引位于"userId"上.主键位于"id"上.我正在尝试使用"userID" GSI上的"withExclusiveStartKey"来实现分页查询.但是,当我传递有效的lastId时,出现以下异常:
I have DynamoDB table called "product" with a Global Secondary Index on "userId".Primary Key is on "id".I am trying to implement Querying with pagination using "withExclusiveStartKey" on "userID" GSI.However, I get following exception when I pass a valid lastId:
我在这里做什么错了?
public QueryResultPage<Product> findPaged(String userId,int limit,String lastId) {
DynamoDBMapper mapper = new DynamoDBMapper(dynamoDb);
Map<String, AttributeValue> vals = new HashMap<>();
vals.put(":valUserId", new AttributeValue().withS(userId));
DynamoDBQueryExpression<Product> queryExp = new DynamoDBQueryExpression<Product>()
.withKeyConditionExpression("userId = :valUserId")
.withIndexName(ModelConsts.TBL_PRODUCT_GSI_USERID)
.withExpressionAttributeValues(vals)
.withScanIndexForward(false)
.withConsistentRead(false)
.withLimit(limit);
if (lastId != null) {//paging
Map<String, AttributeValue> exclusiveStartKey = new HashMap<String, AttributeValue>();
exclusiveStartKey.put("id", new AttributeValue().withS(lastId));
queryExp = queryExp.withExclusiveStartKey(exclusiveStartKey);
}
QueryResultPage<Product> result = mapper.queryPage(Product.class, queryExp);
return result;
}
推荐答案
GSI原始表的所有键值都应设置为开始键.如果该表具有分区键和排序键,则应将两个键值都设置为开始键值.
All the key values of the original table of GSI should be set as start key. If the table has partition key and sort key, then both the key values should be set as start key values.
在下面的示例中:-
1) videos
表中的 videoid
作为分区键,而 category
作为排序键
1) The videos
table has videoid
as partition key and category
as sort key
2)GSI的定义是使用 category
作为分区键,而 videoid
作为排序键
2) The GSI is defined with category
as partition key and videoid
as sort key
以下代码通过设置了开始键(即分区键和排序键)的 category
值查询GSI.
The below code queries the GSI by category
value with start key set (i.e. both partition and sort key).
当我不填充分区或排序键时,我可以重现您的错误.
I can reproduce your error when I don't populate the partition or sort key.
示例代码:-
public QueryResultPage<VideoDynamoMappingAdapter> findVideosByCategoryUsingGSIAndMapperWithStartKey(
String category) {
DynamoDBMapper dynamoDBMapper = new DynamoDBMapper(dynamoDBClient);
QueryResultPage<VideoDynamoMappingAdapter> queryResult = null;
Map<String, AttributeValue> vals = new HashMap<>();
vals.put(":val1", new AttributeValue().withS(category));
DynamoDBQueryExpression<VideoDynamoMappingAdapter> queryExp = new DynamoDBQueryExpression<VideoDynamoMappingAdapter>()
.withKeyConditionExpression("category = :val1").withIndexName("VideoCategoryGsi")
.withExpressionAttributeValues(vals).withScanIndexForward(false).withConsistentRead(false).withLimit(1);
Map<String, AttributeValue> startKey = new HashMap<>();
startKey.put("videoid", new AttributeValue().withS("2"));
startKey.put("category", new AttributeValue().withS("Thriller"));
queryExp.setExclusiveStartKey(startKey);
queryResult = dynamoDBMapper.queryPage(VideoDynamoMappingAdapter.class, queryExp);
System.out.println("Result size ===>" + queryResult.getResults().size());
System.out.println("Last evaluated key ===>" + queryResult.getLastEvaluatedKey());
for (VideoDynamoMappingAdapter videoDynamoMappingAdapter : queryResult.getResults()) {
System.out.println("Video data ===>" + videoDynamoMappingAdapter.toString());
}
return queryResult;
}
这篇关于DynamoDB:使用"withExclusiveStartKey"进行分页;在全球二级指数上的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!