Cloud Functions トリガーonWriteの「change」と「context」について
はじめに
Cloud Functionsのトリガー「onWrite」を使ったときに、引数で受け取る2つの値がある。
それが「change」と「context」である。
const functions = require('firebase-functions');
exports.useWildcard = functions.firestore
.document('users/{userId}')
.onWrite((change, context) => {
// do something
});
でも、この「change」と「context」が一体何なのか?
これが最初はよくわからないですよね〜
前提となるトリガーonWriteについて
そもそもonWriteとは?というと「onCreate、onUpdate または onDelete がトリガーされたときにトリガーされる」というものです。
つまり、データに何かしらの変更があったときに発動するトリガー、との認識で大丈夫かと!
「change」は対象のドキュメントのデータを取得する
まずは「change」から。
ドキュメントによると
関数がトリガーされた後、更新済みのドキュメントのデータを取得する場合や、更新前のデータを取得する場合があります。更新前のデータは、更新前のドキュメントのスナップショットを含む change.before.data() を使用して取得できます。同様に、change.after.data() には更新後のドキュメントのスナップショットの状態が含まれます。
https://firebase.google.com/docs/functions/firestore-events?hl=ja
うーん、わかりにくい。。。
実例で解説すると
users/{userId}/events/{eventId}
の中に、以下のようなドキュメントがあったとする
exports.updateUser2 = functions.firestore
.document('users/{userId}/events/{eventId}')
.onUpdate((change, context) => {
// Get an object representing the current document
const newValue = change.after.data('title');
// ...or the previous value before this update
const previousValue = change.before.data('title');
});
①もし、「title=沖縄」で新規のドキュメントを追加した場合
・newValue
は「沖縄」となる
・previousValue
は「undefined」となる
②もし既存のドキュメント(①で作成したもの)を「title=大阪」で更新した場合
・newValue
は「大阪」となる
・previousValue
は「沖縄」となる
なぜ①previousValue
が「undefined」なのかというと、新規で作成されたドキュメントなので変更前(change.before
)が存在しないからです。
いやーこれに気がついた時は、すっきりしました
「context」も対象のドキュメントのデータを取得する
「context」の最もよく使われるであろう用途はずばりワイルドカード!
ドキュメントによると
ワイルドカードに一致した部分がドキュメント パスから抽出され、context.params に保存されます。明示的なコレクションまたはドキュメント ID に置き換えるワイルドカードは、必要な数だけ定義できます。
https://firebase.google.com/docs/functions/firestore-events?hl=ja
微妙にわからない・・・
実例で解説すると
exports.countEvents = functions.firestore
.document('users/{userId}/events/{eventId}')
.onWrite((change, context) => {
const userId = context.params.userId;
const FieldValue = admin.firestore.FieldValue;
const countsRef = db.collection('users').doc(userId);
if (!change.before.exists) {
// 登録時に件数をインクリメント
return countsRef.update({ eventCount: FieldValue.increment(1) } );
} else if (change.before.exists && !change.after.exists) {
// 削除時に件数をデクリメント
return countsRef.update({ eventCount: FieldValue.increment(-1) });
}
return;
});
上記のコードは「イベントを追加したら、その数をカウントをする」というような処理をしています。
(上記の処理について、詳しくはこちらを参考に)
どのユーザーがイベントを追加したのか?を知るためにはuid
を取得する必要があります。
なので
const userId = context.params.userId;
の部分で、イベントを追加したuserのuidを取得しています。
では「context.params.userId」のparamsの後の「userId」はどうやって決まったのか?
「uid」ではダメなのか?
exports.countEvents = functions.firestore
.document('users/{userId}/events/{eventId}')
上記のコードの場合、paramsの後は「uid」ではダメです。
なぜなら、.document('users/{userId}/events/{eventId}')
のパスの中で、「userId」をワイルドカードにしているからです。
逆言えば
exports.countEvents = functions.firestore
.document('users/{uid}/events/{eventId}')
この場合は.document('users/{uid}/events/{eventId}')
のパスの中で、「uid」が使われてるので、
const userId = context.params.uid;
にしないとuserのIDは取得できません。
最後に
contextについてはワイルドカード以外に使ったことがなく、あんまり詳しくないので
より詳しく知りたい方は下記を参考に・・・
https://firebase.google.com/docs/reference/functions/cloud_functions_.eventcontext?hl=ja
こちらは日本語記事
https://blog.firstfournotes.com/tech/firebase-follow-followered/
Author And Source
この問題について(Cloud Functions トリガーonWriteの「change」と「context」について), 我々は、より多くの情報をここで見つけました https://qiita.com/kokogento/items/6479e29a91e6f09dcd8b著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .