Likeランキング機能を改善しました
2021-02-26
Improved the Like ranking.
前回のあらすじ
前回実装したLikeランキング機能ですが、当初考えた機能とは別物でした。本当にやりたかったのは過去24時間の投稿をLike数でソートして上位20件を表示というものです。
ところが実際に実装できたのは過去24時間のうち最新20件の投稿をLike数順に表示というものでした。
これはFirebase Realtime databaseの制限によるものです。
本来やりたかった機能をFirebaseでやろうとすると、過去24時間の投稿を探してLike数で並べ替えるという2段階のクエリが必要になります。
Realtime DatabaseではorderBy
メソッドは1度しか使えないので素直に実装するのは不可能でした。
改善策
そこで、1つのクエリで取得できるように投稿日時とLike数を合体させたフィールドを用意することにしました。
考え方は2021 02 26 * 1000 + Like数で格納
して2021 02 26 000
以上を取り出してソートするということです。
2021/02/25
20210225001 ←Like数1
20210225002 ←Like数2
20210225003 ←Like数3
...
20210225999 ←Like数999
2021/02/26
20210226001 ←Like数1
20210226002 ←Like数2
20210226003 ←Like数3
...
20210226999 ←Like数999
というようにLike数を格納するフィールドを用意して、今日取り出すときは20210226000
以上の投稿を最大20件取得するようにします。
ゼロ埋め用に1000をかけてますが、アプリの構造とかユーザー数的にLike数が1000を超える投稿はないだろうという判断です。
というわけで、このやり方でRealtime Databaseに格納するとこんな感じになります。
取り出すときのクエリはこんな感じです。
onValueChanged() {
var today = new Date();
var todaystr = today.getFullYear() + ('0' + (today.getMonth() + 1)).slice(-2) + ('0' + today.getDate()).slice(-2)
var todayRank = todaystr * 1000
this.dbh
.ref(`gallery/`)
.orderByChild('likeRank')
.startAt(todayRank)
.limitToLast(20)
.on("value", snapshot => {
hogehoge
}).bind(this);
}
orderByChild
メソッドでlikeRankフィールドをソートして今日の日付x1000をstartAt
メソッドで足きりすると、今日の投稿がLike数順でソートされます。
Realtime Databaseでは昇順でソートされるので、Like数が多いものが後ろに来ます。なのでlimitToLast
メソッドで、最後の20件を取り出します。
これで今日の投稿をLike数順に最大20件取り出せました。
まとめ
スレでアイディアをもらったときには簡単に実装できるかなと思ったのですが、Realtime Databaseの仕様的に一工夫が必要でした。
24時間以内のLike数ランキングではないですが、それに近いものになってよかったです。