You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用DynamoDB增强客户端实现复杂批量读取查询?

使用Java DynamoDB增强客户端实现多分区键+排序键范围查询

问题场景

我正在使用Java版DynamoDB增强客户端,DynamoDB表的分区键为S: product_id(字符串类型),排序键为S: created_date(字符串类型,ISO8601格式)。现有一个List<ProductId>(ProductId为字符串类型),需要获取表中所有满足product_id属于该列表且created_date > someDate的条目。

示例数据

表中原始条目:

[
  {
    "product_id": "aaa",
    "created_date": "2023-04-01T22:57:12.942Z"
  },
  {
    "product_id": "bbb",
    "created_date": "2023-04-02T22:57:12.942Z"
  },
  {
    "product_id": "aaa",
    "created_date": "2023-01-03T22:57:12.942Z"
  },
  {
    "product_id": "ccc",
    "created_date": "2023-04-03T22:57:12.942Z"
  },
  {
    "product_id": "bbb",
    "created_date": "2023-04-01T22:57:12.942Z"
  }
]

期望结果

当List<ProductId>为["aaa", "bbb"],someDate为2023-04-01T22:57:12.942Z时,返回结果:

[
  {
    "product_id": "aaa",
    "created_date": "2023-04-01T22:57:12.942Z"
  },
  {
    "product_id": "bbb",
    "created_date": "2023-04-02T22:57:12.942Z"
  },
  {
    "product_id": "bbb",
    "created_date": "2023-04-01T22:57:12.942Z"
  }
]

实现方案

由于DynamoDB的BatchGetItem仅支持精确匹配主键,无法对排序键做范围筛选,因此需要对列表中的每个product_id单独执行Query请求,再合并结果。以下是具体实现步骤:

1. 定义实体类

用DynamoDB增强客户端的注解标注实体类,映射表结构:

import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSortKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbAttribute;

@DynamoDbBean
public class ProductItem {
    private String productId;
    private String createdDate;

    @DynamoDbPartitionKey
    @DynamoDbAttribute("product_id")
    public String getProductId() {
        return productId;
    }

    public void setProductId(String productId) {
        this.productId = productId;
    }

    @DynamoDbSortKey
    @DynamoDbAttribute("created_date")
    public String getCreatedDate() {
        return createdDate;
    }

    public void setCreatedDate(String createdDate) {
        this.createdDate = createdDate;
    }
}

2. 构建并执行查询

通过增强客户端的DynamoDbTable实例,对每个product_id构建Query请求,设置排序键的范围条件,然后收集所有结果:

import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable;
import software.amazon.awssdk.enhanced.dynamodb.TableSchema;
import software.amazon.awssdk.enhanced.dynamodb.model.QueryConditional;
import software.amazon.awssdk.enhanced.dynamodb.model.QueryEnhancedRequest;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;

import java.util.ArrayList;
import java.util.List;

public class ProductQueryService {
    private final DynamoDbTable<ProductItem> productTable;

    public ProductQueryService(DynamoDbClient dynamoDbClient) {
        DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder()
                .dynamoDbClient(dynamoDbClient)
                .build();
        this.productTable = enhancedClient.table("your-table-name", TableSchema.fromBean(ProductItem.class));
    }

    public List<ProductItem> queryProducts(List<String> productIds, String someDate) {
        List<ProductItem> result = new ArrayList<>();

        for (String productId : productIds) {
            // 构建分区键精确匹配条件
            QueryConditional partitionKeyCond = QueryConditional.keyEqualTo(k -> k.partitionValue(productId));
            
            // 构建排序键范围条件:created_date > someDate
            QueryEnhancedRequest request = QueryEnhancedRequest.builder()
                    .queryConditional(partitionKeyCond)
                    .sortKeyCondition(s -> s.greaterThan(someDate))
                    .build();

            // 执行查询并收集结果,自动处理分页
            productTable.query(request).items().forEach(result::add);
        }

        return result;
    }
}

3. 关键注意事项

  • 日期格式一致性:确保created_date字段存储的是ISO8601格式的字符串(如yyyy-MM-dd'T'HH:mm:ss.SSS'Z'),这样字符串的字典序比较和日期的时间顺序一致,范围筛选结果才正确。
  • 分页处理:单个product_id对应的条目过多时,items()方法会自动遍历所有分页结果,无需额外编码。
  • 性能优化:如果productIds列表过大,建议用CompletableFuture并行执行查询,避免串行请求耗时过长,但需注意控制并发量,避免触发DynamoDB的请求限制。

内容的提问来源于stack exchange,提问作者LEQADA

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 05:55:29