DynamoDB는 AWS의 관리형 NoSQL 데이터베이스다. 서버가 필요 없는 서버리스(ServerLess) 환경을 제공한다. 개발자는 가용성, 확장, 성능 등에 대한 고민 없이 개발 할 수 있다.
개발자는 AWS DynamoDB에 접근 할 수 있는 Credential을 가지고 있어야 한다. IAM - AWS Identity and Access Management문서를 참고하자.
테이블 스키마
테스트를 위해서 아래와 같은 테이블을 만들었다. 앨범정보를 정보를 저장하기 위한 테이블이다. 테이블 이름은 Album, 파일이름은 schema.json 이다.
type Album struct {
Artist string `json:"artist"`
Title string `json:"title"`
Createat string `json:"createat"`
TrackList []Track `json:"tracklist"`
}
type Track struct {
Number int `json:"number"`
Playtime int `json:"playtime"`
Name string `json:"Name"`
}
JSON 데이터를 dynamoDB 속성 데이터로 변경하기
DynamoDB는 MongoDB처럼 JSON을 입/출력 데이터 형식으로 사용한다. 하지만 입력된 데이터를 그대로 사용하지 않고, DynamoDB에 맞게 변환한다. 아래와 같은 데이터가 입력된다고 가정해 보자.
package main
import (
"encoding/json"
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/dynamodb"
"github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute"
"os"
)
type Album struct {
Artist string `json:"artist"`
Title string `json:"title"`
Createat string `json:"createat"`
TrackList []Track `json:"tracklist"`
}
type Track struct {
Number int `json:"number"`
Playtime int `json:"playtime"`
Name string `json:"Name"`
}
func main() {
sess, err := session.NewSession(&aws.Config{
Region: aws.String("ap-northeast-2"),
})
if err != nil {
os.Exit(1)
}
svc := dynamodb.New(sess)
in := Album{Artist: "yundream", Title: "title"}
_, err = dynamodbattribute.MarshalMap(in)
if err != nil {
os.Exit(1)
}
params := &dynamodb.GetItemInput{
TableName: aws.String("Album"),
Key: map[string]*dynamodb.AttributeValue{
"artist": {
S: aws.String("yundream"),
},
"title": {
S: aws.String("title"),
},
},
}
result, err := svc.GetItem(params)
if err != nil {
fmt.Println("GetItem ", err.Error())
os.Exit(1)
}
album := Album{}
dynamodbattribute.UnmarshalMap(result.Item, &album)
jsonStr, _ := json.Marshal(album)
fmt.Println(string(jsonStr))
}
Dynamodb.GetItem()는 GetItemOutput struct를 반환한다.
type GetItemOutput struct {
_ struct{} `type:"structure"`
// The capacity units consumed by the GetItem operation. The data returned includes
// the total provisioned throughput consumed, along with statistics for the
// table and any indexes involved in the operation. ConsumedCapacity is only
// returned if the ReturnConsumedCapacity parameter was specified. For more
// information, see Read/Write Capacity Mode (https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ProvisionedThroughputIntro.html)
// in the Amazon DynamoDB Developer Guide.
ConsumedCapacity *ConsumedCapacity `type:"structure"`
// A map of attribute names to AttributeValue objects, as specified by ProjectionExpression.
Item map[string]*AttributeValue `type:"map"`
}
읽은 아이템은 map[string]*AttributeValue 타입이다. 애플리케이션을 만든다면 JSON으로 반환해야 할테니, dynamodbattribute.UnmarshalMap 메서드와 json.Marshal을 이용해서 JSON 형식으로 변환했다. 출력 값은 아래와 같다.
Contents
개발 환경 및 준비
- 우분투 리눅스 19.04
- Go version 1.12
- AWS Cloud 서울 리전
- 데이터베이스 : Amazon DynamoDB
DynamoDB는 AWS의 관리형 NoSQL 데이터베이스다. 서버가 필요 없는 서버리스(ServerLess) 환경을 제공한다. 개발자는 가용성, 확장, 성능 등에 대한 고민 없이 개발 할 수 있다. 개발자는 AWS DynamoDB에 접근 할 수 있는 Credential을 가지고 있어야 한다. IAM - AWS Identity and Access Management문서를 참고하자.테이블 스키마
{ "TableName" : "Album", "KeySchema": [ { "AttributeName": "artist", "KeyType": "HASH" }, { "AttributeName": "title", "KeyType": "RANGE" } ], "AttributeDefinitions": [ { "AttributeName": "artist", "AttributeType": "S" }, { "AttributeName": "title", "AttributeType": "S" } ], "ProvisionedThroughput": { "ReadCapacityUnits": 1, "WriteCapacityUnits": 1 } }# aws dynamodb list-tables { "TableNames": [ "Album", "ToDo" ] }Put Item
{ "title" : "title", "artist" : "yundream", "createat" : "2020.01.05", "tracklist" : [ { "number" : 1, "playtime" : 185, "Name" : "Hello world" }, { "number" : 2, "playtime" : 212, "Name" : "Wonderful world" }, { "number" : 3, "Name" : "Hell of Fire", "playtime" : 198 } ] }type Album struct { Artist string `json:"artist"` Title string `json:"title"` Createat string `json:"createat"` TrackList []Track `json:"tracklist"` } type Track struct { Number int `json:"number"` Playtime int `json:"playtime"` Name string `json:"Name"` }JSON 데이터를 dynamoDB 속성 데이터로 변경하기
{ "id" : "yundream", "email" : "yundream@gmail.com", "point" : 17.5 }{ "Item": { "id": { "S": "yundream" }, "email": { "S": "yundream@gmail.com" }, "point": { "N": 17.5 } } }package main import ( "encoding/json" "fmt" "os" "github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute" ) var sampleData = ` { "id" : "yundream", "email" : "yundream@gmail.com", "point" : 17.5 } ` func main() { type Sample struct { Id string `json:"id"` Emaim string `json:"email"` Point float64 `json:"point"` } in := Sample{} err := json.Unmarshal([]byte(sampleData), &in) if err != nil { fmt.Println("IN : ", err.Error()) os.Exit(1) } inputMap, err := dynamodbattribute.MarshalMap(in) if err != nil { fmt.Println("IN : ", err.Error()) os.Exit(1) } fmt.Printf("%#v\n", inputMap) }map[string]*dynamodb.AttributeValue{"email":{ S: "yundream@gmail.com" }, "id":{ S: "yundream" }, "point":{ N: "17.5" }}package main import ( "encoding/json" "fmt" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/dynamodb" "github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute" "os" ) type Album struct { Artist string `json:"artist"` Title string `json:"title"` Createat string `json:"createat"` TrackList []Track `json:"tracklist"` } type Track struct { Number int `json:"number"` Playtime int `json:"playtime"` Name string `json:"Name"` } var testData = ` { "title" : "title", "artist" : "yundream", "createat" : "2020.01.05", "tracklist" : [ { "number" : 1, "playtime" : 185, "Name" : "Hello world" }, { "number" : 2, "playtime" : 212, "Name" : "Wonderful world" }, { "number" : 3, "Name" : "Hell of Fire", "playtime" : 198 } ] } ` func main() { sess, err := session.NewSession(&aws.Config{ Region: aws.String("ap-northeast-2"), }) if err != nil { os.Exit(1) } svc := dynamodb.New(sess) in := Album{} err = json.Unmarshal([]byte(testData), &in) if err != nil { fmt.Println("IN : ", err.Error()) os.Exit(1) } item, err := dynamodbattribute.MarshalMap(in) if err != nil { fmt.Println("IN : ", err.Error()) os.Exit(1) } input := &dynamodb.PutItemInput{ Item: item, TableName: aws.String("Album"), } _, err = svc.PutItem(input) if err != nil { fmt.Println("input error : ", err.Error()) os.Exit(1) } }# aws dynamodb scan --table-name Album { "Count": 1, "Items": [ { "createat": { "S": "2020.01.05" }, "tracklist": { "L": [ { "M": { "playtime": { "N": "185" }, "number": { "N": "1" }, "Name": { "S": "Hello world" } } } ] }, "artist": { "S": "yundream" }, "title": { "S": "title" } } ], "ScannedCount": 1, "ConsumedCapacity": null }GetItem
package main import ( "encoding/json" "fmt" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/dynamodb" "github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute" "os" ) type Album struct { Artist string `json:"artist"` Title string `json:"title"` Createat string `json:"createat"` TrackList []Track `json:"tracklist"` } type Track struct { Number int `json:"number"` Playtime int `json:"playtime"` Name string `json:"Name"` } func main() { sess, err := session.NewSession(&aws.Config{ Region: aws.String("ap-northeast-2"), }) if err != nil { os.Exit(1) } svc := dynamodb.New(sess) in := Album{Artist: "yundream", Title: "title"} _, err = dynamodbattribute.MarshalMap(in) if err != nil { os.Exit(1) } params := &dynamodb.GetItemInput{ TableName: aws.String("Album"), Key: map[string]*dynamodb.AttributeValue{ "artist": { S: aws.String("yundream"), }, "title": { S: aws.String("title"), }, }, } result, err := svc.GetItem(params) if err != nil { fmt.Println("GetItem ", err.Error()) os.Exit(1) } album := Album{} dynamodbattribute.UnmarshalMap(result.Item, &album) jsonStr, _ := json.Marshal(album) fmt.Println(string(jsonStr)) }type GetItemOutput struct { _ struct{} `type:"structure"` // The capacity units consumed by the GetItem operation. The data returned includes // the total provisioned throughput consumed, along with statistics for the // table and any indexes involved in the operation. ConsumedCapacity is only // returned if the ReturnConsumedCapacity parameter was specified. For more // information, see Read/Write Capacity Mode (https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ProvisionedThroughputIntro.html) // in the Amazon DynamoDB Developer Guide. ConsumedCapacity *ConsumedCapacity `type:"structure"` // A map of attribute names to AttributeValue objects, as specified by ProjectionExpression. Item map[string]*AttributeValue `type:"map"` }# go run main.go | json_pp { "artist" : "yundream", "tracklist" : [ { "Name" : "Hello world", "playtime" : 185, "number" : 1 }, { "playtime" : 212, "Name" : "Wonderful world", "number" : 2 }, { "playtime" : 198, "Name" : "Hell of Fire", "number" : 3 } ], "title" : "title", "createat" : "2020.01.05" }Recent Posts
Archive Posts
Tags