代码之家  ›  专栏  ›  技术社区  ›  Jan

zrevrank在redis中的“公平”排名

  •  1
  • Jan  · 技术社区  · 6 年前

    当我有一个带有分数的排序集时,即使多个项目具有相同的分数,我也希望拥有正确的排名。

    例如,当有5个项目得分时:1,2,2,2,3,我希望这三个中心项目有相同的排名(1),而最高的得分为0(ZrevRange),最低的得分为4。

    我看到可以有效地查询具有相同分数的键的数量o(log(n)),但是如果我想得到我想要的分数,我必须使用zscan,也就是o(n)。

    编辑:根据接受的解决方案添加完整的示例

    我们的数据集是一个带有分数的排序集。例如:A得1分,B,C,D得2分,E得3分:

    127.0.0.1:6379> zadd aset 1 a
    (integer) 1
    127.0.0.1:6379> zadd aset 2 b
    (integer) 1
    127.0.0.1:6379> zadd aset 2 c
    (integer) 1
    127.0.0.1:6379> zadd aset 2 d
    (integer) 1
    127.0.0.1:6379> zadd aset 3 e
    (integer) 1
    

    ZREVRANK 适用于具有唯一分数的项目:

    127.0.0.1:6379> zrevrank aset a
    (integer) 4
    127.0.0.1:6379> zrevrank aset e
    (integer) 0
    

    但同样得分的项目失败:

    127.0.0.1:6379> zrevrank aset b
    (integer) 3
    127.0.0.1:6379> zrevrank aset c
    (integer) 2
    127.0.0.1:6379> zrevrank aset d
    (integer) 1
    

    要解决这个问题,首先得分数 ZSCORE :

    127.0.0.1:6379> zscore aset c
    "2"
    

    当然,其他项目的得分相同:

    127.0.0.1:6379> zscore aset b
    "2"
    127.0.0.1:6379> zscore aset d
    "2"
    

    要获得他们的等级,只需使用 ZCOUNT 得分:

    127.0.0.1:6379> zcount aset (2 +inf
    (integer) 1
    

    这也适用于那些得分独特的项目:

    127.0.0.1:6379> zcount aset (1 +inf
    (integer) 4
    127.0.0.1:6379> zcount aset (3 +inf
    (integer) 0
    

    把它写成原子Lua脚本留给读者作为练习。

    2 回复  |  直到 6 年前
        1
  •  2
  •   Kevin Christopher Henry    6 年前

    对于有分数的给定项目 x ,您可以确定其在o(log(n))时间中的排名 ZCOUNT (X +inf .

    具体如何利用它取决于实现的细节。

        2
  •  0
  •   Nick Bondarenko    6 年前

    ZREVRANGEBYLEX 在这种情况下可以使用。在这种情况下,时间复杂度为o(log(n)+m),n是排序集中的元素数,m是返回的元素数。请看 ZRANGEBYLEX 用于语法。

    lex系列的已排序集命令允许您为具有相同值的键指定词典排序。