3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

FirebaseAdvent Calendar 2021

Day 5

firestoreでのランキング設計を考える

Last updated at Posted at 2021-12-05

これはFirebase Advent Calendar 2021の5日目の記事です。

こんにちは。virapture株式会社のもぐめっとです。

mogmet.jpg
最近友達が結婚しました。とてもめでたいです。それでも私のおでこのシワは相変わらずとれないみたいです。

今回はfirestoreでランキングを実装するにあたってどうやったら実現できるかの設計・実装方法を考えてみました。

前提

サービスを作っていくとみんな大体ランキングをつけたくなりますよね。
中国ではファンビジネスでランキングを禁止するくらいランキングというのは非常に魅力的な機能の一つになります。

しかしfirestoreではフィルタリングが非常に弱いため、複雑な条件でのランキングになってくると実装をするのが難しくなります。
例えばプロダクトオーナーからこんな意見が出たとしましょう。

「1週間、1ヶ月、総期間での記事のいいねランキングをつけましょう!!!」

日にち区間の指定なく、全体のデータからランキングを生成するといったケースやシンプルな検索条件であれば問題なく実装できます。
しかし、時間軸によってランキングデータが変わるといった内容であると一工夫入れないといけなくなります。

解決策1. CloudFunctionsを使う

時間軸によってそれぞれサブコレクションを分けてデータを保管する必要が出てきます。

全体の設計としてはこんな形のfirestoreの設計を想定しています。

  • articlesサブコレクション
    • createdAt: Timestamp // 記事作成日
    • title: String // 記事タイトル
    • body: String // 記事内容
    • likeCount: Number // 総いいね数
    • weeklyLikeCount: Number // 週でのいいね数
    • monthlyLikeCount: Number // 月でのいいね数
    • likesサブコレクション
      • createdAt: Timestamp // いいねした日
      • username: String // いいねしたユーザ名

いいねした時はlikesサブコレクションにドキュメントを作ります。
またドキュメントが創られたらonCreateLikeというCloudFcuntionsを起動して諸々処理します。

■リアルタイム

下記実装で簡単に実現が可能です。

    1. 記事にいいねがされるとonCreateLikeのCloudFunctionsを起動
    1. article.likeCountをインクリメント
    1. 記事の総いいね数フィールドを集計していいね数順に表示

実装が簡単なので、articleのドキュメントをonSnapshotでListenすることでリアルタイムでの表示も可能です。
ただしfirestoreには1ドキュメントに対する書き込みは1秒あたり1回までの制限があります。

もしサービスが成長してアクセスが増えた場合は下記のようなエクステンションを使ってカウントを計測することをお勧めします。

■1週間/1ヶ月

article.likeCountだけでは週と月の集計は難しいため、バッチ処理を回して集計する必要があります。
そのため、1週間のコレクション、1ヶ月のコレクションにそれぞれ集計した結果を入れていく必要があります。
ただし、ランキングの開始日を月初め、週初めといった形で仕様として決め打ちできるのであれば、下記実装でリアルタイムでのランキングが可能です。

    1. 毎週、毎月の指定日時でarticle.weeklyLikeCount、article.monthlyLikeCountをリセットする
    1. article.weeklyLikeCountもしくはarticle.monthlyLikeCountをいいねしたときにインクリメント

毎週・毎月ランキングをリセットしてみせるという表現になります。

リセットしない1週間/1ヶ月

もしリセットせずに直近1週間、1ヶ月のランキングを見せたいといった場合はlikesのサブコレクションに対して、コレクショングループの検索を使って毎日集計ケッケのみのドキュメントを生成することで見せることはできます。
ただし、この場合はリアルタイムではなく、前日までの集計結果となるので、最大で1日のタイムラグが生じます。

解決策2. BigQueryを使う

丸投げになりますが下記記事に解説されておりますのでより柔軟にランキングの計算や実装ができます。

こちらに関してはサマリーテーブルを使った方法を紹介されてます。
Analyticsの要素も絡めることができるので、よりいろんなセグメントでのランキングも作ることができます。

まとめ

ランキング実装を作るときはどのセグメントを切り取るかで実装方法やコストが変わってきます。
しっかりと仕様を決めてユーザの価値にフィットしたプロダクトとコストに見合った機能を作っていきましょう!

最後に、ワンナイト人狼オンラインというゲームを作ってます!よかったら遊んでね!

他にもCameconOffchaといったサービスも作ってるのでよかったら使ってね!

また、チームビルディングや技術顧問、Firebaseの設計やアドバイスといったお話も受け付けてますので御用の方は弊社までお問い合わせください。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?