DynamoDB Java SDK – 使用 IN 子句的 QueryRequest

huangapple go评论73阅读模式
英文:

DynamoDB Java SDK - QueryRequest with IN clause

问题

software.amazon.awssdk.services.dynamodb.model.QueryRequest.expressionAttributeValues()方法的Javadoc中提到可以执行以下查询:

ProductStatus IN (:avail, :back, :disc)

其中的值通过"ExpressionAttributeValues"以以下方式传递:

{ "avail":{"S":"Available"}, "back":{"S":"Backordered"}, "disc":{"S":"Discontinued"} }

我现在正在尝试弄清楚QueryRequest.expressionAttributeValues是以下Map

Map<String, AttributeValue> expressionAttributeValues)

似乎没有其他方法可以将表达式值传递给在QueryRequest.keyConditionExpression()中定义的表达式。

我特意寻找了传递JSON表达式的方法,但找不到。跳过了旧的方法-- QueryRequest.keyConditions()和其他一些方法。

我尝试了以下代码:

QueryRequest queryRequest = QueryRequest
                .builder().tableName("tablename")
                .indexName("user-index")
                .keyConditionExpression("index-ID IN (:key0, :key1, :key2)")
                .expressionAttributeValues(keys)
                .build();

其中Map<String, Map<String, AttributeValue>> keys在使用toString()打印时如下所示:

{:key2=AttributeValue(S=5555550), :key1=AttributeValue(S=5555551), :key0=AttributeValue(S=5555552)}

对此抛出了以下异常:

software.amazon.awssdk.services.dynamodb.model.DynamoDbException: ExpressionAttributeValues contains invalid key: Syntax error; key: ":key1" (Service: DynamoDb, Status Code: 400, Request ID: R986SKT4JTK02C57HD0P8591TVQV4KQNSO5AEMVJF66Q9ASUAAJG)
	at software.amazon.awssdk.core.internal.http.CombinedResponseHandler.handleErrorResponse(CombinedResponseHandler.java:125)
	at software.amazon.awssdk.core.internal.http.CombinedResponseHandler.handleResponse(CombinedResponseHandler.java:82)
	at software.amazon.awssdk.core.internal.http.CombinedResponseHandler.handle(CombinedResponseHandler.java:60)
	at software.amazon.awssdk.core.internal.http.CombinedResponseHandler.handle(CombinedResponseHandler.java:41)
	at software.amazon.awssdk.core.internal.http.pipeline.stages.HandleResponseStage.execute(HandleResponseStage.java:40)
	at software.amazon.awssdk.core.internal.http.pipeline.stages.HandleResponseStage.execute(HandleResponseStage.java:30)
	at software.amazon.awssdk.core.internal.http.pipeline.RequestPipelineBuilder$ComposingRequestPipelineStage.execute(RequestPipelineBuilder.java:206)
	at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallAttemptTimeoutTrackingStage.execute(ApiCallAttemptTimeoutTrackingStage.java:73)
	at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallAttemptTimeoutTrackingStage.execute(ApiCallAttemptTimeoutTrackingStage.java:42)
	at software.amazon.awssdk.core.internal.http.pipeline.stages.TimeoutExceptionHandlingStage.execute(TimeoutExceptionHandlingStage.java:78)
	at software.amazon.awssdk.core.internal.http.pipeline.stages.TimeoutExceptionHandlingStage.execute(TimeoutExceptionHandlingStage.java:40)
	at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallAttemptMetricCollectionStage.execute(ApiCallAttemptMetricCollectionStage.java:50)
	at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallAttemptMetricCollectionStage.execute(ApiCallAttemptMetricCollectionStage.java:36)
	at software.amazon.awssdk.core.internal.http.pipeline.stages.RetryableStage.execute(RetryableStage.java:81)
	at software.amazon.awssdk.core.internal.http.pipeline.stages.RetryableStage.execute(RetryableStage.java:36)
	at software.amazon.awssdk.core.internal.http.pipeline.RequestPipelineBuilder$ComposingRequestPipelineStage.execute(RequestPipelineBuilder.java:206)
	at software.amazon.awssdk.core.internal.http.StreamManagingStage.execute(StreamManagingStage.java:56)
	at software.amazon.awssdk.core.internal.http.StreamManagingStage.execute(StreamManagingStage.java:36)
	at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallTimeoutTrackingStage.executeWithTimer(ApiCallTimeoutTrackingStage.java:80)
	at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallTimeoutTrackingStage.execute(ApiCallTimeoutTrackingStage.java:60)
	at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallTimeoutTrackingStage.execute(ApiCallTimeoutTrackingStage.java:42)
	at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallMetricCollectionStage.execute(ApiCallMetricCollectionStage.java:48)
	at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallMetricCollectionStage.execute(ApiCallMetricCollectionStage.java:31)
	at software.amazon.awssdk.core.internal.http.pipeline.RequestPipelineBuilder$ComposingRequestPipelineStage.execute(RequestPipelineBuilder.java:206)
	at software.amazon.awssdk.core.internal.http.pipeline.RequestPipelineBuilder$ComposingRequestPipelineStage.execute(RequestPipelineBuilder.java:206)
	at software.amazon.awssdk.core.internal.http.pipeline.stages.ExecutionFailureExceptionReportingStage.execute(ExecutionFailureExceptionReportingStage.java:37)
	at software.amazon.awssdk.core.internal.http.pipeline.stages.ExecutionFailureExceptionReportingStage.execute(ExecutionFailureExceptionReportingStage.java:26)
	at software.amazon.awssdk.core.internal.http.AmazonSyncHttpClient$RequestExecutionBuilderImpl.execute(AmazonSyncHttpClient.java:193)
	at software.amazon.awssdk.core.internal.handler.BaseSyncClientHandler.invoke(BaseSyncClientHandler.java:103)
	at software.amazon.awssdk.core.internal.handler.BaseSyncClientHandler.doExecute(BaseSyncClientHandler.java:171)
	at software.amazon.awssdk.core.internal.handler.BaseSyncClientHandler.lambda$execute$1(BaseSyncClientHandler.java:82)
	at software.amazon.awssdk.core.internal.handler.BaseSyncClientHandler.measureApiCallSuccess(BaseSyncClientHandler.java:179)
	at software.amazon.awssdk.core.internal.handler.BaseSyncClientHandler.execute(BaseSyncClientHandler.java:76)
	at software.amazon.awssdk.core.client.handler.SdkSyncClientHandler.execute(SdkSyncClientHandler.java:45)
	at software.amazon.awssdk.awscore.client.handler.AwsSyncClientHandler.execute(AwsSyncClientHandler.java:56)
	at software.amazon.awssdk.services.dynamodb.DefaultDynamoDbClient.query(DefaultDynamoDbClient.java:4372)

我还尝试了在键周围加上引号以及其他一些变化:

{"key2"=AttributeValue(S=5555550), "key1"=AttributeValue(S=5555551), "key0"=AttributeValue(S=5555552)}

非常感谢帮助。
让我筋疲力尽。

//==================

更新:我知道可以通过脚本直接向AWS服务器发出Restful调用,但我们正在寻找Java解决方案。

英文:

The Javadoc of software.amazon.awssdk.services.dynamodb.model.QueryRequest.expressionAttributeValues() says a following query can be done:

ProductStatus IN (:avail, :back, :disc)

where the values are passed in in "ExpressionAttributeValues" as follows:

{ &quot;:avail&quot;:{&quot;S&quot;:&quot;Available&quot;}, &quot;:back&quot;:{&quot;S&quot;:&quot;Backordered&quot;}, &quot;:disc&quot;:{&quot;S&quot;:&quot;Discontinued&quot;} }

I'm now trying to figure how

QueryRequest.expressionAttributeValues is the following Map:

Map&lt;String, AttributeValue&gt; expressionAttributeValues)

there doesn't seem to be any other way to pass expression values to the expression defined in QueryRequest.keyConditionExpression()

I specifically looked for a way to pass in a JSON expression -- can't find any.
skipped the legacy methods-- QueryRequest.keyConditions() and some others.

i tried

  QueryRequest queryRequest = QueryRequest
.builder().tableName(&quot;tablename&quot;)
.indexName(&quot;user-index&quot;)
.keyConditionExpression(&quot;index-ID IN (:key0, :key1, :key2)&quot;
.expressionAttributeValues(keys)
.build();

where Map&lt;String, Map&lt;String, AttributeValue&gt;&gt; keys looks like the following when i print this Map with its toString():

{:key2=AttributeValue(S=5555550), :key1=AttributeValue(S=5555551), :key0=AttributeValue(S=5555552)}

the following exception is thrown to this:

software.amazon.awssdk.services.dynamodb.model.DynamoDbException: ExpressionAttributeValues contains invalid key: Syntax error; key: &quot;&quot;:key1&quot;&quot; (Service: DynamoDb, Status Code: 400, Request ID: R986SKT4JTK02C57HD0P8591TVQV4KQNSO5AEMVJF66Q9ASUAAJG)
at software.amazon.awssdk.core.internal.http.CombinedResponseHandler.handleErrorResponse(CombinedResponseHandler.java:125)
at software.amazon.awssdk.core.internal.http.CombinedResponseHandler.handleResponse(CombinedResponseHandler.java:82)
at software.amazon.awssdk.core.internal.http.CombinedResponseHandler.handle(CombinedResponseHandler.java:60)
at software.amazon.awssdk.core.internal.http.CombinedResponseHandler.handle(CombinedResponseHandler.java:41)
at software.amazon.awssdk.core.internal.http.pipeline.stages.HandleResponseStage.execute(HandleResponseStage.java:40)
at software.amazon.awssdk.core.internal.http.pipeline.stages.HandleResponseStage.execute(HandleResponseStage.java:30)
at software.amazon.awssdk.core.internal.http.pipeline.RequestPipelineBuilder$ComposingRequestPipelineStage.execute(RequestPipelineBuilder.java:206)
at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallAttemptTimeoutTrackingStage.execute(ApiCallAttemptTimeoutTrackingStage.java:73)
at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallAttemptTimeoutTrackingStage.execute(ApiCallAttemptTimeoutTrackingStage.java:42)
at software.amazon.awssdk.core.internal.http.pipeline.stages.TimeoutExceptionHandlingStage.execute(TimeoutExceptionHandlingStage.java:78)
at software.amazon.awssdk.core.internal.http.pipeline.stages.TimeoutExceptionHandlingStage.execute(TimeoutExceptionHandlingStage.java:40)
at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallAttemptMetricCollectionStage.execute(ApiCallAttemptMetricCollectionStage.java:50)
at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallAttemptMetricCollectionStage.execute(ApiCallAttemptMetricCollectionStage.java:36)
at software.amazon.awssdk.core.internal.http.pipeline.stages.RetryableStage.execute(RetryableStage.java:81)
at software.amazon.awssdk.core.internal.http.pipeline.stages.RetryableStage.execute(RetryableStage.java:36)
at software.amazon.awssdk.core.internal.http.pipeline.RequestPipelineBuilder$ComposingRequestPipelineStage.execute(RequestPipelineBuilder.java:206)
at software.amazon.awssdk.core.internal.http.StreamManagingStage.execute(StreamManagingStage.java:56)
at software.amazon.awssdk.core.internal.http.StreamManagingStage.execute(StreamManagingStage.java:36)
at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallTimeoutTrackingStage.executeWithTimer(ApiCallTimeoutTrackingStage.java:80)
at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallTimeoutTrackingStage.execute(ApiCallTimeoutTrackingStage.java:60)
at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallTimeoutTrackingStage.execute(ApiCallTimeoutTrackingStage.java:42)
at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallMetricCollectionStage.execute(ApiCallMetricCollectionStage.java:48)
at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallMetricCollectionStage.execute(ApiCallMetricCollectionStage.java:31)
at software.amazon.awssdk.core.internal.http.pipeline.RequestPipelineBuilder$ComposingRequestPipelineStage.execute(RequestPipelineBuilder.java:206)
at software.amazon.awssdk.core.internal.http.pipeline.RequestPipelineBuilder$ComposingRequestPipelineStage.execute(RequestPipelineBuilder.java:206)
at software.amazon.awssdk.core.internal.http.pipeline.stages.ExecutionFailureExceptionReportingStage.execute(ExecutionFailureExceptionReportingStage.java:37)
at software.amazon.awssdk.core.internal.http.pipeline.stages.ExecutionFailureExceptionReportingStage.execute(ExecutionFailureExceptionReportingStage.java:26)
at software.amazon.awssdk.core.internal.http.AmazonSyncHttpClient$RequestExecutionBuilderImpl.execute(AmazonSyncHttpClient.java:193)
at software.amazon.awssdk.core.internal.handler.BaseSyncClientHandler.invoke(BaseSyncClientHandler.java:103)
at software.amazon.awssdk.core.internal.handler.BaseSyncClientHandler.doExecute(BaseSyncClientHandler.java:171)
at software.amazon.awssdk.core.internal.handler.BaseSyncClientHandler.lambda$execute$1(BaseSyncClientHandler.java:82)
at software.amazon.awssdk.core.internal.handler.BaseSyncClientHandler.measureApiCallSuccess(BaseSyncClientHandler.java:179)
at software.amazon.awssdk.core.internal.handler.BaseSyncClientHandler.execute(BaseSyncClientHandler.java:76)
at software.amazon.awssdk.core.client.handler.SdkSyncClientHandler.execute(SdkSyncClientHandler.java:45)
at software.amazon.awssdk.awscore.client.handler.AwsSyncClientHandler.execute(AwsSyncClientHandler.java:56)
at software.amazon.awssdk.services.dynamodb.DefaultDynamoDbClient.query(DefaultDynamoDbClient.java:4372)

i also tried surrounding the key-s with quotes along with some other variations:

{&quot;:key2&quot;=AttributeValue(S=5555550), &quot;:key1&quot;=AttributeValue(S=5555551), &quot;:key0&quot;=AttributeValue(S=5555552)}

Will greatly appreciate the help.
Wore me out.

//==================

UPDATE: i'm aware of the direct Restful call via a script to AWS server, but we're looking for the Java solution.

答案1

得分: 1

你所尝试实现的功能在使用KeyConditionExpressionQuery操作中是不可能的。

KeyConditionExpression要求只能在单个分区键上使用等于=比较,不允许使用INORAND来使用多个键。

使用KeyConditionExpression参数为分区键提供特定值。Query操作将返回具有该分区键值的表或索引中的所有项。您可以选择通过在KeyConditionExpression中指定排序键值和比较运算符来缩小Query操作的范围。

参考链接


唯一允许类似于您创建的语法的API是PartiQL的ExecuteStatement,您可以在其中作为IN子句的一部分传递最多50个分区键:

SELECT * FROM mytable WHERE PK IN [1,2...50]

参考链接

英文:

What you are trying to achieve is not possible for a Query using KeyConditionExpression.

A KeyConditionExpression requires an equals = comparative on a single partition key only, multiple keys using IN or OR or AND are now allowed.

> Use the KeyConditionExpression parameter to provide a specific value for the partition key. The Query operation will return all of the items from the table or index with that partition key value. You can optionally narrow the scope of the Query operation by specifying a sort key value and a comparison operator in KeyConditionExpression.

ref


The only API that allows syntax similar to what you are creating is PartiQL ExecuteStatement where you can pass in up to 50 partition keys as part of an IN clause:

SELECT * FROM mytable WHERE PK IN [1,2...50]

https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_ExecuteStatement.html

huangapple
  • 本文由 发表于 2023年8月9日 03:25:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/76862656.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定