Firestoreは素晴らしいサービスですが、集計系は弱いのでBigQueryと連携するのは定石の1つです。
今までは連携を目的に合わせて手動で行う必要がありましたが、連携を自動化してくるextensionが出たので試してみます。
基本的な利用方法はこちらの記事が非常に参考になりますので、補足的なことや、個人的な関心事について書いてみます。
Export Collection to BigQueryとは?
その名の通り、コレクション単位でデータをBigQueryにExportするためのextensionで、実態は、firestoreのwriteをトリガーに動作するFunctionsです。
復数のCollectionに対応できるのか
以前テストしたときから気になっていたのが1つのExtensionで1つのCollectionしか指定できない仕様だったので、復数の同一Extensionを登録できるのかが気になっていました(同じプロジェクトで復数のコレクションを出力したい)。
結論から言えば下記のように登録できました。
ExportしたいCollectionの数だけ登録して利用することになるようです。
拡張機能の構成
構成の要素としていじれるのは下記のパラメータのみです。
- Functionをデプロイするリージョン(データセットとは違う)
- コレクション名(Firestore側)
- データセット名(BigQuery側)
- テーブル名(BigQuery側)
このうち、Functionsのリージョン以外は後からでも変更できるようです。
データセットは標準ではUSに作られてしまうので、日本にしたい場合は予め作成しておいてデータセットにマッピングする必要があります。
インストールが終わると
- [table_name]_raw_changelog
- [table_name]_raw_latest
の2つのテーブルとビューができるようです。クエリはビューの方に行うといいでしょう。
上記は復数のextensionを登録した後の状態です。
latestの方には最新の状態のデータが格納されており、changelogの方はその名の通り、全ての操作ログが保存されています。
上記の例では、1つのドキュメントがcreateされ、updateされ、deleteされたすべての記録が残っています。
データ構造
上記のスキーマをみていただくといいのですが、dataというところにjson形式でデータが格納されます。
dataに下記のようなJSONが入ってます。
[
{name:'foo', point:10, tel:'0312345678'}
]
いくつかクエリを実行してみる
JSONにクエリをかける
JSONにクエリをかけるには下記の2つの標準関数があります。
- json_extract()
- json_extract_scalar()
json_extract()だと"name"というような""が付いた形式で取得されます。
scalar()だとname自体が取得されます。
取得はjson_extract_scalar(column_name,'$.param_name')という感じで行います。
Selectしてみる
select
json_extract_scalar(data,'$.name') as name,
json_extract_scalar(data,'$.email') as email
from firestore_export.members_raw_latest
Whereしてみる
asで指定したAlias名はwhereじゃつかえないみたい。
select
json_extract_scalar(data,'$.name') as name,
json_extract_scalar(data,'$.email') as email
from firestore_export.members_raw_latest
where json_extract_scalar(data,'$.name') like '%8%'
Sumしてみる
もちろんsumもできる。
select
sum(cast(json_extract_scalar(data,'$.point') as int64) ) as point_sum
from firestore_export.users_raw_latest
Deleteしてみる
deleteもできるようになった。
delete from firestore_export.members_raw_changelog where true
その他
InsertはStream Insertにより行われているので、データがbufferにあるうちはデータを削除できない。。。あと、もちろん費用も考える(1GB $0.05)。
30分くらいという噂があるが、明確なソースがわからない。