🔎

BigQueryとデータポータルで、Firestoreのデータを分析する

2021/05/25に公開2

はじめに

個人開発しているサービスで、追加した機能の効果測定がしたいと思ったので、データ分析の仕組みを整えることにしました。

実現手段の検討

分析したい内容を決める

まず、分析したい内容を決め、取得したいデータの内容を決定します。これはサービス個別の内容なので省略します。

Firestoreのデータをどう分析するか

DBにFirestoreを使用しているので、Firestoreからどうやってデータを取得して表示するか考えました。

[却下] 管理画面を作って、そこにデータを表示する

管理画面用にFirestoreのセキュリティールールを作成したり、いちいちFunctionsでデータを取得してくるのは面倒なので却下。

[却下] GASを使って、Google Spredsheetに表示

Fuctionsでデータを加工、取得してきて、それをGASでゴニョゴニョして、Googleスプレッドシートに表示するのも、面倒なので却下。

[却下] Google Analyticsにイベントを送信して、Analyticsでグラフ化

この方法がマッチするケースもあると思いますが、必要なデータをGoogle Analyticsに送信しないといけないので、柔軟性に欠けます。今回の用途では却下。蛇足ですが、この方法はFirestoreとは関係ないですね。。

[採用] BigQueryにデータをインポートし、データポータルで可視化

FirestoreのコレクションをBigQueryに自動でインポートしてくれるExtensionを発見。簡単に導入できて、BigQueryで分析も柔軟にできる。さらに、データポータルでデータの可視化も簡単にできそう。採用!!

でも、お高いんでしょ?

BigQueryなので、お値段もBigじゃないの?ということで料金を調べてみました。

https://cloud.google.com/bigquery/pricing?hl=ja

今回の使用用途の場合、無料枠じゃないのは、データ取り込み部分だけのようです。使ってみないと分からないので、あくまで見込みです。

米国(マルチリージョン)の場合、ストリーミング挿入(tabledata.insertAll)で $0.010 per 200 MB かかるようです。

サービス規模が小規模で、データの挿入量も小規模なので、おそらく1ヶ月数円で済むと思われます。

お安いですね!

実践

Export Collections to BigQueryをインストール

このExtensionを使えば、Firestoreの特定のコレクションを指定して、自動でBigQueryにインポートできます。

https://firebase.google.com/products/extensions/firestore-bigquery-export/

コンソールからExtensionをインストール

Extensionページに「Install in console」というボタンがあるので、そこからインストールします。

Cloud Functions location

Functionsのロケーションは、通常のFunctionsやFirestoreをTokyoロケーションで使用しているで、同じくTokyoロケーションにしました。

BigQuery Dataset location

BigQueryのロケーションも、ドキュメントを読むと、同じロケーションにしておいた方が良さそうだったので、Tokyoロケーションにしました。

https://cloud.google.com/bigquery/docs/locations

他の方のインストール記事を見ると、以前はこの項目が存在しなかったようです。BigQueryのロケーションを指定したい場合は、先にデータセットを作る必要があったようですが、今はその必要はなく、ここでロケーションを指定できるようになっています。

Collection path

エクスポートしたいFirestoreのCollection pathを指定します。複数のコレクションをエクスポートしたい場合は、複数のExtensionをインストールする必要があります。

Dataset ID

Datasetとは何が分からなかったので、軽く調べたところ、データベースのDB名みたいなものでした。デフォルトのまま、「firestore_export」にしています。複数のExtensionをインストールした場合も同じDataset名を指定すれば、そのDatasetにデータをインポートしてくれます。

https://dev.classmethod.jp/articles/gcp-bigquery-dataset-overview-studying/

Table ID

DatasetのTable名です。基本的には、FirestoreのCollection名と同じ名前で良いと思います。

しかし、FirestoreのCollection名をpostCommentsのようにキャメルケースで指定していた場合には注意が必要です。

BigQueryでは、テーブル名の後ろにスネークケースでpostfixが付くテーブルやビューが自動生成されます。

  • 生の変更ログテーブル: ${param:TABLE_ID}_raw_changelog
  • 最新のビュー: ${param:TABLE_ID}_raw_latest

もし、テーブル名をpostCommentsに設定しまうと、 postComments_raw_changelog というテーブル名になり、むず痒い思いをすることになります。

僕は初めにキャメルケースでテーブル名を指定していたのですが、後でスネークケースに変更しました。テーブル名は幸いにも後で変更することができました。

BigQuery SQL table partitioning option

データを取り込み時間によってパーティショニングすることができます。hour, day, month, yearから選択できます。

現状であれば、データ量が少ないのでパーティショニングなしで全く問題ないですが、エクスポートしたCollectionの性質上、年をまたいでクエリを叩きたくなることはあまりないので、yearに設定しておきました。

https://dev.classmethod.jp/articles/bigquery-partition-table-for-cost-cut/

インストール後の手順

インストールには、3-5分かかります。

下記のドキュメントのリンクが表示されました。
https://github.com/firebase/extensions/blob/master/firestore-bigquery-export/POSTINSTALL.md

インストール完了後、BigQueryのコンソールを開き、上記のURLに載っているSQLを叩くと、データが参照できます。

(Option) 既存ドキュメントはインポートする必要がある

このExtensionは、変更されたドキュメントのコンテンツのみを送信します。既存のドキュメントの完全なデータセットをBigQueryにエクスポートすることはありません。

Extensionをインストールする前に既に登録済みのドキュメントがあり、それらもインポートしたい場合は、下記の手順を踏む必要があります。

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

手順通りに行っていけばできるのですが、1点分かりにくい部分があったので解説します。

インポートコマンド( npx @firebaseextensions/fs-bq-import-collection )を実行した後、ターミナルで対話的に情報を入力していきます。

? What is the path of the the Cloud Firestore Collection you would like to import from? (This may, or may not, be the same Collection for
which you plan to mirror changes.)

途中で、この質問が出るのですが、subCollectionを追加したい場合、posts/{postid}/postComments のように入力するとエラーが出ます。

subCollectionを入力したい場合は、postComments とだけ入力する必要がありました。

? Would you like to import documents via a Collection Group query?

そして次の質問でこう聞かれるので、Yes と回答する必要があります。

https://github.com/firebase/extensions/issues/17#issuecomment-568587826

(Option) 別のCollectionもインポートする

別のCollectionもインポートしたい場合は、もう1つExtensionをインストールする必要があります。1つのExtensionで1つのCollectionをインポートできる仕組みになっています。

2つ目のインストール時には、ExtensionのインスタンスIDを入力する必要があります。

その他は、1つ目と同じ手順です。

スキーマビューを作成する

BigQueryの ${param:TABLE_ID}_raw_latest の中身をSQLを叩いて見てみると、FirestoreのデータはJSONで格納されており、見辛いです。また、JSONに対して、SQLを発行するのはクエリを書くのが面倒です。

そのため、ビューを作成します。

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

上記URLに書いてある手順を実行すれば、スキーマビューを作成できます。

つまづいた点としては、JSONの型定義が間違っており、データが全部nullで表示されてしまったということがありました。型定義が間違っていると、例えデータが存在していたとしてもnullとなります。

データは存在するのにスキーマビューにデータが表示されないなというときは、スキーマの型定義が合っているか確認してみてください。

また、スキーマビューのテーブル名は下記のような命名規則になります。

${param:TABLE_ID}_schema_${json_file_name}_changelog
${param:TABLE_ID}_schema_${json_file_name}_latest

テーブル名と、JSONファイル名を同じにすると、微妙な名前になってしまいます。これが正しいかは分かりませんが、僕の場合は、JSONファイル名は、 default.json としました。一番基本のスキーマービューはdefaultで、後で別のスキーマビューを追加したくなったら、別の名前で追加しようと考えています。

データポータルでグラフ化

BigQueryのデータをデータポータルで加工して表示することができます。表示したかったデータをスプレッドシートの表のような形式で表示することができました。グラフ化については、また今度やってみたいと思います。

https://cloud.google.com/bigquery/docs/visualize-data-studio?hl=ja

データポータルは最初はとっつきにくく、どうすればいいか全然分かりませんでしたが、適当に動かしながら、やりたいことをググれば、なんとか作りたいものを作れました。

データポータルは設定変更を行うとすぐにグラフに反映されるのですが、それが反映されなくなることがあり、自分の設定内容が原因だと色々試していたのですが、試しにリロードしてみたところ、うまく表示できるようになりました。即時反映されなくなったら、リロードを試してみることをお勧めします。

今回は、2つのFirestoreコレクションを、BigQueryにインポートしたのですが、そのコレクション同士をLEFT JOINして表示することも、SQLを書かずにデータポータルの設定だけで実現することができました。

https://support.google.com/datastudio/answer/9061420

その他にも、かなり柔軟に設定できるので、ゴニョゴニョしがいがありそうです。このあたりの知見が溜まったら、別途記事化したいと思います。

終わりに

GoogleクラウドにロックインされるのはFirebaseを使っている時点で諦めていた訳ですが、合理的な選択をしていくと、さらにロックインされていくのは、よく考えられてるとしか言いようがないですね。ロックインされるのは諦めて、開発スピード重視で頑張りたいと思います!

サービスに機能追加を行う時に、どういう効果が出るのか仮説を立ててから機能追加することが大事だと思ってます。その仮説検証に、今回の分析基盤を役立てていきたいです。

参考

Export Collections to BigQuery

https://qiita.com/watatakahashi/items/e9210c19b3915ab1b0d5
https://medium.com/google-cloud-jp/firestore-bigquery-3b887a5bc27e

データポータル

https://ayudante.jp/column/2018-07-27/08-50/
https://zenn.dev/kiiimii/articles/bacc4a15e9bdb7

Discussion

tomotomo

とても参考になる記事をありがとうございます!

Collection Pathでワイルドカードを利用して既存ドキュメントをインポートした場合、path_paramsがセットされない不具合があるのが辛いですね。 https://github.com/firebase/extensions/issues/947

imaima

この記事が役に立てたようで良かったです!

不具合報告、今後、この記事を見る人の役に立つと思います!ご報告ありがとうございました!