🧨

GoでDynamoDBのデータ操作をマスターする

2023/12/12に公開

DynamoDBは、Amazon Web Services(AWS)が提供する高速かつスケーラブルなNoSQLデータベースサービスです。その柔軟性とパフォーマンスの高さから、多くの開発者や企業がDynamoDBを選択しています。しかし、DynamoDBを利用するためには、その操作方法や機能について正確な理解が必要です。

本記事では、Go言語を使用してDynamoDBのデータ操作をマスターする方法に焦点を当てます。CRUD(Create, Read, Update, Delete)操作からトランザクション処理まで、幅広いトピックを詳しく解説します。

セットアップ

まずは、 aws-sdk-go-v2 ライブラリのインストールから始めましょう。

go get github.com/aws/aws-sdk-go-v2

クライアントの初期化

次に、DynamoDBにアクセスするためのクライアントを生成します。

import (
    "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"
)

cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRegion("us-west-2"))
if err != nil {
    log.Fatalf("unable to load SDK config, %v", err)
}

client := dynamodb.NewFromConfig(cfg)

詳細については、公式ドキュメントをご覧ください。

データの取得

DynamoDBからデータを取得する主要な方法は3つあります。

以下ではそれぞれの方法を用いてデータを取得する方法について説明します。

GetItem

GetItemは一つの項目を取得するためのAPIです。主キーを指定して使用します。

以下の例では、主キーが UserId で値が 12345 のユーザの情報を取得しています。

input := &dynamodb.GetItemInput{
    TableName: aws.String("Users"),
    Key: map[string]types.AttributeValue{
        "UserId": &types.AttributeValueMemberS{
            Value: "12345",
        },
    },
}

resp, err := client.GetItem(context.TODO(), input)
if err != nil {
    log.Fatalf("failed to get item, %v", err)
}

ここで Users はテーブル名で、 UserId は主キー(パーティションキー)名を指します。そのため、各自の環境に合わせてこれらの名前を変更してください。

詳細については、公式ドキュメントをご覧ください。

Scan

Scanはテーブルの全項目をスキャンするAPIです。条件を指定しない場合、全項目を取得します。

以下の例では、Usersテーブルの全項目を取得します。

input := &dynamodb.ScanInput{
    TableName: aws.String("Users"),
}

resp, err := client.Scan(context.TODO(), input)
if err != nil {
    log.Fatalf("failed to scan, %v", err)
}

注意点として、Scanはテーブル全体をスキャンするため、大規模なテーブルに対してはパフォーマンスに影響を及ぼす可能性があります。特定の項目のみを取得したい場合はQueryやGetItemを使うことを検討してください。

詳細については、公式ドキュメントをご覧ください。

Query

Queryは主キーまたはインデックスを指定して項目を取得するAPIです。

以下の例では、Usersテーブルで Gender が Male である全ユーザを取得します。ここではインデックス Gender-index を利用しています。

input := &dynamodb.QueryInput{
    TableName: aws.String("Users"),
    IndexName: aws.String("Gender-index"),
    KeyConditionExpression: aws.String("Gender = :v"),
    ExpressionAttributeValues: map[string]types.AttributeValue{
        ":v": &types.AttributeValueMemberS{
            Value: "Male",
        },
    },
}

resp, err := client.Query(context.TODO(), input)
if err != nil {
    log.Fatalf("failed to query, %v", err)
}

この例では、 Gender-index というセカンダリインデックスを使っており、:v というエクスプレッション属性値を使ってクエリ条件を指定しています。

詳細については、公式ドキュメントをご覧ください。

データの追加

新しい項目をテーブルに追加するには、PutItemAPIを使用します。

以下の例では、新しいユーザをUsersテーブルに追加します。

input := &dynamodb.PutItemInput{
    TableName: aws.String("Users"),
    Item: map[string]types.AttributeValue{
        "UserId": &types.AttributeValueMemberS{
            Value: "12346",
        },
        "Name": &types.AttributeValueMemberS{
            Value: "John Doe",
        },
        "Email": &types.AttributeValueMemberS{
            Value: "john.doe@example.com",
        },
        "Gender": &types.AttributeValueMemberS{
            Value: "Male",
        },
    },
}

_, err := client.PutItem(context.TODO(), input)
if err != nil {
    log.Fatalf("failed to put item, %v", err)
}

注意点として、PutItemAPIは指定した主キーの項目が既に存在する場合、新しい項目で上書きされます。

特定の条件下でのみ項目を追加する場合は、条件式を使用することができます。

詳細については、公式ドキュメントをご覧ください。

データの更新

既存の項目を更新するには、UpdateItemAPIを使用します。

以下の例では、 UserId12345 のユーザのEmailを更新します。

input := &dynamodb.UpdateItemInput{
    TableName: aws.String("Users"),
    Key: map[string]types.AttributeValue{
        "UserId": &types.AttributeValueMemberS{
            Value: "12345",
        },
    },
    ExpressionAttributeValues: map[string]types.AttributeValue{
        ":e": &types.AttributeValueMemberS{
            Value: "new.email@example.com",
        },
    },
    UpdateExpression: aws.String("SET Email = :e"),
    ReturnValues:     types.ReturnValueUpdatedNew,
}

resp, err := client.UpdateItem(context.TODO(), input)
if err != nil {
    log.Fatalf("failed to update item, %v", err)
}

更新条件としてエクスプレッションを使用しています。ここでは SET Email = :e というエクスプレッションを使って、Email属性を新しい値に更新しています。

詳細については、公式ドキュメントをご覧ください。

データの削除

項目を削除するには、DeleteItemAPIを使用します。

以下の例では、 UserId12345 のユーザを削除します。

input := &dynamodb.DeleteItemInput{
    TableName: aws.String("Users"),
    Key: map[string]types.AttributeValue{
        "UserId": &types.AttributeValueMemberS{
            Value: "12345",
        },
    },
}

_, err := client.DeleteItem(context.TODO(), input)
if err != nil {
    log.Fatalf("failed to delete item, %v", err)
}

詳細については、公式ドキュメントをご覧ください。

トランザクション処理

DynamoDBでは、複数の項目操作を一つのトランザクションとして実行することが可能です。TransactWriteItemsAPIを使用します。

以下の例では、新しいユーザを追加し、同時に別のユーザを削除するトランザクションを作成します。

put := &types.TransactWriteItem{
    Put: &types.Put{
        TableName: aws.String("Users"),
        Item: map[string]types.AttributeValue{
            "UserId": &types.AttributeValueMemberS{
                Value: "12347",
            },
            "Name": &types.AttributeValueMemberS{
                Value: "Jane Doe",
            },
            "Email": &types.AttributeValueMemberS{
                Value: "jane.doe@example.com",
            },
            "Gender": &types.AttributeValueMemberS{
                Value: "Female",
            },
        },
    },
}

delete := &types.TransactWriteItem{
    Delete: &types.Delete{
        TableName: aws.String("Users"),
        Key: map[string]types.AttributeValue{
            "UserId": &types.AttributeValueMemberS{
                Value: "12345",
            },
        },
    },
}

input := &dynamodb.TransactWriteItemsInput{
    TransactItems: []types.TransactWriteItem{*put, *delete},
}

_, err := client.TransactWriteItems(context.TODO(), input)
if err != nil {
    log.Fatalf("failed to transact items, %v", err)
}

ここでは、一つのPut操作と一つのDelete操作を一つのトランザクションで実行しています。

詳細については、公式ドキュメントをご覧ください。

さいごに

今回は、GoとDynamoDBを使ったデータ操作について詳しく解説しました。

これらの基本的な操作を理解すれば、より複雑なデータ構造への対応も容易になります。GoとDynamoDBを使用して、効率的でスケーラブルなアプリケーションを開発しましょう。

クエリア

Discussion