Cloud Functions for Firebaseを使用して、"最近の更新"の件数を制限する (STEP 3 : 他のユーザのタスクが見れるタスク管理アプリを作成する - React + Redux + Firebase チュートリアル)

★前回の記事

yucatio.hatenablog.com

前回までで、/recentUpdatedTodosへのデータの追加を行うことはできましたが、これではどんどんデータが溜まって行ってしまうので、個数を制限します。制限を超えたら古いデータを削除します。

firebaseのサンプル(limit-children)があるので、このコードをもとにします。

実装方針

/recentUpdatedTodosに新しくデータが登録された時に、古いデータを削除します。何件のデータを残すかは、MAX_RECENT_UPDATED_TODOSで制御します。 動作確認を簡単にするため、MAX_RECENT_UPDATED_TODOSは一旦”3”にします。

“/recentUpdatedTodos”の子ノードの数の取得

はじめに、/recentUpdatedTodosの子ノードの数の取得をするコードを書きます。削除処理が必要なのは子の数がMAX_RECENT_UPDATED_TODOSより大きい場合なので、それ以下の場合は早期にreturnします。

functions/index.js

const MAX_RECENT_UPDATED_TODOS = 3;

exports.limitRecentUpdatedTodos = functions.database.ref('/recentUpdatedTodos/{todoId}/_updatedAt')  // #1
  .onCreate((snapshot, context) => {
    const recentUpdatedTodosRef = snapshot.ref.parent.parent;  // #2
    return recentUpdatedTodosRef.once('value').then((todosSnapshot) => {  // #3

      console.log('numChildren: ' + todosSnapshot.numChildren());  // #4

      if (todosSnapshot.numChildren() <= MAX_RECENT_UPDATED_TODOS) {
        console.log('Less than or equals to ' + MAX_RECENT_UPDATED_TODOS);
        return null;
      }

      console.log('More than ' + MAX_RECENT_UPDATED_TODOS);
      return null;
    });
})
  • データ追加のトリガを/recentUpdatedTodos/{todoId}/_updatedAtに設定します(#1)。
  • /recentUpdatedTodosは、_updatedAtから見て親の親なので、/recentUpdatedTodosのリファレンスはsnapshot.ref.parent.parentで取得することができます(#2)。
  • /recentUpdatedTodosのデータを取得します(#3)。
  • 子ノードの個数はnumChildren()で取得します(#4)。

子ノード数取得の動作確認

デプロイして動作確認します。

$ cd todo-sample
$ firebase deploy --only functions

動作確認のため、一旦DBの/recentUpdatedTodosの子ノードを削除します。

f:id:yucatio:20181026225707p:plain

タスクを作成・更新して、/recentUpdatedTodosにデータを追加します。

f:id:yucatio:20181027214107p:plain

Cloud Functionsのログを確認します。

f:id:yucatio:20181027215027p:plain

/recentUpdatedTodos```の子ノードの数と、MAX_RECENT_UPDATED_TODOS``より大きいか小さいかが表示されました。

制限件数を超えたら、古いデータを削除する

制限件数を超えたら、古いデータから削除するように修正します。データを_updatedAtで並び替え、最初の方のデータから削除します。

functions/index.js

const MAX_RECENT_UPDATED_TODOS = 3;

exports.limitRecentUpdatedTodos = functions.database.ref('/recentUpdatedTodos/{todoId}/_updatedAt')
  .onCreate((snapshot, context) => {
    const recentUpdatedTodosRef = snapshot.ref.parent.parent;
    return recentUpdatedTodosRef.orderByChild('_updatedAt').once('value').then((todosSnapshot) => { // #1

      if (todosSnapshot.numChildren() <= MAX_RECENT_UPDATED_TODOS) {
        return null;
      }

      let childCount = 0;
      const updates = {};
      todosSnapshot.forEach((child) => {
        // remove old updates
        if (++childCount <= todosSnapshot.numChildren() - MAX_RECENT_UPDATED_TODOS) {  // #2
          updates[child.key] = null;  // #3
        }
      });
      return recentUpdatedTodosRef.update(updates);  // #4
    });
})
  • 最近の更新のデータを最終更新時間順に並び変えるため、orderByChild('_updatedAt’を追加します(#1)。データは昇順に並びます。
  • 子ノードの個数 - MAX_RECENT_UPDATED_TODOSぶん、/recentUpdatedTodosの子ノードを削除します(#2)。
  • 削除したいデータの値をnullにします(#3)。
  • 更新内容を、updateの引数として渡します(#4)。

件数の制限の動作確認

デプロイして動作確認します。

$ cd todo-sample
$ firebase deploy --only functions

実行前の/recentUpdatedTodosです。

f:id:yucatio:20181027220309p:plain

_updateAtの古い順に①②③④と番号を振りました。

タスクを1件追加します。

f:id:yucatio:20181027220709p:plain:w200

追加後の/recentUpdatedTodosです。

f:id:yucatio:20181027221319p:plain

①と②のデータが消えて、件数が3件に制限されました。件数制限のスクリプトがうまく動いています。

保存件数の変更

今回は最新の10件をビューで表示するので、MAX_RECENT_UPDATED_TODOSの値を”10”に変更します。

const MAX_RECENT_UPDATED_TODOS = 10;

デプロイします。

$ cd todo-sample
$ firebase deploy --only functions

以上で、Cloud Functions for Firebaseを使用して、"最近の更新"の件数を制限することができました。

★次回の記事

yucatio.hatenablog.com

★目次

yucatio.hatenablog.com