📦
【DynamoDB】Dockerで立てたDynamoDB LocalをGoで扱う
はじめに
DynamoDB Localを簡単に触ってみたので、記事にしてみました。
DynamoDB LocalはCredentials全部ダミーでいいから楽ですね。
また、無料で使えて、キャパシティユニットなども全く気にしなくていいので嬉しいです。
今回はCLIは使わずに、全部コードだけです。
ゴール
docker-compose up
go run main.go
この2つのコマンドだけで、DynamoDBを触る事が出来ること。
環境
- go 1.15
- github.com/aws/aws-sdk-go v1.38.0
- github.com/guregu/dynamo v1.11.0
前提
こちらはある前提で進めます。
インストールなどは事前にお済ませください。
- Dockerが扱える環境であること(インストールなどご用意ください)
- go.mod使用(go mod initなど必要です)
- "github.com/guregu/dynamo"を使用しています。
素のaws-sdkの書き方とは違うので、ご注意ください。
では、早速やっていきます。
ソースコード
docker-compose.yml
こちらは公式から丸パクリです。
GoのアプリケーションもDocker化出来ますが、今回はDynamoDB Localだけです。
version: '3.8'
services:
dynamodb-local:
command: "-jar DynamoDBLocal.jar -sharedDb -dbPath ./data"
image: "amazon/dynamodb-local:latest"
container_name: dynamodb-local
ports:
- "8000:8000"
volumes:
- "./docker/dynamodb:/home/dynamodblocal/data"
working_dir: /home/dynamodblocal
main.go
package main
import (
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/guregu/dynamo"
)
type User struct {
UserID string `dynamo:"UserID,hash"`
Name string `dynamo:"Name,range"`
Age int `dynamo:"Age"`
Text string `dynamo:"Text"`
}
// 本来はenvから取得した方が良い
const AWS_REGION = "ap-northeast-1"
const DYNAMO_ENDPOINT = "http://localhost:8000"
func main() {
// クライアントの設定
sess, err := session.NewSession(&aws.Config{
Region: aws.String(AWS_REGION),
Endpoint: aws.String(DYNAMO_ENDPOINT),
Credentials: credentials.NewStaticCredentials("dummy", "dummy", "dummy"),
})
if err != nil {
panic(err)
}
db := dynamo.New(sess)
// テーブル作成をする為に、一度テーブルを削除します
db.Table("UserTable").DeleteTable().Run()
// テーブル作成
err = db.CreateTable("UserTable", User{}).Run()
if err != nil {
panic(err)
}
// テーブルの指定
table := db.Table("UserTable")
// User構造体をuser変数に定義
var user User
// DBにPutします
err = table.Put(&User{UserID: "1234", Name: "太郎", Age: 20}).Run()
if err != nil {
panic(err)
}
// DBからGetします
err = table.Get("UserID", "1234").Range("Name", dynamo.Equal, "太郎").One(&user)
if err != nil {
panic(err)
}
fmt.Printf("GetDB%+v\n", user)
// DBのデータをUpdateします
text := "新しいtextです"
err = table.Update("UserID", "1234").Range("Name", "太郎").Set("Text", text).Value(&user)
if err != nil {
panic(err)
}
fmt.Printf("UpdateDB%+v\n", user)
// DBのデータをDeleteします
err = table.Delete("UserID", "1").Range("Name", "Test1").Run()
if err != nil {
panic(err)
}
// Delete出来ているか確認
err = table.Get("UserID", "1").Range("Name", dynamo.Equal, "Test1").One(&user)
if err != nil {
// Delete出来ていれば、dynamo: no item found のエラーとなる
fmt.Println("getError:", err)
}
}
解説
簡単に解説していきます。
type User struct {
UserID string `dynamo:"UserID,hash"`
Name string `dynamo:"Name,range"`
Age int `dynamo:"Age"`
Text string `dynamo:"Text"`
}
ここで構造体を定義しています。
dynamoタグをつける事でdynamoテーブルと構造体をうまくマッピングしてくれます。
hash
とつけるとハッシュキーに、range
とつけるとレンジキーになります。
// 本来はenvから取得した方が良い
const AWS_REGION = "ap-northeast-1"
const DYNAMO_ENDPOINT = "http://localhost:8000"
func main() {
// クライアントの設定
sess, err := session.NewSession(&aws.Config{
Region: aws.String(AWS_REGION),
Endpoint: aws.String(DYNAMO_ENDPOINT),
Credentials: credentials.NewStaticCredentials("dummy", "dummy", "dummy"),
})
if err != nil {
panic(err)
}
db := dynamo.New(sess)
コメントにも書いてある通り、リージョンとかは.envから呼び出すなどした方が良いのですが、こちらの方がわかりやすいかと思い、このような記載としています。
os.Getenvなど使われる事をお勧めします。
// テーブル作成をする為に、一度テーブルを削除します
db.Table("UserTable").DeleteTable().Run()
// テーブル作成
err = db.CreateTable("UserTable", User{}).Run()
if err != nil {
panic(err)
}
// テーブルの指定
table := db.Table("UserTable")
// User構造体をuser変数に定義
var user User
この辺りで、テーブルの指定など行っています。
CreateTableする為に、あえて一度テーブル削除してます。
// DBにPutします
err = table.Put(&User{UserID: "1234", Name: "太郎", Age: 20}).Run()
if err != nil {
panic(err)
}
// DBからGetします
err = table.Get("UserID", "1234").Range("Name", dynamo.Equal, "太郎").One(&user)
if err != nil {
panic(err)
}
fmt.Printf("GetDB%+v\n", user)
// DBのデータをUpdateします
text := "新しいtextです"
err = table.Update("UserID", "1234").Range("Name", "太郎").Set("Text", text).Value(&user)
if err != nil {
panic(err)
}
fmt.Printf("UpdateDB%+v\n", user)
// DBのデータをDeleteします
err = table.Delete("UserID", "1").Range("Name", "Test1").Run()
if err != nil {
panic(err)
}
// Delete出来ているか確認
err = table.Get("UserID", "1").Range("Name", dynamo.Equal, "Test1").One(&user)
if err != nil {
// Delete出来ていれば、dynamo: no item found のエラーとなる
fmt.Println("getError:", err)
}
DynamoDB LocalでCRUDしてみました。
レンジキーが無い場合は、ハッシュキーだけの指定で大丈夫です。
Deleteして、本当に削除出来ているか確認する為に、もう一度Getしてます。(ここではエラーになりますが、想定通りです)
結果
コマンド
docker-compose up -d
go run main.go
出力結果
GetDB{UserID:1234 Name:太郎 Age:20 Text:}
UpdateDB{UserID:1234 Name:太郎 Age:20 Text:新しいtextです}
getError: dynamo: no item found
こうなっていれば成功です。
さいごに
- DynamoDB Local思ったより簡単に使えますね。
- 普通のDynamoDBを練習で使うと料金が意外と高くつくので、練習にはDynamoDB Localを使いましょう。
Discussion