redis 从 2 个排序集中获得前 5 个

问题描述

我有 2 个排序集作为排名。我想从他们之间的联盟中获得前 5 名。分数是一样的。

zadd rank1 1 aaa
zadd rank1 2 bbb
zadd rank1 3 ccc
zadd rank1 4 ddd
zadd rank2 1 aaa
zadd rank2 2 bbb
zadd rank2 3 ccc
zadd rank2 4 ddd

这样做的最佳方法是什么?

ZUINON 10 rank1 rank2 AGGREGATE MAX 5 

我会假设类似的东西,但 max 5 不存在。

编辑 刚刚发现即使 ZUNION 也无济于事,因为我的 redis 版本是 6.0.5 而不是 6.2.0

解决方法

我的排序集合很大 - 即每个集合中有数百万个键。另外,这个联合每秒会发生很多次(这是我网站中的首要查询)。这是最快的方法吗?

只需从每个 SortedSet 中取出前 5 个,然后在您的服务器(/客户端)进程中从这 10 个元素中选择前 5 个。对于您的场景,这将是最快且最不复杂的。

您可以使用 ZREVRANGE 命令从一个 SortedSet 中获取前 N 个元素。但是要统一/合并 2xN 元素并选择前 M 个元素,您还需要这些元素的相应分数。带有 ZREVRANGE 关键字的 WITHSCORES 命令返回前 N 个元素及其分数。

ZREVRANGE rank1 0 4 WITHSCORES
ZREVRANGE rank2 0 4 WITHSCORES
,

这取决于你想用同一个键的分数做什么。对于两个'aaa',要不要把它们相加(聚合),然后得到前五名的聚合结果?

您可以使用 ZUNIONSTORE,可以选择将临时结果存储在其他地方,然后获得前五名的结果。 (支持Redis 6以下版本)

要以原子方式执行此操作,您需要一个 lua 脚本来组合以下两个命令

ZUNIONSTORE out 2 rank1 rank2  --(the temporary result is stored in a zset called 'out')
ZREVRANGE out  0 4   ---- (ranking from highest to lowest,get top five)