DynamoDB Query with equality on PK and Begins with on SK in Go using Expressions package

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

DynamoDB Query with equality on PK and Begins with on SK in Go using Expressions package

问题

我正在尝试使用Go语言在DynamoDB表上编写一个查询操作。我想复制以下CLI命令:

aws dynamodb query \
  --table-name myTable \
  --index-name name-index \
  --key-condition-expression "_pk = :dpid and begins_with(st, :st)" \
  --expression-attribute-values  '{"dpid":{"S":"dp#1"}, "st":{"S":"jam"}}'

注意 _pk 前面的下划线。

我尝试使用 Expressions package,但是我觉得文档非常令人困惑。到目前为止,我有以下代码:

func (p *PatientStore) SearchPatients(ctx context.Context, searchTerm string) ([]PatientSearchResponseItem, error) {
	dentalPracticeId := "dp#1"
	lowerCaseSearchTerm := strings.ToLower(searchTerm)
	var err error
	var response *dynamodb.QueryOutput
	var patients []PatientSearchResponseItem
	keyEx := expression.Key("_pk").Equal(expression.Value(dentalPracticeId))
	gsiCondition := expression.BeginsWith(expression.Name("st"), lowerCaseSearchTerm) // gsiCondition declared but not used error
	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 = p.client.Query(context.TODO(), &dynamodb.QueryInput{
			TableName:                 aws.String(p.tableName),
            IndexName:                 jsii.String("name-index"),
			ExpressionAttributeNames:  expr.Names(),
			ExpressionAttributeValues: expr.Values(),
			KeyConditionExpression:    expr.KeyCondition(),
		})
		if err != nil {
			log.Printf("Couldn't query for patients matching %v. Here's why: %v\n", lowerCaseSearchTerm, err)
		} else {
			err = attributevalue.UnmarshalListOfMaps(response.Items, &patients)
			if err != nil {
				log.Printf("Couldn't unmarshal query response. Here's why: %v\n", err)
			}
		}
	}

	return patients, err
}

目前,我收到一个错误,指出 gsiCondition 被声明但未使用,这是有道理的,但我不知道如何使用该条件。文档中没有显示如何使用多个条件。

我该如何使其工作起来?

英文:

I am trying to write a Query operation on a DynamoDB table with Go. I am trying to duplicate the following CLI command:

aws dynamodb query \
  --table-name myTable \
  --index-name name-index \
  --key-condition-expression "_pk = :dpid and begins_with(st, :st)" \
  --expression-attribute-values  '{":dpid":{"S":"dp#1"}, ":st":{"S":"jam"}}'

Note the _ in front of the _pk.

I am trying to use the Expressions package, but I find the docs super confusing. So far I have:

func (p *PatientStore) SearchPatients(ctx context.Context, searchTerm string) ([]PatientSearchResponseItem, error) {
	dentalPracticeId := "dp#1"
	lowerCaseSearchTerm := strings.ToLower(searchTerm)
	var err error
	var response *dynamodb.QueryOutput
	var patients []PatientSearchResponseItem
	keyEx := expression.Key("_pk").Equal(expression.Value(dentalPracticeId))
	gsiCondition := expression.BeginsWith(expression.Name("st"), lowerCaseSearchTerm) // gsiCondition declared but not used error
	expr, err := expression.NewBuilder().WithKeyCondition(keyEx).Build()
	if err != nil {
		log.Printf("Couldn't build epxression for query. Here's why: %v\n", err)
	} else {
		response, err = p.client.Query(context.TODO(), &dynamodb.QueryInput{
			TableName:                 aws.String(p.tableName),
            IndexName:                 jsii.String("name-index"),
			ExpressionAttributeNames:  expr.Names(),
			ExpressionAttributeValues: expr.Values(),
			KeyConditionExpression:    expr.KeyCondition(),
		})
		if err != nil {
			log.Printf("Couldn't query for patients matching %v. Here's why: %v\n", lowerCaseSearchTerm, err)
		} else {
			err = attributevalue.UnmarshalListOfMaps(response.Items, &patients)
			if err != nil {
				log.Printf("Couldn't unmarshal query response. Here's why: %v\n", err)
			}
		}
	}

	return patients, err
}

Right now, I'm getting an error that states that the gsiCondition is declared but not used, which makes sense, but I don't know how to use that condition. The docs don't show how to have multiple conditions.

How can I get this working?

答案1

得分: 1

你看过我们在GitHub上的示例了吗?

https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/go/example_code/dynamodb/DynamoDBScanItems.go

这应该会给你所需的信息。

至于异常,如果你不需要请求中的expressionAttributeValues/Names,你可以简单地省略它们。

package main

import (
    "context"
    "fmt"

    "github.com/aws/aws-sdk-go-v2/aws"
    "github.com/aws/aws-sdk-go-v2/config"
    "github.com/aws/aws-sdk-go-v2/service/dynamodb"
    "github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
)

func main() {
    cfg, err := config.LoadDefaultConfig(context.TODO(), func(o *config.LoadOptions) error {
        o.Region = "eu-west-1"
        return nil
    })
    if err != nil {
        panic(err)
    }

    svc := dynamodb.NewFromConfig(cfg)
    out, err := svc.Query(context.TODO(), &dynamodb.QueryInput{
        TableName:              aws.String("test"),
        KeyConditionExpression: aws.String("#pk = :pk and #sk > :sk"),
        ExpressionAttributeValues: map[string]types.AttributeValue{
            ":pk":  &types.AttributeValueMemberS{Value: "lhnng"},
            ":sk": &types.AttributeValueMemberN{Value: "500"},
        },
        ExpressionAttributeNames: map[string]string{
            "#pk": "_pk",
            "#sk": "sk",
        },
    })
    if err != nil {
        panic(err)
    }

    fmt.Println(out.Items)
}
英文:

Have you taken a look at our examples on GitHub?

https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/go/example_code/dynamodb/DynamoDBScanItems.go

This should give you the information you require.

As for the exception, you cannot declare expressionAttributeValues/Names and not use them, it they are no needed for the request you can simply omit them.

package main

import (
    "context"
    "fmt"

    "github.com/aws/aws-sdk-go-v2/aws"
    "github.com/aws/aws-sdk-go-v2/config"
    "github.com/aws/aws-sdk-go-v2/service/dynamodb"
    "github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
)

func main() {
    cfg, err := config.LoadDefaultConfig(context.TODO(), func(o *config.LoadOptions) error {
        o.Region = "eu-west-1"
        return nil
    })
    if err != nil {
        panic(err)
    }

    svc := dynamodb.NewFromConfig(cfg)
    out, err := svc.Query(context.TODO(), &dynamodb.QueryInput{
        TableName:              aws.String("test"),
        KeyConditionExpression: aws.String("#pk = :pk and #sk > :sk"),
        ExpressionAttributeValues: map[string]types.AttributeValue{
            ":pk":  &types.AttributeValueMemberS{Value: "lhnng"},
            ":sk": &types.AttributeValueMemberN{Value: "500"},
        },
        ExpressionAttributeNames: map[string]string{
            "#pk": "_pk",
            "#sk": "sk",
        },
    })
    if err != nil {
        panic(err)
    }

    fmt.Println(out.Items)
}

答案2

得分: 0

将这段代码翻译为中文如下:

为了让其他人受益,我将这段代码放在这里。我使用表达式解决了这个问题。

var condition = expression.Name("pk").Equal(expression.Value("pkValue")).And(expression.Name("sk").BeginsWith("skValue"))
condExp, err := expression.NewBuilder().WithCondition(condition).Build()
if err != nil {
	return nil, fmt.Errorf("构建表达式时出错:%w", err)
}

response, err := svc.Query(c, &dynamodb.QueryInput{
	TableName:                 &tableName,
	KeyConditionExpression:    condExp.Condition(),
	ExpressionAttributeNames:  condExp.Names(),
	ExpressionAttributeValues: condExp.Values(),
})
if err != nil {
	return nil, fmt.Errorf("读取数据失败:%w", err)
}
英文:

Putting this here just for the benefit of others. I was able to solve it with expressions

var condition = expression.Name("pk").Equal(expression.Value("pkValue")).And(expression.Name("sk").BeginsWith("skValue"))
condExp, err := expression.NewBuilder().WithCondition(condition).Build()
if err != nil {
	return nil, fmt.Errorf("error building expression: %w", err)
}

response, err := svc.Query(c, &dynamodb.QueryInput{
	TableName:                 &tableName,
	KeyConditionExpression:    condExp.Condition(),
	ExpressionAttributeNames:  condExp.Names(),
	ExpressionAttributeValues: condExp.Values(),
})
if err != nil {
	return nil, fmt.Errorf("failed reading data: %w", err)
}

huangapple
  • 本文由 发表于 2022年11月9日 06:16:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/74367765.html
匿名

发表评论

匿名网友

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

确定