🌬

Firebase Extensionsを使ってFirestoreのデータをリアルタイムにBigQueryへ流し込む

2022/02/25に公開
CHANGELOG
  • 2023.10.03
    • はじめに セクションにてクエリビルダーでの複合条件の表示について追記しました。
  • 2022.02.28
    • import scriptschema-views script セクションを具体例を添えて記載しました。

はじめに

日頃 Firestore を使っていて「一覧を CSV に書き出したい」「複数条件でささっと検索したい」「データを分析したい」という要望は結構あります。ただし、Firebase Console(Google Cloud Console でも同様)の基本的な GUI 操作では一覧表示や単一条件のフィルタ程度しかできません。複合条件でのデータ抽出には クエリビルダー を使って実現できますが、index を貼る手間が必要でクエリにも限界があります。
少し複雑な複合条件での分析をする用途には適しておらず、別のアプローチとして一旦 CSV などに書き出す方法も考えられますが、それ用のスクリプトを作成する必要がありこれもまた手間です。MySQL などの RDB の雰囲気で操作するとちょっとしたデータ確認も簡単にできず、もどかしさを感じるかもしれません。

今回は、Firebase 公式から提供されている Firebase Extensions の1つである Stream Collections to BigQuery を使って、Firestore のデータを BigQuery へリアルタイムに流しこんで BigQuery からデータ閲覧し分析が簡単にできる様子を紹介します。

Stream Collections to BigQuery

Firebase Extensions

Firebase Extensions(2022年2月現在 Beta)はその名の通り Firebase サービスの拡張機能で、Firebase 公式をはじめ Stripe や Algolia などから提供されており、30弱の拡張が存在します(Blaze プランのみ)。
https://firebase.google.com/products/extensions?hl=ja

ドキュメントはこちらです。
Firebase Extensions  |  Firebase Documentation

例えば、

  • Firebase Authentication の削除をトリガーに対応する uid のドキュメントを削除する拡張
  • Cloud Storage にアップロードされた画像のリサイズを行う拡張
  • Firestore が苦手な全文検索を簡単に実現する Algolia との結合拡張
    などがあります。

今回利用する Stream Collections to BigQuery もこの数ある中の1つで、「指定した Firestore コレクションから BigQuery に、リアルタイムな増分更新を送信」する拡張となります。
https://firebase.google.com/products/extensions/firebase-firestore-bigquery-export?hl=ja

実際はこの拡張をインストールするだけで作業自体は完了なのですが、内部では拡張に必要な各サービスやサービスアカウントの生成もまとめて行ってくれます。この辺りを手動で1つずつ設定せずに、コマンド一発で自動生成してくれる点が楽で良いですね。
例えば、Stream Collections to BigQuery であれば Firestore のドキュメントの変更をトリガーに BigQuery へエクスポートするために、内部的には Cloud Functions が生成されます。勿論、それに必要なサービスアカウント(BigQuery の特定 dataset に対する書き込み権限など)も同時に生成されます。

※ちなみに昔は「Export Collections to BigQuery」という名前でしたが、ストリーミングインサートされているのが若干分かりやすい命名に変わりました。
https://twitter.com/h_tsuruo/status/1481161594747105282?s=20&t=9hT_Am9OermU7aeoQ2JTyQ

料金

基本料金: $0.01/month + サービス使用に対する従量課金

You will be charged a small amount (typically around $0.01/month) for the Firebase resources required by this extension (even if it is not used).

無料範囲であれば当然料金はかかりませんが、それを超えた分は各サービス分請求されます。

  • BigQuery (this extension writes to BigQuery with streaming inserts)
  • Cloud Firestore
  • Cloud Functions (Node.js 10+ runtime. See FAQs)

前置きが長くなりましたが、次節から導入していきます。

拡張をインストール

以前は再利用のしやすさから CLI を好んでいましたが、firebase-toolsv9.22.0firebase ext:exportfirebase deploy コマンドが対応したことにより複数環境での再利用性が高まったので、今は GUI ポチポチ操作が楽だと思います。

1. 準備

先に下記2箇所のセットアップが必要です。1つ目は Firestore を利用していれば既に設定されているので問題ないですが、2つ目は「プロジェクトの設定 > 統合 > BigQuery のリンクを押下」が必要です。

  1. Cloud Firestore の有効化
  2. Firebase プロジェクトと BigQuery のリンク

2. 拡張の仕様を確認

この手順は省略可能ですが、行うことを強くおすすめします。
https://firebase.google.com/docs/extensions/install-extensions?hl=ja&platform=console

公式ドキュメントでも推奨されているので、一応インストール前に下記コマンドなどで料金や生成されるアカウントなどの詳細を確認しておくと良いです。

firebase ext:info [extensionName]
# Streams to Collection BigQueryの例だと下記
firebase ext:info firestore-bigquery-export

3. インストール

簡単です。下記の一覧から利用したい拡張を見つけて「Install」ボタンを押下するだけです。

https://firebase.google.com/products/extensions?hl=ja

CLI を使ったインストール
ext:info <extensionInstanceId>
ext:configure [options] <extensionInstanceId>
ext:export [options]
ext:install [options] [extensionName]
ext:list
ext:uninstall [options] <extensionInstanceId>
ext:update [options] <extensionInstanceId> [updateSource]

.envファイルの作成

env ファイルを ext:install [.env] とすることでプロンプトのやりとりをスキップでき、他環境でも同様の設定で使い回せます。各拡張には extension.yaml が用意されているので、それを見ながら必要なパラメータを探して.env を作ります。今回使う「Stream Collections to BigQuery」だと以下になります。
https://github.com/firebase/extensions/blob/master/firestore-bigquery-export/extension.yaml

firestore-bigquery-export-user.env
LOCATION=asia-northeast1
DATASET_LOCATION=asia-northeast1
COLLECTION_PATH=user
DATASET_ID=firestore_export
TABLE_ID=user
# `COLLECTION_PATH`にはサブコレクションの指定もできます
# COLLECTION_PATH=User/{userId}/SubcollectionName

CLIでインストール

firebase ext:install firestore-bigquery-export \
  --params=path/to/params.env \
  --project=projectID-or-alias

インストールの確認や BigQuery Data Editor 付与の確認プロンプトが2,3回でますが全て Yes とすれば、3~5分でインストールが完了します。

※ちなみにこの拡張は、コレクション1つにつき1拡張となるので、複数コレクションをエクスポートしたい場合はその数の拡張をインストールする必要があります(Firebase Extensions | Delete User Data はカンマ区切りで対象のドキュメントを複数できるのでインストールは1回で済みますが、Stream Collections to BigQuery はコレクションごと指定ためか都度インストールが必要です)。

4. エクスポートの確認

下記のような単純な user ドキュメントを追加した場合に

BigQuery にはインストール時に指定した名前のデータセットが生成され、xxx_raw_changelog のテーブルと xxx_raw_latest のビューの存在が確認できると思います。名前の通り前者が「CREATE, UPDATE, IMPORT, or DELETE」の操作の度に追加される全履歴で、後者は changelog からドキュメント別に最新の値のみに絞ったものです。

xxx_raw_latest の中身はこのような形となっています。

フィールド値は全て data の JSON 型としてまとめられます。
このままでは扱いづらいので後述の schema-views script でスキーマビューを作って普段はクエリを発行しています。

{"birthDay":{"_seconds":605890800,"_nanoseconds":0},"blood":"A","name":"a-chan"},
{"birthDay":{"_seconds":601484400,"_nanoseconds":0},"blood":"A","name":"KASHIYUKA"},
{"birthDay":{"_seconds":593276400,"_nanoseconds":0},"blood":"A","name":"NOCCHi"}

複数環境へのデプロイ(任意)

project1の拡張をproject2へインストールするのもこれだけで済む
firebase ext:export --project=[project1Id]
firebase deploy --only extensions --project=[project2Id]

https://firebase.google.com/docs/extensions/reuse-project-config

追加のセットアップ(任意)

import script ~インストール前のデータを補完する~

この拡張の導入はドキュメント作成後でも全てのデータをマイグレートできるように、こちらもしっかりスクリプトが用意されておりますので、それを実行すれば補完できます。Application Default Credentials の認証後に下記コマンドを実行するとプロンプトが表示されるので順に答えていけば良いです。履歴は全て INSERT となり、その後の変更は全て xxx_raw_changelog に追加される形となります。

npx @firebaseextensions/fs-bq-import-collection

https://github.com/firebase/extensions/blob/master/firestore-bigquery-export/guides/IMPORT_EXISTING_DOCUMENTS.md

参考までにプロンプトの中身をコメント付きで見ていきます。

❯ npx @firebaseextensions/fs-bq-import-collection
# プロジェクトIDを入れます。
? What is your Firebase project ID? projectId

# コレクション名を入れます(ex: user)
? What is the path of the the Cloud Firestore Collection you would like to import from? (This may, or may not, be the sa
me Collection for which you plan to mirror changes.) user

# コレクショングループも対応しているのでその場合はYesを選択します(便利!)。
? Would you like to import documents via a Collection Group query? No

# BigQueryのデータセットIDを入力します(ex: firestore_export)
? What is the ID of the BigQuery dataset that you would like to use? (A dataset will be created if it doesn't already exist) firestore_export

# BigQueryのテーブル名のprefixを入力します(ex: user)
# xxx_raw_changelogの`xxx`の部分
? What is the identifying prefix of the BigQuery table that you would like to import to? (A table will be created if one doesn't already exist) user

# 一度に書き込むドキュメント数です。デフォルト300ですが既に大量データがある場合は数値を引き上げると良いです。
? How many documents should the import stream into BigQuery at once? 300

# BigQueryのデータセットのロケーションです(ex: asia-northeast1)
# ref. https://github.com/firebase/extensions/blob/7e235af87aa8327c55677fabdefe5d6bc3e7acc5/firestore-bigquery-export/scripts/import/src/config.ts#L17-L45
? Where would you like the BigQuery dataset to be located? asia-northeast1

# 複数スレッドでimportするかですが、こちらも大量データ以外は基本的にNoで良い気がします。
? Would you like to run the import across multiple threads? No

# 以上で完了です

schema-views script (BigQueryスキーマビューの生成)

xxx_raw_latest の中身はこのような形でとなっており、フィールド値は全てdataのJSON型としてまとめられます。

前述の通りフィールド値は全て data の JSON 型としてまとめられるため、そのままだとクエリを発行しづらい点があります(BigQuery 操作に慣れている方であれば、整形したビューを自分で作って操作すると良いです。JSON 型の扱いは BigQueryのネイティブJSON型がサポートされたことでどう変わったのか を参考にしました)。

BigQuery に慣れていない方も心配せず、本拡張からスクリプトが提供されています。下記ドキュメントに丁寧に記載されており、.json のスキーマファイルを作成して npx コマンド実行して簡単に実行できます。

https://github.com/firebase/extensions/blob/master/firestore-bigquery-export/guides/GENERATE_SCHEMA_VIEWS.md

参考までに例を下記に記載します。

user.json
{
  "fields": [
    {
      "name": "user",
      "type": "string",
    },
    {
      "name": "blood",
      "type": "string",
    },
    {
      "name": "birthDay",
      "type": "timestamp",
    }
  ]
}

上記のスキーマ定義ファイルを用意して、下記コマンドを叩いて完了です。

npx @firebaseextensions/fs-bq-schema-views \
  --non-interactive \ # プロンプトの対話形式が面倒の場合は`--non-interactive`で省けます
  --project=projectId \ # プロジェクトID
  --dataset=firestore_export \ # データセットID(ex: firestore_export)
  --table-name-prefix=user \
  --schema-files=./user.json # スキーマ定義ファイルのパス

以上で、xxx_schema_xxx_changelogxxx_schema_xxx_latest の2つのビューが生成されます。
ちなみに、xxx_raw_changelog と同じデータセットを指定する必要があり、他のデータセットを指定すると下記エラーが出力されてビューの生成に失敗するので注意です。

# ビュー用に`firestore_export_schema`という別のデータセットIDとして指定した場合
Not found: Table projectId:firestore_export_schema.user_raw_changelog

終わりに

コンソールポチポチでインストールできますし、権限周りを適切に設定さえできれば提供されている簡単なスクリプト実行ですぐにマイグレートできるので、導入も簡単です。また、BigQuery はデータセット単位などで細かく権限設定が行えるので、例えばカスタマーサポート対応などで担当者に本番データを調査してもらう際などは Firebase コンソールにアクセスすることなく業務を任せることができ、権限管理の観点からも良い選択肢だと思います。

Firestoreデータを書き出す他の方法

リアルタイムである必要がなく下記のような要求であれば、Cloud Storage などに定期的にバックアップするついでにエクスポートする形の方が良いかもしれません。

日頃Firestoreを使っていて「一覧をcsvに書き出したい」「複数条件でささっと検索したい」「データを分析したい」という要望は結構あると思います。

  • リアルタイム性が必要ない(例えば毎日0:00定時でバックアップをとる)などであれば、おそらくこの方法で十分です
  • Cloud Storage のバケットを直接 BigQuery から参照もできるらしいので多少のデータラグを許容できるのであればこちらもありです。

https://cloud.google.com/bigquery/docs/loading-data-cloud-firestore

この辺りはまだ自分でセットアップしたことがないので、時間見つけて触ってみようと思います。

参考

Discussion