How to query AWS DynamoDb using KeyConditionExpression and v2 Go SDK?

WBOY
Release: 2024-02-08 20:48:04
forward
632 people have browsed it

如何使用 KeyConditionExpression 和 v2 Go SDK 查询 AWS DynamoDb?

Question content

I have an existing table in dynamodb created using the following command

aws dynamodb create-table \
  --region us-east-1 \
  --table-name notifications \
  --attribute-definitions AttributeName=CustomerId,AttributeType=S AttributeName=Timestamp,AttributeType=N AttributeName=MessageId,AttributeType=S \
  --key-schema AttributeName=CustomerId,KeyType=HASH AttributeName=Timestamp,KeyType=RANGE \
  --provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \
  --global-secondary-indexes '[
      {
          "IndexName": "MessageId",
          "KeySchema": [
              {
                  "AttributeName": "MessageId",
                  "KeyType": "HASH"
              }
          ],
          "Projection": {
              "ProjectionType": "ALL"
          },
          "ProvisionedThroughput": {
              "ReadCapacityUnits": 5,
              "WriteCapacityUnits": 5
          }
      }
  ]'
}
Copy after login

I wanted to put an API wrapper in front of it that would allow me to get all the records from the table providing the CustomerId, so I tried using a query from the v2 GO SDK

<code>// GET /notifications/
func (api NotificationsApi) getNotifications(w http.ResponseWriter, r *http.Request) {
    var err error

    customerId := r.URL.Query().Get("customerId")
    if customerId == "" {
        api.errorResponse(w, "customerId query parameter required", http.StatusBadRequest)
        return
    }
    span, ctx := tracer.StartSpanFromContext(r.Context(), "notification.get")
    defer span.Finish(tracer.WithError(err))

    keyCond := expression.Key("CustomerId").Equal(expression.Value(":val"))
    expr, err := expression.NewBuilder().WithKeyCondition(keyCond).Build()

    input := &dynamodb.QueryInput{
        TableName:              aws.String("notifications"),
        KeyConditionExpression: expr.KeyCondition(),
        ExpressionAttributeValues: map[string]dynamodbTypes.AttributeValue{
            ":val": &dynamodbTypes.AttributeValueMemberS{Value: customerId},
        },
    }

    fmt.Println(*expr.KeyCondition())
    output, err := api.dynamoClient.Query(ctx, input)

    fmt.Println(output)
    fmt.Println(err)
}
</code>
Copy after login

However, I got 400

from dynamodb
operation error DynamoDB: Query, https response error StatusCode: 400, RequestID: *****, api error ValidationException: Invalid KeyConditionExpression: An expression attribute name used in the document path is not defined; attribute name: #0
Copy after login
The output of

fmt.PrintLn(*expr.KeyCondition()) is #0 = :0

Running this query locally returns my expected results

awslocal dynamodb query \
    --table-name notifications \
    --key-condition-expression "CustomerId = :val" \
    --expression-attribute-values '{":val":{"S":"localTesting"}}'
Copy after login

I also tried including the timestamp but don't think it's necessary as my terminal commands work without it. I don't think I dereferenced inappropriately. I know my generator session is valid because I can publish to my wrapper and see updates via terminal commands.


Correct answer


Here are examples of queries you can use as templates:

// TableBasics encapsulates the Amazon DynamoDB service actions used in the examples.
// It contains a DynamoDB service client that is used to act on the specified table.
type TableBasics struct {
    DynamoDbClient *dynamodb.Client
    TableName      string
}



// Query gets all movies in the DynamoDB table that were released in the specified year.
// The function uses the `expression` package to build the key condition expression
// that is used in the query.
func (basics TableBasics) Query(releaseYear int) ([]Movie, error) {
    var err error
    var response *dynamodb.QueryOutput
    var movies []Movie
    keyEx := expression.Key("year").Equal(expression.Value(releaseYear))
    expr, err := expression.NewBuilder().WithKeyCondition(keyEx).Build()
    if err != nil {
        log.Printf("Couldn't build expression for query. Here's why: %v\n", err)
    } else {
        response, err = basics.DynamoDbClient.Query(context.TODO(), &dynamodb.QueryInput{
            TableName:                 aws.String(basics.TableName),
            ExpressionAttributeNames:  expr.Names(),
            ExpressionAttributeValues: expr.Values(),
            KeyConditionExpression:    expr.KeyCondition(),
        })
        if err != nil {
            log.Printf("Couldn't query for movies released in %v. Here's why: %v\n", releaseYear, err)
        } else {
            err = attributevalue.UnmarshalListOfMaps(response.Items, &movies)
            if err != nil {
                log.Printf("Couldn't unmarshal query response. Here's why: %v\n", err)
            }
        }
    }
    return movies, err
}
Copy after login

You can see more GoV2 examples here

The above is the detailed content of How to query AWS DynamoDb using KeyConditionExpression and v2 Go SDK?. For more information, please follow other related articles on the PHP Chinese website!

source:stackoverflow.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!