如何使用DynamoDB V2 Enhanced SDK的batchGetItem获取同一分区键所有记录?
问题描述
我们有一个包含Partition Key(分区键)和Sort Key(排序键)的DynamoDB表,多数分区键对应多条记录,需要一次性获取某个分区键下的所有记录。使用V2 Enhanced Java SDK时,尝试用batchGetItem()方法仅指定分区键、忽略排序键来获取对应所有记录,出现报错:The provided key element does not match the schema。若指定排序键,代码能正常获取单条记录,但我们无法提前知晓排序键的值,这种方式不适用。请问是否可以用batchGetItem()实现获取同一分区键的所有记录?
相关代码示例
仅指定分区键的报错代码
import software.amazon.awssdk.services.dynamodb.model.*; List<Integer> keys = List.of(0,1,2,3,4); ReadBatch.Builder<MyRecord> readBatchBuilder = ReadBatch.builder(MyRecord.class); keys.forEach(id -> readBatchBuilder.addGetItem(Key.builder().partitionValue(id).build())); readBatchBuilder.mappedTableResource(table); ReadBatch readBatch = readBatchBuilder.build(); BatchGetResultPageIterable iterable = enhancedClient.batchGetItem(r -> r.addReadBatch(readBatch));
指定排序键的有效代码
import software.amazon.awssdk.services.dynamodb.model.*; List<Integer> keys = List.of(0,1,2,3,4); ReadBatch.Builder<MyRecord> readBatchBuilder = ReadBatch.builder(MyRecord.class); keys.forEach(id -> readBatchBuilder.addGetItem(Key.builder().partitionValue(id).sortValue("VALUE").build())); readBatchBuilder.mappedTableResource(table); ReadBatch readBatch = readBatchBuilder.build(); BatchGetResultPageIterable iterable = enhancedClient.batchGetItem(r -> r.addReadBatch(readBatch));
解决方案
不能用batchGetItem()实现这个需求,原因如下:
batchGetItem()的设计目标是根据**完整主键(分区键+排序键)**批量获取单个条目,它不支持仅通过分区键查询该分区下的所有记录。- 当表存在排序键时,主键是复合结构,必须同时提供分区键和排序键才能唯一定位一条记录。只传入分区键会违反表的schema定义,因此触发
The provided key element does not match the schema错误。
正确的做法是使用**query()方法**,它专门用于查询指定分区键下的所有(或部分)排序键对应的记录。以下是V2 Enhanced SDK的实现示例:
单个分区键查询所有记录
// 查询分区键为0的所有记录 QueryConditional queryConditional = QueryConditional.keyEqualTo(Key.builder() .partitionValue(0) .build()); List<MyRecord> records = table.query(r -> r.conditional(queryConditional)) .items() .stream() .collect(Collectors.toList());
批量处理多个分区键
如果需要一次性处理多个分区键的查询,可以通过循环或并行执行多个query请求:
List<Integer> partitionKeys = List.of(0,1,2,3,4); List<List<MyRecord>> allRecords = new ArrayList<>(); // 串行处理 for (Integer key : partitionKeys) { QueryConditional conditional = QueryConditional.keyEqualTo(Key.builder() .partitionValue(key) .build()); List<MyRecord> partitionRecords = table.query(r -> r.conditional(conditional)) .items() .stream() .collect(Collectors.toList()); allRecords.add(partitionRecords); } // 并行处理(提高效率) List<CompletableFuture<List<MyRecord>>> futures = partitionKeys.stream() .map(key -> CompletableFuture.supplyAsync(() -> { QueryConditional conditional = QueryConditional.keyEqualTo(Key.builder() .partitionValue(key) .build()); return table.query(r -> r.conditional(conditional)) .items() .stream() .collect(Collectors.toList()); })) .collect(Collectors.toList()); // 等待所有请求完成 allRecords = futures.stream() .map(CompletableFuture::join) .collect(Collectors.toList());
内容的提问来源于stack exchange,提问作者Hephaestus
相关产品推荐
相关产品推荐

