Go语言 AWS DynamoDB:正在解组BatchGetItem响应

x759pob2  于 2023-10-14  发布在  Go
关注(0)|答案(2)|浏览(127)

我正在使用GO SDK和DynamnoDB BatchGetItem API。
我看到了这个代码示例-
https://github.com/aws/aws-sdk-go/blob/master/service/dynamodb/examples_test.go
是否有其他代码示例显示来自BatchGetItem API的响应的解组?

8ftvxx2r

8ftvxx2r1#

让我分享一段代码。理解它的关键是,当您向dynamodb发送GetBatchItem请求时,您指定了该表的表名和键的Map,因此您得到的响应是表名和匹配项的Map

placeIDs := []string { "london_123", "sanfran_15", "moscow_9" }

type Place {
    ID string `json:"id"`
    Name string `json:"name"`
    Description string `json:"description"`
}

mapOfAttrKeys := []map[string]*dynamodb.AttributeValue{}

for _, place := range placeIDs {
    mapOfAttrKeys = append(mapOfAttrKeys, map[string]*dynamodb.AttributeValue{
        "id": &dynamodb.AttributeValue{
            S: aws.String(place),
        },
        "attr": &dynamodb.AttributeValue{
            S: aws.String("place"),
        },
    })
}

input := &dynamodb.BatchGetItemInput{
    RequestItems: map[string]*dynamodb.KeysAndAttributes{
        tableName: &dynamodb.KeysAndAttributes{
            Keys: mapOfAttrKeys,
        },
    },
}

batch, err := db.BatchGetItem(input)

if err != nil {
    panic(fmt.Errorf("batch load of places failed, err: %w", err))
}

for _, table := range batch.Responses {
    for _, item := range table {
        var place Place

        err = dynamodbattribute.UnmarshalMap(item, &place)

        if err != nil {
            panic(fmt.Errorf("failed to unmarshall place from dynamodb response, err: %w", err))
        }

        places = append(places, place)
    }
}
pes8fvy9

pes8fvy92#

这些都是很老的问题和答案,但它们非常有用,感谢TP @dattatray和@itmeze
尽管如此,今天亚马逊建议使用新的实现,AWS SDK for Go V2,其中相同的东西可以以更简洁和更具表现力的方式实现。

import (
        "context"
        "fmt"
        "github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue"
        "github.com/aws/aws-sdk-go-v2/service/dynamodb"
        "github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
    )

    type Place struct {
        ID string `dynamodbav:"id" json:"id"`
        Name string `dynamodbav:"name" json:"name"`
        Description string `dynamodbav:"description" json:"description"`
    }

    // define your context and DynamoDB client
    var ctx context.Context
    var db dynamodb.Client
    

    placeIDs := []string { "london_123", "sanfran_15", "moscow_9" }
    tableName := "Places"

    //marshall and collect into a slice the keys to be queried
    var requests types.KeysAndAttributes
    for _, place := range placeIDs {
        key := struct {
            Name string `dynamodbav:"name" json:"name"`
        } {Name: place}
        item, err := attributevalue.MarshalMap(key)
        if err != nil {
            panic(fmt.Errorf("failed to marshal key %s, err: %w", place, err))
        }
        requests.Keys = append(requests.Keys, item)
    }

    //prepare and issue `BatchGetItem` request
    batch := make(map[string]types.KeysAndAttributes)
    batch[tableName] = requests
    op, err := db.BatchGetItem(ctx, &dynamodb.BatchGetItemInput{
        RequestItems: batch,
    })
    if err != nil {
        panic(fmt.Errorf("couldn't send a batch of items to dynamo DB %w", err))
    }

    //here we collect the keys for which we didn't get results
    //basically they can be later passed to retry BatchGetItem call
    var missingKeys []map[string]types.AttributeValue
    if missing, ok := op.UnprocessedKeys[tableName]; ok {
        copy(missingKeys, missing.Keys)
    }

    //collecting the results into the slice
    var resultItems []Place
    for _, items := range op.Responses {
        var unmarshaledItems []Place
        if err := attributevalue.UnmarshalListOfMaps(items, unmarshaledItems); err != nil {
            panic(fmt.Errorf("failed to unmarshal item, err: %w", err))
        }
        resultItems = append(resultItems, unmarshaledItems...)
    }

相关问题