pagination - DynamoDB:在全局二级索引上使用“withExclusiveStartKey”进行分页

标签 pagination amazon amazon-dynamodb

我有一个名为“ product”的DynamoDB表,其全局二级索引位于“ userId”上。主键位于“ id”上。
我正在尝试使用“ userID” GSI上的“ withExclusiveStartKey”来实现分页查询。
但是,当我传递有效的lastId时,出现以下异常:


独占启动键的大小必须与表的键模式相同
(服务:AmazonDynamoDBv2;状态代码:400;错误代码:
ValidationException;要求编号:
822db97e-04a3-4c36-8c72-6008e2693679)


我在这里做错了什么?

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原始表的所有键值都应设置为开始键。如果表具有分区键和排序键,则两个键值都应设置为开始键值。

在以下示例中:

1)videos表具有videoid作为分区键和category作为排序键

2)GSI定义为category作为分区键,而videoid作为排序键

以下代码通过设置了开始键(即分区键和排序键)的category值查询GSI。

当我不填充分区或排序键时,我可以重现您的错误。

示例代码:-

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;

}

关于pagination - DynamoDB:在全局二级索引上使用“withExclusiveStartKey”进行分页,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40988397/

相关文章:

amazon-web-services - 如何设计关键模式以使每个应用程序只有一个 DynamoDB 表?

php - PHP 分页的错误

javascript - 刷新 jqGrid 不会保存启用无限滚动的当前页面位置

php - CakePHP 模型 : COUNT(*) in Containable

android - Amazon IAP在 Release模式下不起作用

amazon - 如何将多个产品发送到亚马逊商城?

java - 如何在运行时从 DynamoDB 获取排序结果

'WHERE (col1, col2) < (val1, val2)' 的 SQL 语法术语

Amazon EC2 代码部署没有主机成功

java - 使用 spring-data-dynamodb 自定义 DynamoDBMapper