FirebaseのCloud Firestoreを使い、サクッとCloud上にDatabaseを構築する

## はじめに

Unityでアプリケーション作成をするに辺り、Cloud上でDatabaseを構築したい！せっかくなので評判のいいFirebaseを使ってみました。

- 対象読者:FirebaseのDatabaseをとりあえず使いたい人
- 書いてないこと: ユーザー認証処理。ここではDatabaseへの更新は管理者が行います。

後日Unityでの利用方法をまとめる予定

## FirebaseのCloud Firestoreとは

[Firebase](https://firebase.google.com/?authuser=0)はGoogleが提供しているPlatform as a serviceで、多数のサービスを提供しています。
その中にDatabaseを扱う為のサービスとして[Firebase Realtime Database](https://firebase.google.com/products/realtime-database/?hl=ja)と今回紹介する[Cloud Firestore](https://firebase.google.com/products/firestore/?authuser=0)があります。

使い分け方も[公式で公開](https://firebase.google.com/docs/database/rtdb-vs-firestore?hl=ja)してくれています。
Realtime Databaseは1 JSONファイルで全てを管理するので、管理データが複雑になると扱いが難しくなります。

一方でCloud Firestoreはコレクション>ドキュメントという階層でデータを管理する形のNoSQL Databaseなので、Realtime Databaseよりも複雑な構造のデータを扱うことが出来ます。
[Cloud Firestore データモデル](https://firebase.google.com/docs/firestore/data-model?authuser=0)

[利用上限](https://firebase.google.com/pricing?authuser=0)も無料で以下なので、個人開発するには十分な量ですね。

1 GiB total
10GiB/month
2 万/日
5 万/日
2 万/日

## 使い方

### プロジェクトとDatabaseの作成
まずはプロジェクトを作成。[トップページ](https://firebase.google.com/?hl=ja)にアクセスし、Googleアカウントでログイン後プロジェクトを作成を選びましょう。
<img width="782" alt="first.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252277/41e8d5df-27a5-4d85-2e3a-565788ccf3d0.png">

作成したプロジェクトを選択して、Cloud Filestoreを作成しましょう。
<img width="809" alt="start.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252277/b91901b7-1cee-bb2d-f175-a168cfddb134.png">

セキュリティルールの設定。後で細かくルールを変えられるので、ロックを選択。
認証を使うならAuthenticationの設定が必要です。
<img width="908" alt="realtime_db.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252277/7bb0b745-2781-383e-a06f-82e747d2b7d1.png">

後はDBを作るロケーションを設定して完了
<img width="532" alt="location.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252277/32e5da08-1522-2227-0f93-6d9bd1dce81e.png">

### Databaseにデータを詰める
Databaseを選ぶとコレクションを追加画面があるので、
<img width="1573" alt="after_creating.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252277/fef10904-87fe-025c-5fa7-b1b857bafcea.png">

コレクションの名前を指定して、
<img width="936" alt="collectin.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252277/6bda7756-10b4-15ca-024e-d168806c47e7.png">

Document、その中のフィールドを指定することでデータを詰めていきます。
<img width="951" alt="document.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252277/8963d063-467b-a140-f0e0-2e2d46591c7c.png">

### とりあえずクライアントからのデータアクセス

プロジェクトへのアクセスは、秘密鍵を生成することで行うことが出来ます。サービスアカウントで新しい秘密鍵の生成を行うと、鍵やDBアクセス先URL等の情報が入ったjsonファイルが取得できます。
<img width="1223" alt="key_configuration.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252277/42b6f5db-4172-8434-269f-12c982666d50.png">

後はこれを使ってアクセス用のコードを書くだけです。使い方は[こちら](https://firebase.google.com/docs/firestore/quickstart?hl=ja)。各言語に合わせたチュートリアルを公式で用意してくれています。
例えばGolangならこんな形でデータの追加、参照、削除が出来ます。

```golang:main.go
package main

import (
	"context"
	"fmt"
	"log"
	"time"

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

func main() {
	// Firebase接続
	sa := option.WithCredentialsFile("path/to/key.json")
	ctx := context.Background()
	app, err := firebase.NewApp(ctx, nil, sa)
	if err != nil {
		log.Fatalln(err)
	}

	// Firestore用のクライアント生成
	client, err := app.Firestore(ctx)
	if err != nil {
		log.Fatalln(err)
	}
	defer client.Close()

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

	//読み込み
	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", err)
		}
		fmt.Println(doc.Data())
	}

	//削除。ここでは書き込みをした新Documentを削除する
	_, err = docRefs.Delete(ctx)
	if err != nil {
		return
	}
}

```

Firebaseのsnippetにもリンクが張ってありますが、様々な言語でのサンプルコードがgithubで公開されています。
https://github.com/firebase?utf8=%E2%9C%93&q=snippets&type=&language=