如何在多个字段上对排行榜进行排序?

最后更新于 2024 年 3 月 22 日

问题

如何执行多维排序操作?

答案

在排行榜中,如果需要根据不同的维度进行排序,例如根据玩家的分数对玩家进行排序,如果分数相同,则根据排名进行排序,然后根据完成任务的时间进行排序,可以使用两种方法对分数进行建模。

在排序集中对分数进行编码

此方法使用排序集,并使用自定义分数对不同的字段进行编码。我们将把三个分数编码为一个双精度数字,它由三个部分组成

  1. 主要分数,可变且无界
  2. 排名,它有一个上限。例如 999
  3. 时间,它有一个上限。例如 99999

因此,我们将对该条目的总分数进行编码

HSET user:score:11 score 10 ranking 15 time 1000

如下所示,将以下字符从左到右连接起来

"10" + "015" + "01000" = 1001501000

现在可以使用排序集对排行榜进行建模。

ZADD leaderboard 1001501000 user:score:11
ZADD leaderboard 5000902000 user:score:12
ZADD leaderboard 1002002000 user:score:13
ZADD leaderboard 1002502000 user:score:14
ZADD leaderboard 1003002000 user:score:15
ZADD leaderboard 1003502000 user:score:16

现在,用户将根据三个分数进行自然排序。

ZREVRANGE leaderboard 0 -1
1) "user:score:12"
2) "user:score:16"
3) "user:score:15"
4) "user:score:14"
5) "user:score:13"
6) "user:score:11"

使用 FT.AGGREGATE 进行索引和聚合

使用不同的数据模型,其中每个用户对象都存储用于排序的字段,您可以将分数建模为 `NUMERIC SORTABLE` 字段,并请求 `SORTBY` 属性列表。请查看以下示例。

HSET user:score:11 user user:11 score 10 ranking 15 time 1000
HSET user:score:12 user user:12 score 50 ranking 9 time 2000
HSET user:score:13 user user:13 score 10 ranking 20 time 2000
HSET user:score:14 user user:14 score 10 ranking 25 time 2000
HSET user:score:15 user user:15 score 10 ranking 30 time 2000
HSET user:score:16 user user:16 score 10 ranking 35 time 2000

FT.CREATE user_score_idx ON HASH PREFIX 1 user:score SCHEMA user AS user TEXT score AS score NUMERIC SORTABLE ranking AS ranking NUMERIC SORTABLE time AS time NUMERIC SORTABLE

FT.AGGREGATE user_score_idx * SORTBY 6 @score DESC @ranking DESC @time DESC 
1) (integer) 6
2) 1) "score"
   2) "50"
   3) "ranking"
   4) "9"
   5) "time"
   6) "2000"
3) 1) "score"
   2) "10"
   3) "ranking"
   4) "35"
   5) "time"
   6) "2000"
4) 1) "score"
   2) "10"
   3) "ranking"
   4) "30"
   5) "time"
   6) "2000"
5) 1) "score"
   2) "10"
   3) "ranking"
   4) "25"
   5) "time"
   6) "2000"
6) 1) "score"
   2) "10"
   3) "ranking"
   4) "20"
   5) "time"
   6) "2000"
7) 1) "score"
   2) "10"
   3) "ranking"
   4) "15"
   5) "time"
   6) "1000"

参考资料

请查看有关 FT.AGGREGATE 的文档。