Redis使ってますか?
今日はzrankを使わないでセリーグ順位表を作ってみましょう。
例として、下のような順位表があるとします。
Team Rank 勝 負 分
Tigers 1 5 0 0
Dragons 2 4 1 0
Swallows 3 3 2 0
Giants 4 2 3 0
Carp 5 1 4 0
BayStars 6 0 5 0
順位に関してはなんとなくな個人の趣味で決めてますw
((5位力のカープと最下位ベイスターズ以外は適当に決めました。))
上の順位表をデータとしてRedisにセットしましょう。
HMSET Tigers Win 5 Lose 0 draw 0
HMSET Dragons Win 4 Lose 1 draw 0
HMSET Swallows Win 3 Lose 2 draw 0
HMSET Giants Win 2 Lose 3 draw 0
HMSET Carp Win 1 Lose 4 draw 0
HMSET BayStars Win 0 Lose 5 draw 0
SADD central Tigers Dragons Swallows Giants Carp BayStars
上の内容をdata.lstとして保存して下のコマンドを実行します。
% perl -pe 's/\n$/\r\n/g' data.lst |redis-cli --pipe
All data transferred. Waiting for the last reply...
Last reply received from server.
errors: 0, replies: 7
改行コードをCR+LFにしてパイプラインで流しこんでます。
データの準備はこれで完了です。
あとは、Redisの操作です。
ここからは SORT を駆使していきます。
% redis-cli
# 勝ち数順に並び替え
redis 127.0.0.1:6379> SORT central BY "*->Win" DESC
1) "Tigers"
2) "Dragons"
3) "Swallows"
4) "Giants"
5) "Carp"
6) "BayStars"
セット型のcentralの要素を見ながら同名のハッシュ型の値を参照してKey名Winの値を基準に並べ替えています。
これで大体のことは出来ました。あとはオマケです。
# 勝ち数順に並び替え + チーム名と勝ち数を取得
redis 127.0.0.1:6379> SORT central BY "*->Win" GET # GET "*->Win" DESC
1) "Tigers"
2) "5"
3) "Dragons"
4) "4"
5) "Swallows"
6) "3"
7) "Giants"
8) "2"
9) "Carp"
10) "1"
11) "BayStars"
12) "0"
# 勝ち数順に並び替え + 勝ち数と負け数を取得
redis 127.0.0.1:6379> SORT central BY "*->Win" GET "*->Win" GET "*->Lose" DESC
1) "5"
2) "0"
3) "4"
4) "1"
5) "3"
6) "2"
7) "2"
8) "3"
9) "1"
10) "4"
11) "0"
12) "5"
上位3チームだけ必要な場合はLIMIT句を使うことで実現出来ます。
# 勝ち数順に並び替え + チーム名と勝ち数を上位3チームまで取得
redis 127.0.0.1:6379> SORT central BY "*->Win" LIMIT 0 3 GET # GET "*->Win" GET "*->Lose" DESC
1) "Tigers"
2) "5"
3) "0"
4) "Dragons"
5) "4"
6) "1"
7) "Swallows"
8) "3"
9) "2"
SORTコマンドってこうやってみていくとSQLっぽいですね。
このランキングの作り方だとzrankで作るよりも柔軟にランキングが作れることが魅力です。
欠点は6チーム中何位みたいなランキングを作ることは難しいです。
できなくも無いですがすべての要素をソートしてどこにあるか確定させる必要があるので要素数が多くなるとパフォーマンスの問題が発生が起こります。
要素数があまり大きくなく(多分、n<10000)、上位100位ぐらいまで表示させたいならこの方法でも十分なパフォーマンスが出せるでしょう。
こんな感じでSORT + HASH型 + SET型を組み合わせれば ソート済みSET型を使わなくても簡単なランキングが作れるという話でした〜。