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

如何在.NET Core Lambda中获取AWS DynamoDB某列的最大值?

问题:DynamoDB Query操作报错“必须指定KeyConditions或KeyConditionExpression参数”

我在部署为Lambda的.NET Core应用中,想要获取DynamoDB表中CustomerId列的最大值,参考文档编写代码后,运行时抛出如下错误:

错误信息

Amazon.DynamoDBv2.AmazonDynamoDBException: Either the KeyConditions or KeyConditionExpression parameter must be specified in the request.
 ---> Amazon.Runtime.Internal.HttpErrorResponseException: Exception of type 'Amazon.Runtime.Internal.HttpErrorResponseException' was thrown.

现有代码

var maxIdRequest = new QueryRequest
{
    TableName = "Customers",
    IndexName = "CustomerIdIndex",
    Select = "SPECIFIC_ATTRIBUTES",
    AttributesToGet = { "Id" },
    ScanIndexForward = false,
    Limit = 1,
};

var result = await _dynamoDBClient.QueryAsync(maxIdRequest);
var attributeList = result.Items[0];

DynamoDB表及GSI的Terraform配置

resource "aws_dynamodb_table" "customer-dynamodb-table" {
  name           = var.table_name
  billing_mode = "PAY_PER_REQUEST"
  hash_key       = "Id"

  attribute {
    name = "Id"
    type = "N"
  }

  attribute {
    name = "CustomerId"
    type = "N"
  }

  global_secondary_index {
    name               = "CustomerIdIndex"
    hash_key           = "Id"
    range_key = "CustomerId"
    write_capacity     = 10
    read_capacity      = 10
    projection_type    = "INCLUDE"
    non_key_attributes = ["Id"]
  }
}

问题原因及解决方案

1. 报错直接原因

DynamoDB的Query操作强制要求指定哈希键(Hash Key)的匹配条件——Query是针对主键或索引的哈希键做精确匹配,再对范围键进行排序/过滤。你的GSI CustomerIdIndex哈希键是Id,但代码中未提供Id的条件,因此触发报错。

2. 需求适配问题

当前GSI设计无法满足“全局获取CustomerId最大值”的需求:该GSI以Id为哈希键,数据会被分片存储,每个分片内的CustomerId是排序的,但无法跨分片获取全局最大值。

3. 最优解决方案:调整GSI设计

创建一个单分片GSI(哈希键用固定值),让所有数据路由到同一个分片,再通过Query倒序取第一条得到最大值。

修改后的Terraform配置

resource "aws_dynamodb_table" "customer-dynamodb-table" {
  name           = var.table_name
  billing_mode = "PAY_PER_REQUEST"
  hash_key       = "Id"

  attribute {
    name = "Id"
    type = "N"
  }

  attribute {
    name = "CustomerId"
    type = "N"
  }

  # 新增用于全局获取CustomerId最大值的GSI
  global_secondary_index {
    name               = "GlobalCustomerIdIndex"
    hash_key           = "GlobalPartition" # 固定哈希键
    range_key          = "CustomerId"
    write_capacity     = 10
    read_capacity      = 10
    projection_type    = "INCLUDE"
    non_key_attributes = ["CustomerId"]
  }
}

注意:需要给每个Customer条目添加GlobalPartition属性,值固定为统一内容(比如"1"),确保所有数据进入同一个GSI分片。

修改后的.NET代码

var maxIdRequest = new QueryRequest
{
    TableName = "Customers",
    IndexName = "GlobalCustomerIdIndex",
    Select = "SPECIFIC_ATTRIBUTES",
    AttributesToGet = { "CustomerId" },
    ScanIndexForward = false, // 倒序排列,最大值排在首位
    Limit = 1,
    // 指定固定哈希键的匹配条件
    KeyConditionExpression = "GlobalPartition = :partitionVal",
    ExpressionAttributeValues = new Dictionary<string, AttributeValue>
    {
        { ":partitionVal", new AttributeValue { S = "1" } } // 对应GSI的哈希键值
    }
};

var result = await _dynamoDBClient.QueryAsync(maxIdRequest);
if (result.Items.Count > 0)
{
    var maxCustomerId = result.Items[0]["CustomerId"].N;
    // 处理获取到的最大值
}

4. 备选方案:使用Scan操作(不推荐)

如果无法修改表结构,可通过Scan遍历全表获取最大值,但该方法性能差、成本高,仅适合小数据量场景:

var scanRequest = new ScanRequest
{
    TableName = "Customers",
    Select = "SPECIFIC_ATTRIBUTES",
    AttributesToGet = { "CustomerId" },
};

var result = await _dynamoDBClient.ScanAsync(scanRequest);
decimal maxCustomerId = 0;
foreach (var item in result.Items)
{
    if (decimal.TryParse(item["CustomerId"].N, out var currentId) && currentId > maxCustomerId)
    {
        maxCustomerId = currentId;
    }
}
// 处理最大值

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 18:40:40