121
91

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Go その2Advent Calendar 2015

Day 25

気楽にDynamoDBを使おう

Last updated at Posted at 2015-12-25

Merry Christmas! gureguです。kamimogiの作者です。
最近開発しているDynamoDBのライブラリーを紹介しようと思います。

DynamoDBとは

DynamoDBはAmazon Web ServicesのNoSQLデータベースです。安くてスケールしやすいのが特徴です。DynamoDBの基本知識については、@kenichi_nakamuraさんのこの記事を読んでください

aws-sdk-go

AWSの公式がライブラリー。最近やっと1.0になりました!aws-sdk-goでは、DynamoDBへの問い合わせはできるが、かなり面倒臭いことをやらなきゃいけない。公式のライブラリーはポインターだらけで、データのMarshalとUnmarshalで苦労することがあります。

Introducing dynamo

dynamoは、DynamoDBを使いやすくするライブラリーです。シンプルに言うと、dynamoaws-sdk-goのラッパーです。MongoDBのmgoにインスパイアされて、よくやる処理をfluentなAPIで、やりやすくしたライブラリーです。aws-sdk-godynamoは簡単に一緒に使えます。

dynamoを作ったきっかけは、グノシー漫画のログなどの保存のためです。今でもプロダクションで使われています!

Examples

Userが何かしらのアクションを記録するデータベースがあるとします。

Actionsというテーブル名にしましょう。

Key Name Type
Hash UserID Number
Range Date String

数字のUserIDに対する日付のついたイベントを保存します。

イベントはこういうstructで表現できます。

type Event struct {
	UserID    int `dynamo:"User"`
	Date      time.Time
	Action    string         
	Points    int    
	Hidden    bool `dynamo:"-"`         
}

encoding/jsonと同じように、struct tagにより、DynamoDBのAttribute Nameを指定できます。dynamo:"-"の場合は、その値を保存しないで無視されます。

セットアップ

dynamo.New()にAWSのsessionとconfigを渡します。

import (
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/guregu/dynamo"
)

func main() {
	db := dynamo.New(session.New(), &aws.Config{
		Region: aws.String("ap-northeast-1"),
	})
	table := db.Table("Actions")
	// ...
}

Put

簡単です!

evt := Event{UserID: 42, Date: time.Now().UTC(), Action: "test"}
err := table.Put(evt).Run()
// check err...

条件もつけられます。例えば、これで上書きできなくなります。(新規保存のみ可能)

evt := Event{UserID: 42, Date: time.Now().UTC(), Action: "test"}
err := table.Put(evt).If("attribute_not_exists(ID)").Run() // IDがHash Keyだから

条件について詳しく知りたい方はこちらへどうぞ

Get

dynamoでは、DynamoDBのQueryとGetItemのAPIは一緒になっています。

一つのアイテム

Hash KeyとRange Keyを指定しないといけません。一つだけの場合はOneを使います。

var result Event
err := table.Get("UserID", 42).Range("Date", dynamo.Equal, "2015-12-24T...").One(&result)

複数のアイテム

UserID = 42のアイテムを全て取得します。

var results []Event
err := table.Get("UserID", 42).All(&results)

Filterもかけられます。これで、User 42の12月以前のアクションを取得します。

var results []Event
err := table.Get("UserID", 42).Filter("'Date' < ?", "2015-12-01").All(&results)

DateはDynamoDBの予約語なので、Single Quotes('')をつけないといけません。
Attribute Valuesは、はてな(?)をplaceholderとして使う必要があります。

Update

Updateで、Attribute単位の変更ができます。
一回の処理で、AddUpdateSetをいくつも実行できます。

例えば、これはatomicなカウンターです。


type Counter struct {
	Table dynamo.Table
	Name  string
}

func (c Counter) Next() (int64, error) {
	type count struct {
		Name  string
		Count int64
	}

	var result count
	err := c.Table.Update("Name", c.Name).Add("Count", 1).Value(&result)
	return result.Count, err
}

// ...
ctr := Counter{table, "UserIDs"}
nextID, err := ctr.Next()

update.Value()を使うと、変更後の値の取得ができます。

Delete

Range KeyのあるテーブルはRange Keyの指定が必要です。

err := table.Delete("UserID", 42).Range("Date", "2015-12-24...").Run()

削除した値も取得できます。

var oldValue Event
err := table.Delete("UserID", 42).Range("Date", "2015-12-24...").OldValue(&oldValue)

ちなみに、UpdateもOldValueが使えます!

終わりに

BatchGetもBatchWriteも、UpdateとGetの色々な機能もあります! ぜひドキュメントを見てみてください!

dynamoにてIssueとPull Requestが募集中!
https://github.com/guregu/dynamo

DynamoDBのFree Tierは無限なので、DynamoDBは無料運用にとても便利なデータベースだと思います!

121
91
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
121
91

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?