Firestoreでのデータの生成、変更、削除等をトリガーに処理を実行するfirestoreトリガーを試してみたいと思います。
なお、HTTP(リクエストによる)トリガーについてはこちらをどうぞ。
前提
- Firebaseを利用したり、Functionを作成するための環境が整っていること。
- まだの方はこちらをどうぞ。
実装
最低限の実装はおおよそ下記のような感じかと。
下記の例では、firestoreのshareという名前のCollectionのparamsというドキュメントに対して、create, update, deleteのいずれかが実行されたことをトリガーに処理(コンソールにHello Trigger!と表示)を実行します。
const functions = require('firebase-functions');
exports.helloTrigger = functions.firestore.document('share/params').onWrite((change, context) => {
console.log("Hello Trigger!");
return 0;
});
return 0;を入れているのはError: Value for argument "data" is not a valid Firestore document.とかいうエラーがログに出るのを防ぐためです。
実行の確認(デバッグ)
実行
実行は、別のプログラム等からdb.collection('share').doc('params').set({color:'red'});等のダミーコマンド実行して、トリガーの対象となっているドキュメントを生成(更新・削除)してみます。
いちいちテストのためにスクリプト書くのも面倒なので私はSQL Tabsというツールと使ってデータを生成させたり、更新させたりしてます。あまり複雑な処理はできなくて不満もありますが、無いよりマシです。
console.log()の出力をどこで確認するのか?
HTTPトリガーの場合は、出力にエラーを含ませればディバッグできますが、Firestoreトリガーの場合、console.log()を使う必要がありますが、もちろんローカルコンソールに出力はされません。コード中のconsole.log()はFirebaseコンソールのFunctionsのログにて確認できます。
下記のような感じで出力が確認できます。
なお、return 0;を入れないと、下記のようならErrorログが出力されます。
少し応用
私はあるドキュメントの変更をトリガーに別のDB(RDBとか)に必要な情報を書き込むような処理がしたいと考えていますので、それを意識したコードを書いてみます。とはいえ、無料でつかえるクラウドSQLサーバが無いので、とりあえずFirestoreに書き込みをしてみます。
- share/paramsの変更を起点に、logsに(ログ風の)データを書き込んでいます。
- functionが展開されるリージョンを東京に指定しています。
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
const db = admin.firestore();
exports.helloTrigger = functions.region('asia-northeast1').firestore.document('share/params').onWrite((change, context) => {
db.collection('logs').add({
param: 'hoge',
after: change.after.data(),
before: change.before.data(),
created_at: admin.firestore.FieldValue.serverTimestamp(),
});
console.log("hoge");
return 0;
});
ワイルドカードの利用
ワイルドカードがいまいち何なのかわからなかったので確認してみました。
例えば、下記のようなコードを準備して、
exports.helloTrigger = functions.region('asia-northeast1').firestore.document('share/{doc_name}').onWrite((change, context) => {
let doc_name = context.params.doc_name;
console.log(doc_name);
console.log(change.after.data());
console.log(change.before.data());
return 0;
});
db.collection('share').doc('params').set({});
を実行すると、paramsが出力され、
db.collection('share').doc('configs').set({});
を実行するとconfigsが出力されます。つまり、db操作時にパラメータを渡してやるとそれをfunction側で取得できるような仕組みのようです。
あるコレクションを監視し、どのドキュメンにどのような処理がされたか?などを知るにはいいのかもしれない(逆に、特定のドキュメントのみを関しするシーンの方が少ないか・・・)。
いまひとつ理解が足りないので継続探求するということで。