Firebase Database 今までは、Realtime DatabaseというDBが存在しました。

Firebase Realtime Database はクラウドでホスティングされるデータベースです。データは JSON として保存され、接続されているすべてのクライアントとリアルタイムで同期されます。iOS、Android、JavaScript SDK を使用してクロスプラットフォーム アプリを構築した場合、すべてのクライアントが、1 つの Realtime Database インスタンスを共有して、最新のデータによる更新を自動的に受信します。

最近、Cloud Firestore が登場しましたので、こちらをGoで軽く触って見ます。

この記事は、公式: Cloud Firestoreを使ってみる にかかれている内容とほぼおなじです。

まずは必要なパッケージをインストール

$ dep init
$ dep ensure -add firebase.google.com/go
$ dep ensure -add google.golang.org/api/option

Firestore Clientを作ってみる

import (
	firebase "firebase.google.com/go"
	"google.golang.org/api/option"
)

func main() {
    opt := option.WithCredentialsFile("./serviceAccountKey.json")
    ctx := context.Background()
    app, err := firebase.NewApp(ctx, nil, opt)
    if err != nil {
        fmt.Fprintf(w, "error initializing app: %v", err)
        return
    }

    client, err := app.Firestore(ctx)
    if err != nil {
        log.Fatalln(err)
    }
    defer client.Close()
}

serviceAccountKey.json はこちらから取得します。

https://console.firebase.google.com/u/0/project/< PROJECT ID >/settings/serviceaccounts/adminsdk の新しい秘密鍵を生成をクリックして取得。

それではDBに書き込んでみよう

_, _, err = client.Collection("users").Add(ctx, map[string]interface{}{
        "first": "Ada",
        "last":  "Lovelace",
        "born":  1815,
})
if err != nil {
        log.Fatalf("Failed adding alovelace: %v", err)
}

ここでは、users コレクションに、データを追加しています。 first, last, boarn というkeyに対して値を入れています。

初めて実行したら

このように、Userコレクションが作成され、データも追加されました。

スキーマ変更

		_, _, err = client.Collection("users").Add(ctx, map[string]interface{}{
			"first":  "Alan",
			"middle": "Mathison",
			"last":   "Turing",
			"born":   1912,
		})
		if err != nil {
			log.Fatalf("Failed adding alovelace: %v", err)
		}

先程の、フィールドにmiddleを追加してみます。 Firestoreでは、スキーマ定義が不要なので、必要があれば追加・削除をする事ができます。 とはいえ、Golangでは構造体で扱いたいなどありますので、あまり変更しすぎても辛いだけですが。

map[string]interface って便利だけど、参照する観点では型が無く辛い事も多そう。

変更した結果

最後に取得してみる

iter := client.Collection("users").Documents(ctx)
		for {
			doc, err := iter.Next()
			if err == iterator.Done {
				break
			}
			if err != nil {
				log.Fatalf("Failed to iterate: %v<br>", err)
			}
			fmt.Fprintf(w, "%v<br>", doc.Data())
		}

実行した結果

map[first:Alan born:1912 middle:Mathison last:Turing]
map[last:Lovelace first:Ada born:1815]

この様な結果となりました。 途中で書きましたが、取得時点では map[string]interface と型が何とでもなる状態ですので、このまま使う場合は色々キャストしていく必要があります。 もしくは互換性を持って構造体を拡張していくなどでもよさそうです。

おわり。