こんにちはフクシャチョーです。
Firebaseとお友達月間です。
今回の実装内容
さて、よくあるあるアプリの実装で、ユーザーが何らかのデータを投稿する、というのがあります。twitterとかInstagramとか・・・諸々のアプリでおなじみの操作です。
アプリからユーザーのアカウントページを見ると、そのユーザーの投稿数が表示されますよね。この投稿数をCloudFunctionsで集計します。
CloudFirestoreにあるコレクションは以下のような感じ
- users ・・・ユーザーデータ
- posts・・・投稿データ
アプリから投稿する際にはpostsコレクションにドキュメントが追加されます。
このドキュメントが追加されたイベントトリガーで、投稿したユーザーのpostCountsフィールドをインクリメントするCloudFunctionsを実装します。
プロジェクト設定
ログインしてプロジェクトの設定
この一連の操作は覚えておきましょう。
$firebase login $firebase init functions $firebase use --add
自分が利用するFirebaseのプロジェクトを設定しましょう
コード
今回はinitの時にTypeScriptを選択しました。
index.js
import * as collection from './collection'; export const updatePostCount = collection.updatePostCount;
collection.js
import * as functions from "firebase-functions"; import * as admin from "firebase-admin"; admin.initializeApp(functions.config().firebase); export const updatePostCount = functions.firestore .document("posts/{postId}") .onCreate(async event => { // Get the post UserID const userId = event.data().userId; // Reference user doc const db = admin.firestore(); const userRef = db.collection("users").doc(userId); // Get the user data const user = await userRef.get(); // Update the count and run the update const postCount = (user.data().postCount || 0) + 1; return userRef.update({ postCount }); });
postsドキュメントがonCreateした時に実行します。
postドキュメントからuserIdを取得して、そのユーザーIDをもつユーザーのドキュメントのpostCount フィールドをインクリメントするようにしています。
イベントパラメーターとデータプロパティについて
Events and Triggers | Cloud Functions Documentation | Google Cloud
Property | Description | Type |
---|---|---|
data | The data object for the event. | Object |
context | The context object for the event. | Object |
context. | A unique ID for the event. | String |
context. | The date/time this event was created. | String (ISO 8601) |
context. | The type of the event. | String |
context. | The resource that emitted the event. | String |
実際のデータは event.dataプロパティに含まれています。
イベントタイプによってデータは変わるので、以下を参照してください。
- HTTP: ExpressJS Request
- Google Cloud Storage: Cloud Storage Object
- Google Cloud Pub/Sub: PubsubMessage
CloudStorageの場合、event.dataには、取得したデータのオブジェクトが返却されてきます。
なので、上記ではevent.data().userIdでユーザーIDを取得しています。
Cloud Firestoreのイベントについて
※ Cloud Firestore は、create
、update
、delete
、write
イベントをサポートしています。
イベントタイプ | トリガー |
---|---|
onCreate | ドキュメントが最初に書き込まれたときにトリガーされます。 |
onUpdate | すでに存在するドキュメントの値が変更されたときにトリガーされます。 |
onDelete | データを含むドキュメントが削除されたときにトリガーされます。 |
onWrite | onCreate 、onUpdate または onDelete がトリガーされたときにトリガーされます。 |
デプロイ
$firebase deploy --only functions
プログラムに異常がなくて、デプロイ時にエラーになる場合は懲りずに数回実行してみましょう。
アップされたことを確認したら、確認して実行しましょう。
実行
さて、ユーザーがpost ドキュメントを投稿する前に、現状どうなっているか確認してから投稿をしましょう。
投稿前のCloudStorageにあるusersドキュメント
ドキュメントのpostCountフィールドの値は0です。
ここで、postドキュメントを投稿してみましょう
投稿後のCloudStorageドキュメントにあるusersドキュメント
postドキュメントを投稿したあとは、postCountフィールドの値は1になっています。
もちろんpostコレクションのデータも1増えています。
Functionsのログを確認
Functionsのログを確認してみましょう。OKで終了していますね。
これで、ユーザーがドキュメントを投稿する都度、usersのpostCountがインクリメントされていきます。
削除がある場合は、その処理も追加しておきましょう。
集計の処理はCloudFunctionsに任せてしまうとアプリ側の処理は楽になりますね。
Enjoy!