AWS SDK Java DynamoDB - 使用表达式属性名称查询 - 表达式中使用的表达式属性值未定义

AWS SDK Java DynamoDB - Query with Expression Attribute Name - An expression attribute value used in expression is not defined

类似于:I cannot query my dynamodb table from aws lambda due to wrong filterexpression? and

我正在尝试编写一种查询 DynamoDB tables 的方法,使用 Java 中分区键/排序键的部分匹配。

我尝试访问的 DynamoDB table 有一个分区键“Type”(我知道是 DynamoDB 中的受限关键字,但不是我的选择)和一个​​排序键“Id”。我知道“类型”但不知道完整的 Id,所以我使用 AWS SDK 2.x 源代码研究了查询方法并实现如下所示:

DynamoDBClient dynamoDbClient = DynamoDbClient.builder()
  .region(Region.EU_WEST_1)
  .credentialsProvider(StaticCredentialsProvider.create(awsCredentials))
  .build();

String idKey = "wholeIdKey";
String idValue = "partialIdValue";
String typeValue = "typeValue";

Map<String, String> expressionNames = new HashMap<>();
expressionNames.put("#t", "Type");

QueryRequest request = QueryRequest.builder()
  .tableName(tableName)
  .keyConditionExpression("begins_with ( " + idKey + ", :" + idValue + " )
     AND #t = :" + typeValue)
  .expressionAttributeNames(expressionNames)
  .build();

QueryResponse response = dynamoDbClient.query(request);

但是,当我 运行 这段代码时,我收到以下错误消息:

Exception in thread "main" software.amazon.awssdk.services.dynamodb.model.DynamoDbException: 
Invalid KeyConditionExpression: An expression attribute value used in expression is not defined; attribute value: :typeValue

好像它没有意识到我告诉代码使用表达式属性名称功能将“#t”替换为“Type”(这是 DynamoDB 中的保留关键字)这一事实

有人可以帮忙吗?

编辑:代码参考:

https://docs.aws.amazon.com/code-samples/latest/catalog/javav2-dynamodb-src-main-java-com-example-dynamodb-Query.java.html

https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ExpressionAttributeNames.html

https://www.javadoc.io/static/software.amazon.awssdk/dynamodb/2.7.14/software/amazon/awssdk/services/dynamodb/model/QueryRequest.html#expressionAttributeNames--

您的 expressionAttributeName 看起来不错,但您忘记为 :typeValue 提供值,因此 dynamoDB 不知道要查找什么。

除了您所做的之外,您还需要添加一个 expressionAttributeValue,您可以在其中提供适当的值。 See documentation here

名称很好,但是您在两个值前都添加了“:”前缀。这导致在 ExpressionAttributeValues 中查找您未提供的内容。

切勿尝试将动态值直接写入查询字符串。

固定代码供将来任何人使用(感谢@aherve and @MattTimmermans

DynamoDBClient dynamoDbClient = DynamoDbClient.builder()
  .region(Region.EU_WEST_1)
  .credentialsProvider(StaticCredentialsProvider.create(awsCredentials))
  .build();

String idKey = "wholeIdKey";
String idValue = "partialIdValue";
String typeValue = "typeValue";
String typeKey = "typeKey";

Map<String, String> expressionNames = new HashMap<>();
expressionNames.put("#t", "Type");
expressionNames.put("#i", "Id");

Map<String, AttributeValue> expressionValues = new HashMap<>();
expressionValues.put(":typeName", AttributeValue.builder().s(typeValue).build());
expressionValues.put(":idName", AttributeValue.builder().s(idValue).build());

QueryRequest request = QueryRequest.builder()
  .tableName(tableName)
  .keyConditionExpression("#t = :typeName AND begins_with ( #i, :idName )")
  .expressionAttributeNames(expressionNames)
  .expressionAttributeValues(expressionValues)
  .build();

response = dynamoDbClient.query(request);