Node.jsからFirebase RealTime DBを触る

## はじめに
Firebase RealTime Database (以下 RealTime DB) は Google が提供する NoSQL クラウドデータベースです。
これは RealTIme DB をサーバー上のプログラム(Node.js)から読み書きする際の導入記事になります。
この記事は[公式ドキュメント](https://firebase.google.com/?hl=ja)から抜粋及び要約したものであり、より網羅的・体系的な情報が必要な場合には公式ドキュメントを参照してください。

## 利用例
RealTime DB はレイテンシが低く無料プランでは100台までの同時接続及び1GBの容量、10GBまでの転送量が利用可能であるため、個人ユースで複数のクライアント間でデータをやりとりさせるのに適しています。
例えば IoT 機器やスマートフォンのセンサの値を RaspberryPi 上で取得して何らかの処理を行うといったことを想定します。

## 導入
### プロジェクト作成
任意の Google アカウントから Firebase にアクセスしてプロジェクトを作成します。
プロジェクト名と国地域の指定及びチェックボックスへのチェックを要求されます。
今回は適当にプロジェクト名をtestとしました。

![スクリーンショット 2018-06-11 16.42.34.png](https://qiita-image-store.s3.amazonaws.com/0/61751/8710bd36-6abb-9816-7e6e-fa7cf6c5a4ee.png)

### データベース作成
プロジェクト作成完了後プロジェクトのコンソール上でデータベースを作成します。
画面左側に並ぶメニューから `DEVELOP` -> `Database` を選び, `RealTime Database` の `スタートガイド`　(もしくは `使ってみる`) から　`テストモード` でデータベース作成画面に入ります。これは各クライアントから簡易にデータの読み書きを行えるようにするためです。
データベースの作成は画面上でポチポチしても作成できますが予め JSON 形式で設計したものをインポートすることも可能です。
例として以下のように設計した JSON をデータベースとして利用します。

```JSON:サンプルデータベース
{
    "room1": {
        "temperature": 0,
        "humidity": 0
    },
    "room2": {
        "temperature": 0,
        "humidity": 0
    }
}
```
![スクリーンショット 2018-06-11 17.52.03.png](https://qiita-image-store.s3.amazonaws.com/0/61751/2d68f256-bd05-c00a-ed67-a9873e24fe15.png)

## Node.js からの利用
### セットアップ
実行環境に Node.js と npm を導入します。ここでは特に説明しません。
導入後ターミナルまたはターミナルエミュレータ上で以下のコマンドを実行して Node.js 用の Firebase Admin SDK をインストールします。

```
$ npm install firebase-admin
```

### 認証情報の発行
プロジェクトのコンソール上から認証情報を発行します。
`Project Overview 右の歯車`　-> `プロジェクトの設定` -> `サービスアカウント` -> `新しい秘密鍵の生成`
認証情報を含んだ JSON ファイルがダウンロードされるので丁寧に保存します。機密情報なので公開してはいけません。

### 実装
実際にプログラムを書いていきます。
##### 認証部分

まずは認証部分です。適当な js ファイルを作成しテキストエディタで以下を記述します。

```javascript:test.js
var admin = require('firebase-admin');
var serviceAccount = require('認証情報のJSONファイルへのpath');

admin.initializeApp( {
    credential: admin.credential.cert(serviceAccount),
    databaseURL: "https://test-4552f.firebaseio.com" //データベースのURL
} );
```

##### データの取得
認証部分に続けて以下を追記します。

```javascript:test.js

var db = admin.database();
var ref = db.ref("room1"); //room1要素への参照

/*　room1以下に対しての非同期コールバック */
ref.on("value", function(snapshot) {
    /* ここに取得したデータを用いた何らかの処理 */
    console.log(snapshot.val());
}, 
function(errorObject) {
    console.log("The read failed: " + errorObject.code);
} );
```

`on`メソッドの第一引数には読み取りイベントの種類を指定します。
`value`を指定した場合にはプログラム実行時と参照しているデータベースが更新された際にコールバック関数が発火します。
試しにターミナルまたはターミナルエミュレータ上で実行すると以下のように出力されるはずです。

```
$ node test.js
{ humidity: 0, temperature: 0 }
```

ここでプロジェクトのコンソール上から`room1`の`temperture`を変更してみます。

![スクリーンショット 2018-06-11 17.52.16.png](https://qiita-image-store.s3.amazonaws.com/0/61751/7a5c6089-367e-0048-0058-f67ea2c42214.png)

変更が実行中のプログラムに通知されて以下のように出力されるはずです。

```
$ node test.js
{ humidity: 0, temperature: 0 }
{ humidity: 0, temperature: 20 }
```

参照しているデータベース中の任意の要素にアクセスするには以下のようにします。
例: `room1`の`temperature`へのアクセス

```javascript:test.js
ref.on("value", function(snapshot) {
    console.log(snapshot.val().temperature); //またはsnapshot.child("temperature").val()
}, 
function(errorObject) {
    console.log("The read failed: " + errorObject.code);
} );
```

```
$ node test.js
20
```

##### データの更新
認証部分に続けて以下を追記します。
例: `room1`の`humidity`を 10 に更新

```javascript:test.js
var db = admin.database();
var ref = db.ref("room1"); //room1要素への参照

ref.update( {
    "humidity": 10 //更に子の要素にアクセスするには / で区切って指定
} );
```
これを実行してプロジェクトのコンソールからデータベースを確認すると以下のようになっているはずです。
![スクリーンショット 2018-06-11 19.46.49.png](https://qiita-image-store.s3.amazonaws.com/0/61751/88748547-fba4-977f-fc2b-c5dbd3a6ed18.png)