LoginSignup
1
1

More than 1 year has passed since last update.

AWS日記③ (DynamoDB)

Last updated at Posted at 2020-05-10

はじめに

今回はDynamoDBを利用して簡易な掲示板を作成します。

準備

DynamoDBのテーブルを作成します。
[Lambda , API Gatewayの準備をします。]
(https://qiita.com/tanaka_takurou/items/3f93295de6cff060ec09)

[参考資料]
テーブルの作成
DynamoDBのテーブル作成

WEBページ・API作成

GO言語のAWS Lambda関数ハンドラー aws-lambda-go を使用してHTMLやJSONを返す処理を作成します。
また、DynamoDB を使用するため aws-sdk-go を利用します。

[参考資料]
AWS SDK for Go API Reference
あえて aws-sdk-go で dynamoDB を使うときの基本操作
Reading an Amazon DynamoDB Table Item

今回は、ページ用とAPI用のLambda関数を別々に作成し、ページ用のメソッドはGET、API用のメソッドはPOSTに設定しました。
apigateway.jpg

要素を取得する際にはScanを使う。
main.go
func scan(tableName string, filt expression.ConditionBuilder)(*dynamodb.ScanOutput, error)  {
        sess := session.Must(session.NewSessionWithOptions(session.Options{
                SharedConfigState: session.SharedConfigEnable,
        }))
        svc := dynamodb.New(sess)
        expr, err := expression.NewBuilder().WithFilter(filt).Build()
        if err != nil {
                return nil, err
        }
        params := &dynamodb.ScanInput{
                ExpressionAttributeNames:  expr.Names(),
                ExpressionAttributeValues: expr.Values(),
                FilterExpression:          expr.Filter(),
                ProjectionExpression:      expr.Projection(),
                TableName:                 aws.String(tableName),
        }
        return svc.Scan(params)
}

func getMessageList(room_id int, threshold int)([]MessageData, error)  {
        var messageList []MessageData
        result, err := scan(messageTableName, expression.Name("room_id").Equal(expression.Value(room_id)))
        if err != nil {
                return nil, err
        }
        for _, i := range result.Items {
                item := MessageData{}
                err = dynamodbattribute.UnmarshalMap(i, &item)
                if err != nil {
                        return nil, err
                }
                if item.Status >= threshold {
                        continue
                }
                messageList = append(messageList, item)
        }
        return messageList, nil
}
要素を挿入する際にはPutItemを使う。
main.go
func put(tableName string, av map[string]*dynamodb.AttributeValue) error {
        sess := session.Must(session.NewSessionWithOptions(session.Options{
                SharedConfigState: session.SharedConfigEnable,
        }))
        svc := dynamodb.New(sess)
        input := &dynamodb.PutItemInput{
                Item:      av,
                TableName: aws.String(tableName),
        }
        _, err := svc.PutItem(input)
        return err
}

func putMessage(room_id int, user string, message string, icon_id int) error {
        t := time.Now()
        count, err := getMessageCount(room_id)
        if err != nil {
                return err
        }
        item := MessageData {
                Message_Id: int(*count) + 1,
                Room_Id: room_id,
                Icon_Id: icon_id,
                Status: 0,
                User: user,
                Message: message,
                Created: t.Format(layout),
        }
        av, err := dynamodbattribute.MarshalMap(item)
        if err != nil {
                return err
        }
        err = put(messageTableName, av)
        if err != nil {
                return err
        }
        return nil
}
要素を更新する際にはUpdateItemを使う。
main.go
func update(tableName string, an map[string]*string, av map[string]*dynamodb.AttributeValue, key map[strin
g]*dynamodb.AttributeValue, updateExpression string) error {
        sess := session.Must(session.NewSessionWithOptions(session.Options{
                SharedConfigState: session.SharedConfigEnable,
        }))
        svc := dynamodb.New(sess)
        input := &dynamodb.UpdateItemInput{
                ExpressionAttributeNames: an,
                ExpressionAttributeValues: av,
                TableName: aws.String(tableName),
                Key: key,
                ReturnValues:     aws.String("UPDATED_NEW"),
                UpdateExpression: aws.String(updateExpression),
        }

        _, err := svc.UpdateItem(input)
        return err
}

func updateMessage(message_id int, value int, name string) error {
        an := map[string]*string{
                "#s": aws.String(name),
        }
        av := map[string]*dynamodb.AttributeValue{
                ":new": {
                        N: aws.String(strconv.Itoa(value)),
                },
        }
        key := map[string]*dynamodb.AttributeValue{
                "message_id": {
                        N: aws.String(strconv.Itoa(message_id)),
                },
        }
        updateExpression := "set #s = #s + :new"
        err := update(messageTableName, an, av, key, updateExpression)
        if err != nil {
                return err
        }
        return nil
}

作成したLambda 関数、テンプレート

終わりに

DynamoDBは NoSQLのため慣れるまでは扱いにくく感じましたが、メリットが多くあります。
[参考資料]
DynamoDBを使いこなして精神的安定を手に入れた

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1