CloudFirestoreにドキュメントが投稿されたら投稿数をインクリメントするCloudFunctionsを実装 #CloudFirestore #CloudFunctions

シェアする

こんにちはフクシャチョーです。

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.eventId A unique ID for the event. String
context.timestamp The date/time this event was created. String (ISO 8601)
context.eventType The type of the event. String
context.resource The resource that emitted the event. String

実際のデータは event.dataプロパティに含まれています。

イベントタイプによってデータは変わるので、以下を参照してください。

CloudStorageの場合、event.dataには、取得したデータのオブジェクトが返却されてきます。

なので、上記ではevent.data().userIdでユーザーIDを取得しています。

Cloud Firestoreのイベントについて

※ Cloud Firestore は、createupdatedeletewrite イベントをサポートしています。

イベントタイプ トリガー
onCreate ドキュメントが最初に書き込まれたときにトリガーされます。
onUpdate すでに存在するドキュメントの値が変更されたときにトリガーされます。
onDelete データを含むドキュメントが削除されたときにトリガーされます。
onWrite onCreateonUpdate または 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!