Firestoreのデータを分析するための3つの方法とその注意点

[別の記事](https://qiita.com/kira_puka/items/ef80b07347cfdd37f116)を書く前に、いろいろ試したことの備忘録。
Firestoreのデータをいろいろ見たかったけど、
別プロジェクトの移動してみることにした経緯のまとめ。

## 試したのは以下の3つ

1. エクスポートデータをBigQueryにインポートしてBigQuery上で確認
2. [node-firestore-import-export](https://github.com/jloosli/node-firestore-import-export)を使ってローカルのJSONファイルとしてエクスポートして確認
3. 別プロジェクトにデータを移行して、別プロジェクト上で確認([この記事](https://qiita.com/kira_puka/items/ef80b07347cfdd37f116))

それぞれの方法と注意点は以下の通り。

### 1. BigQueryにインポートして確認

[公式ドキュメント](https://cloud.google.com/bigquery/docs/loading-data-cloud-firestore?hl=ja)などで紹介されている通り、
FirestoreのデータをBigQueryにインポートできるらしい。

これが一番いい方法だが、後述するカラム10000制約に引っかかったので、諦める形に。。

#### 流れとしては、こんな感じ。

1. バックファイルファイルを配置できるようCloud StorageにBucketを作成
1. gcloudを使って、Firestoreのバックアップファイルを作成したBucketにエクスポート
2. BigQueryでデータセットを作成
3. テーブルを作成する際に、テーブル作成元に「Google Cloud Storage」を選択

#### 注意: ハマった点

##### a. バックアップデータを作成する際は、collection-idsを指定しないといけない

[公式ドキュメント](https://cloud.google.com/bigquery/docs/loading-data-cloud-firestore?hl=ja)にも書いてあるが以下の通りらしい。。

> エクスポート コマンドには、**collection-idsフィルタを指定する必要があります**。
> コレクションIDフィルタを指定せずにエクスポートされたデータをBigQueryに読み込むことはできません。

なので、バックアップする際は、こんな感じで、コレクションを指定しなければならない。

```console
$ gcloud beta firestore export gs://[BUCKET_NAME] --collection-ids=[COLLECTION_ID_1],[COLLECTION_ID_2]
```

##### b. ファイル形式も「Cloud DataStoreバックアップ」に変更しないといけない

[公式ドキュメント](https://cloud.google.com/bigquery/docs/loading-data-cloud-firestore?hl=ja)のスクリーンショットになかったのでハマった。。

![スクリーンショット_2019-09-24_19_50_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/a9eac817-3145-5784-865e-756c50ec5109.png)


インポートする際には、ファイル形式も「Cloud DataStoreバックアップ」に変更しないといけないらしい。。
なにもしていないと、ファイル形式「Avro」になっているので、ファイル形式が合わずエラーになってしまう。。

##### c. ドキュメントフィールドがobjectの場合、ドット区切りで展開され、カラムの上限は10000まで

これが原因で諦めました。。

Firestore上で、以下のようなobjectやマップなどが存在すると、

```json
{
  "uid": "XXXXX",
  "group": {
    "groupA": true,
    "groupB": false
  }
}
```

BigQueryにインポートする際、ドットで繋げる形で展開されます。

```csv
uid, group.groupA, group.groupB
```

また、[公式ドキュメント](https://cloud.google.com/bigquery/docs/loading-data-cloud-firestore?hl=ja)の制約事項に、

> Cloud Firestore のエクスポートを正しく読み込むには、
> エクスポートデータ内のドキュメントが一貫したスキーマを共有し、
> 個別のフィールド名が**10,000個未満**でなければなりません。

と、あるため、大量のプロパティを持つobjectをセットしていると、インポート時にエラーになります。。

**対応策**

フィールド数の問題を回避する方法として、特定のフィールドだけ読み込むこともできます。

>  CLI で --projection_fieldsフラグを使用するか、
>  load ジョブの構成でprojectionFieldsプロパティを設定することで
>  特定のフィールドを読み込むことができます。

とあるため、読み込むフィールドを指定することで、回避することができそうです。


## 2. [node-firestore-import-export](https://github.com/jloosli/node-firestore-import-export)でローカルにエクスポート

次にやったのがこれ。
[node-firestore-import-export](https://github.com/jloosli/node-firestore-import-export)を使うと、CUIでJSON形式でエクスポートできるらしい。
JSON形式でエクスポートできれば、ツールなど作っていろいろできそうかなと。

実行するには、Google Cloudアカウントのcredentialsファイルが必要。

```console
# インストール
$ npm install -g node-firestore-import-export

# 全体のバックアップ
firestore-export --accountCredentials path/to/credentials/file.json --backupFile backups_myDatabase.json

# コレクションを指定して、一部だけをエクスポート
firestore-export --accountCredentials path/to/credentials/file.json --backupFile backups_myDatabase.json　--nodePath collectionA
```

データ量が多い場合は、`--max_old_space_size`を指定して実行する。

```
node --max_old_space_size=8192 /usr/local/bin/firestore-export --accountCredentials path/to/credentials/file.json --backupFile backups_myDatabase.json
```

#### 注意: というか見送った点。。

サクッと使えてよかったけど、データ量が多いと、やはりつらい。。

1. データ量が多いと、メモリ不足やFirestoreとのコネクション切れで失敗する
2. 無料枠でも使えるが、firebase-adminを使って取ってきているだけなので読み込みが大量に発生する
3. エクスポートしたファイルも大きくなるため、ツールでもメモリを大量に使う

### 別プロジェクトにデータを移行して、別プロジェクト上で確認

上の2つの方法を試してなんとかしたかったのは、このの3つ。

1. エクスポート時に大量の読み込みが発生し、**本番環境の無料枠を消費する**
2. **ネストが深いobjectがあると**と簡単にBigQueryにインポートできない
3. ローカルファイルでも全データをメモリ上に展開するので、つらい

そのため、別プロジェクトに移行して、本番環境と関係ない部分で、いろいろ触れるようにしてみた。
これであれば、本番環境を気にせず、firebase-adminとかで、いろいろ調べたりできそう。

詳細なやり方は、[別の記事](https://qiita.com/kira_puka/items/ef80b07347cfdd37f116)にまとめました。

他と同様、リアルタイムの情報ではないので、注意が必要。

## 簡単なまとめ

##### 1. BigQueryにインポートして確認

- BigQuery上なので、SQLで分析ができる
- 有料プランのみ
- **注意**: バックアップデータを作成する際は、collection-idsを指定しないといけない
- **注意**: ファイル形式も「Cloud DataStoreバックアップ」に変更しないといけない
- **注意**: ドキュメントフィールドがobjectの場合、ドット区切りで展開され、カラムの上限は10000

##### 2. [node-firestore-import-export](https://github.com/jloosli/node-firestore-import-export)でローカルにエクスポート

- 無料枠でも使える
- JSONでエクスポートできる
- **注意**: エクスポート時に大量の読み込みが発生し、本番環境の無料枠を消費する
- **注意**: ドキュメントのネストが深いと簡単にBigQueryにインポートできない
- **注意**: ローカルファイルでも全データをメモリ上に展開するのでつらい


##### 3. 別プロジェクトにデータを移行して、別プロジェクト上で確認([この記事](https://qiita.com/kira_puka/items/ef80b07347cfdd37f116))

- 有料プランのみ
- 別プロジェクトなので、本番環境を気にせず使える


## こんなのつくってます!!

積読用の読書管理アプリ 『積読ハウマッチ』をリリースしました！
[積読ハウマッチ](https://tsundoku.site)は、Nuxt.js+Firebaseで開発してます!

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/572d4947-f40b-e4dc-1c9c-bc584cd2a66c.png" width="200"/>

もしよかったら、遊んでみてくださいヽ(=´▽`=)ﾉ

要望・感想・アドバイスなどあれば、
公式アカウント([@MemoryLoverz](https://twitter.com/MemoryLoverz))や開発者([@kira_puka](https://twitter.com/kira_puka))まで


# 参考にしたサイト

- [データのエクスポートとインポート  |  Firebase](https://firebase.google.com/docs/firestore/manage-data/export-import?hl=ja)
- [Cloud Firestoreのバックアップ・リストア - google-cloud-jp - Medium](https://medium.com/google-cloud-jp/firestore-backup-67327a74cd54)
- [gcloudのアカウント変更とプロジェクト変更｜yo16｜note](https://note.mu/yo16/n/ne25615bab8f5)
- [自分用GCPコマンドリファレンス - Qiita](https://qiita.com/ShuA/items/1ff83b8d804168b087ba)
- [gcloudの自分用メモ - Qiita](https://qiita.com/Takakuwa-Shun/items/ac455c96a81a189eacce)
- [gcloudコマンド（GCP）で複数のプロジェクトとアカウントの使い分けを便利に - Adwaysエンジニアブログ](https://blog.engineer.adways.net/entry/2018/06/08/150000)
- [macosにgcloudとkubectlのインストール - Qiita](https://qiita.com/sakamossan/items/8ff74ed377dc77325b80)
- [macOS 用のクイックスタート  |  Cloud SDK のドキュメント  |  Google Cloud](https://cloud.google.com/sdk/docs/quickstart-macos?hl=ja)
- [Cloud Firestore のエクスポートからのデータの読み込み  |  BigQuery  |  Google Cloud](https://cloud.google.com/bigquery/docs/loading-data-cloud-firestore?hl=ja)
- [エクスポートされたFirestoreドキュメントをBigQueryに自動ロード - google-cloud-jp - Medium](https://medium.com/google-cloud-jp/firestore-bigquery-3b887a5bc27e)
- [Cloud Firestore のコレクションを日次で Bigquery にロードする - Qiita](https://qiita.com/kurikei/items/ece7f6a21115494386c9)