美文网首页Redis应用
详尽Redis有序集合指令

详尽Redis有序集合指令

作者: 李小磊_0867 | 来源:发表于2020-05-21 19:31 被阅读0次

    Redis基础数据类型的最后一种常用的数据类型,有序集合能够在日常开发中给我们提供更多的想象空间。
    在这里,一些示例直接采用了try.redis.io中的例子,文中有标注。

    有序集合类型

    有序集合在集合类型的基础上,对每个元素添加了一个分数,除了具备集合类型的基础功能外,如添加、删除、查找、判断元素是否存在等,还能够根据分数进行一些相关操作,查询分值区间的元素等。

    有序集合和列表类型也有一定的相似度,比如有序集合和列表都是有序的,并且可以提供获取区域元素,在一定程度上可以实现分页的功能。但两者也有本质的区别,列表主要是双向链表数据结构,查询两端元素性能比较高,随着元素的增多,越靠近中间的元素查询性能越低,列表对于实现小规模数据的存储,比如个人收藏等,或者排行榜、最新日志等有较好的体现;有序集合采用Hash、跳跃表等实现,因此对于大数据量,中间查询也有较快的表现;列表因为采用双向链表实现,因此调整顺序比较麻烦,有序集合在调整顺序时,只需要调整分数即可。

    添加元素
    ZADD key score member [score member ...]
    

    ZADD指令用于向有序集合添加一组或多组元素+元素分数,当元素已存在时,将更新分数。该命令将当前插入成功的元素个数返回,不包含已存在的元素。

    将名画家的作品按创作年份插入到有序集合(try.redis.io)。

    ZADD a 1965 "girl with a pearl earring" 1895 "The Last Supper" 1987 "The Death of Marat" 
    # (integer) 3
    

    此时,要调整The Death Of Marat的创作日期,同时需要新增一副作品

    ZADD a 1978 "The Death of Marat" 1901 "Marilyn Monroe"
    # (integer) 1
    

    由于The Death Of Marat作品已存在,因此只更新了分数1978,新增了一副作品,指令返回值为新增作品数1

    得分除了整数外,也支持浮点数。

    可以使用+inf-inf表示分数,分别代表正无穷大和负无穷大

    ZADD a 1978.8 "The Death of Marat" 
    # (integer) 0
    ZADD +inf "The dog" -inf "The cat"
    # (integer) 2
    ZRANGE a 0 -1   # 升序排列,-inf最小,+inf最大
    # 1) "The cat"
    # 2) "The Last Supper"
    # 3) "Marilyn Monroe"
    # 4) "girl with a pearl earring"
    # 5) "The Death of Marat"
    # 6) "The dog"
    
    获取元素分数
    ZSCORE key member
    

    ZSCORE指令用于获取元素的得分,该指令每次只能返回一个元素的得分。如果指定的key或者member不存在时,该指令返回nil

    ZSCORE a "The cat"
    # "-inf"
    ZSCORE a "The Death of Marat"
    # "1978.8"
    ZSCORE a b
    # (nil)
    ZSCORE ab b
    # (nil)
    
    按升序获取指定范围的元素列表
    ZRANGE key start stop [WITHSCORES]
    

    ZRANGE指令用于按SCORE升序返回start到stop之间的元素,包括start和stop索引位置的元素。该指令与来列表的LRANGE指令类似,只不过一个按插入排序,一个按SCORE升序,其他的STOP、START取值及使用方式一致。

    ZRANGE a 0 -1   # 按升序返回全部元素
    # 1) "The cat"
    # 2) "The Last Supper"
    # 3) "Marilyn Monroe"
    # 4) "girl with a pearl earring"
    # 5) "The Death of Marat"
    # 6) "The dog"
    # 从右向左获取元素
    ZRANGE a -3 -1
    # 1) "girl with a pearl earring"
    # 2) "The Death of Marat"
    # 3) "The dog"
    

    STOP、START取值和LRANGE的方式一致,START必须小于等于STOP,否则返回空。

    ZRANGE指令有一个可选参数,在指令末尾加上WITHSCORES,这样可以将元素得分一起返回,其格式为:元素,得分,元素,得分...,每个元素后紧跟着该元素的得分。

    ZRANGE a 0 3 WITHSCORES
    # 1) "The cat"
    # 2) "-inf"
    # 3) "The Last Supper"
    # 4) "1895"
    # 5) "Marilyn Monroe"
    # 6) "1901"
    # 7) "girl with a pearl earring"
    # 8) "1965"
    

    前面提到,ZRANGE在大数据量下,取中间的数据性能优于列表类型,其查找元素时间复杂度为O(logn + m),n为有序集合的基数,m为要返回的元素个数。当部分元素得分相同的情况下,将按照字典顺序进行排列(数字<大写字母<小写字母,每种类型内部也是升序)。

    ZRANGE a 1 2 WITHSCORES
    # 1) "ABC"
    # 2) "1895"
    # 3) "The Last Supper"
    # 4) "1895"
    
    按降序获取指定范围的元素列表
    ZREVRANGE key start stop [WITHSCORES]
    

    ZREVRANGE指令的使用方式同ZRANGE完全一致,唯一区别就是按降序返回数据。

    ZREVRANGE a 0 -1 WITHSCORES
    # 1) "The dog"
    # 2) "inf"
    # 3) "The Death of Marat"
    # 4) "1978.8"
    # 5) "girl with a pearl earring"
    # 6) "1965"
    # 7) "Marilyn Monroe"
    # 8) "1901"
    # 9) "The Last Supper"
    # 10) "1895"
    # 11) "ABC"
    # 12) "1895"
    # 13) "The cat"
    # 14) "-inf"
    
    按指定得分范围返回元素列表,从小到大排列
    ZRANGEBYSCORE key min max [WITHSCORE] [LIMIT offset count]
    

    ZRANGEBYSCORE指令用于从有序列表中,返回min<=分数<=max的所有元素,并按从小到大排列。min和max的取值同以往的分值参数一致,支持+inf(正无穷)、-inf(负无穷)。同时为了支持大于和小于的操作,提供一个(英文小括号,用于加在数字前面,表示大于(min或者小于(max的数值,此时不包括max和min的分值。

    WITHSCORE可选参数,同之前的命令一致,当携带此参数时,将返回得分,仍然元素,分数,元素,分数...格式返回。

    LIMIT offset count可选指令参数,用于限制返回的数量,同MySql的Limit指令类似,offset表示从那个位置开始返回数据,count用于表示返回多少个元素。

    ZRANGE a 0 -1 WITHSCORES    # 有序列表存储了学生的生日
    # 1) "lucy"
    # 2) "1979"
    # 3) "paul"
    # 4) "1982"
    # 5) "ray"
    # 6) "1983"
    # 7) "hh"
    # 8) "1988"
    # 9) "viciky"
    #10) "1997"
    #11) "xx"
    #12) "2011"
    # 获取80后的学生信息
    ZRANGEBYSCORE a 1980 1989
    # 1) "paul"
    # 2) "ray"
    # 3) "hh"
    

    在上面的指令上,如果希望不包含1980年的学生,则可以使用(指令加在min上。

    ZADD a 1990 jack
    ZRANGEBYSCORE a 1980 (1990 WITHSCORES
    # 1) "paul"
    # 2) "1982"
    # 3) "ray"
    # 4) "1983"
    # 5) "hh"
    # 6) "1988"
    

    当希望返回所有的80年以后出生的学生,但不知道最大的出生年龄(实际可以设置当前年份)时,可以使用+inf参数。

    ZRANGEBYSCORE a 1980 +inf
    # 1) "paul"
    # 2) "ray"
    # 3) "hh"
    # 4) "jack"
    # 5) "viciky"
    # 6) "xx"
    

    返回80后,从第二个学生开始,并返回三个学生,可以借助LIMIT参数。

    ZRANGEBYSCORE a 1980 +inf LIMIT 1 3
    # 1) "ray"
    # 2) "hh"
    # 3) "jack"
    
    按指令得分返回从大到小返回元素列表
    ZREVRANGEBYSCORE key max min [WITHSCORE] [LIMIT offset count]
    

    ZREVRANGEBYSCORE指令同ZRANGEBYSCORE指令基本一致,只是返回结果是按照分数从大到小排列,同时分数的限制条件为 max min,先大后小,也是和ZRANGEBYSCORE指令相反,其他都一致。

    ZREVRANGEBYSCORE a +inf 1990 WITHSCORES
    # 1) "xx"
    # 2) "2011"
    # 3) "viciky"
    # 4) "1997"
    # 5) "jack"
    # 6) "1990"
    

    上述指令返回90后学生信息,并按年龄从小到大排列。

    给某元素增加分数
    ZINCRBY key increment member
    

    ZINCRBY指令用于对有序列表中某元素增加一个分数,即原始分数+增加的分数,并将该分数返回。如上述学生列表中,jack的出生年份录入错误,实际生日为1992,则可以使用增加分数指令。

    ZINCRBY a 2 jack
    # "1992"
    ZINCRBY a -2 xx
    # "2009"
    

    当要增加分数的元素不存在时,相当于ZADD命令。如

    ZINCRBY a -2 x  # x学生不存在
    # "-2"
    
    获取集合元素数量
    ZCARD key
    

    ZCARD可以返回有序集合的元素数量。

    ZCARD a
    # "8"
    
    获取指定分数范围内的元素数量
    ZCOUNT key min max
    

    ZCOUNT指令可以获取min、max之间(包含关系同ZRANGEBYSCORE一致,同时也支持-inf,+inf参数)的元素数量。

    ZCOUNT a (1982 1990
    # "2"
    
    删除一个或多个元素
    ZREM key member [member ...]
    

    ZREM指令用于从有序列表中删除指定的一个或多个元素,并返回成功删除的元素数量。如果元素不存在,则返回数量不包含该元素。

    ZCARD a 
    # (integer) 8
    ZREM a y x  # y不存在,x存在
    # (integer) 1
    ZCARD a 
    # (integer) 7
    
    按照排序范围删除元素
    ZREMRANGEBYRANK key start stop
    

    有序集合已经排序,ZREMRANGEBYRANK指令,将按照元素的从小到大书序,删除指定的start、stop范围内的所有元素,包括start、stop位置的元素,并返回删除的元素数量。该指令类似于列表的LTRIM指令,列表按照插入也是有序的。

    # 删除了年龄最大的前3个学生。
    ZREMRANGEBYRANK a 0 2
    # (integer) 3
    ZRANGE a 0 -1 # 剩余4个学生
    # 1) "hh"
    # 2) "jack"
    # 3) "viciky"
    # 4) "xx"
    # 删除剩余学生中年龄最小的两个人
    ZREMRANGEBYRANK a -2 -1
    # (integer) 2
    ZRANGE a 0 -1 # 剩余2个学生
    # 1) "hh"
    # 2) "jack"
    

    当指令指定范围超过有序列表的元素数量时,将删除全部元素,并返回成功删除的个数

    按照分数范围删除元素
    ZREMRANGEBYSCORE key min max
    

    ZREMRANGEBYSCORE命令将删除指定分数范围内的所有元素,查找方式和min、max的取值方式同ZRANGEBYSCORE指令的参数设置方式完全相同,当删除完成时,返回删除的元素数量。

    学生出生日期有序列表中还剩余两个学生,使用生日范围删除

    ZRANGE a 0 -1
    # 1) "lucy"
    # 2) "jack"
    ZREMRANGEBYSCORE a 1990 (2000
    # (integer) 1
    
    获取元素的排名
    ZRANK key member
    

    ZRANK指令按照有序列表从小到大顺序获取元素的排名,由于数据的索引从0开始,因此返回的实际是索引值。

    ZADD a 1987 ray 1990 hh
    ZRANGE a 0 -1
    # 1) "ray"
    # 2) "hh"
    # 3) "jack"
    ZRANK a hh
    # (integer) 1
    
    获取元素降序排名
    ZREVRANK key member
    

    ZREVRANK同ZRANK基本一致,只不过是降序排名。

    ZREVRANK a hh
    # (integer) 1
    ZREVRANK a jack
    # (integer) 0
    
    有序集合的交集
    ZINTERSTORE destination numKeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]
    

    ZINTERSTORE指令用于计算给定的一个或多个集合的交集,并将结果存储到destination集合中。其中key的数量必须与numKeys一致,如numKeys=2,则其后需要跟两个集合的key。

    交集计算后的元素分数,由AGGREGATE参数确定。其支持三种方式:

    • SUM,交集计算后元素分数为多个集合中该元素的分数之和,SUM为默认值
    • MIN,交集计算后元素的分数为多个集合中该元素的最小分数。
    • MAX,交集计算后元素的分数为多个集合中该元素的最大分数。

    创建一个学生的多科成绩表:

    # 集合a为语文成绩,集合b为数学成绩
    ZADD a 98 ray 89 hh 78 xx 80 jack
    # (integer) 4
    ZADD b 87 ray 100 hh 78 xx 90 tom
    # (integer) 4
    

    使用默认进行交集计算学生的两科总成绩,此时传递AGGREGATE参数为SUM或者不传递AGGREGATE参数,效果一致。

    ZINTERSTORE c 2 a b # jack没有参加数学,tom没有参加语文,因此总成绩只有三人,并将结果存储到c集合中
    # (integer) 3
    ZRANG c 0 -1 WITHSCORES # 此时交集为各科成绩之和
    # 1) "xx"
    # 2) "156"
    # 3) "ray"
    # 4) "185"
    # 5) "hh"
    # 6) "189"
    

    采用AGGREGATE参数,取参与每科考试的学生,成绩较差的一科,用于分析学生考试差的原因。

    ZINTERSTORE d 2 a b AGGREGATE MIN # 结果存储到d集合,有三人数据
    # (integer) 3
    ZRANGE d 0 -1 WITHSCORES    # 此时交集为各科最差成绩
    # 1) "xx"
    # 2) "78"
    # 3) "ray"
    # 4) "87"
    # 5) "hh"
    # 6) "89"
    

    获取参与考试的学生考的最好学科,采用MAX参数。

    ZINTERSTORE e 2 a b AGGREGATE MAX # 结果存储到e集合
    # (integer) 3
    ZRANGE e 0 -1 WITHSCORES    # 此时交集为各科最好成绩
    # 1) "xx"
    # 2) "78"
    # 3) "ray"
    # 4) "98"
    # 5) "hh"
    # 6) "100"
    

    交集参数中还有一个参数WEIGHTS,用于指定每个集合中的得分权重,计算时,每个集合中的元素分数会乘上该集合的权重,集合的权重与集合key的顺序一致。如果指定WEIGHTS参数时,后面跟谁的权重参数必须和key的个数对应,否则将会报指令格式不合法的异常

    在计算两科总成绩时,由于语文成绩较难,因此需要加上一个1.2倍的系数,作为总成绩。

    ZINTERSTORE f 2 a b WEIGHTS 1.2 1
    # (integer) 3
    ZRANGE f 0 -1 WITHSCORES
    # 1) "xx"
    # 2) "171.59999999999999"   # = 78 * 1.2 + 78
    # 3) "ray"
    # 4) "204.59999999999999"
    # 5) "hh"
    # 6) "206.80000000000001"
    
    有序集合的并集
    ZUNIONSTORE destination numKeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]
    

    ZUNIONSTORE指令用于计算集合的并集,并将结果存储到destination中。中key的数量必须与numKeys一致,如numKeys=2,则其后需要跟两个集合的key。

    除了执行并集外,其余参数及指令格式均与有序集合的交集一致。

    采用并集计算参加考试的所有学生总成绩,此时即使缺考也会被计算。

    ZUNIONSTORE g 2 a b
    # (integer) 5
    ZRANGE g 0 -1 WITHSCORES
    # 1) "jack"
    # 2) "80"
    # 3) "tom"
    # 4) "90"
    # 5) "xx"
    # 6) "156"
    # 7) "ray"
    # 8) "185"
    # 9) "hh"
    #10) "189"
    

    相关文章

      网友评论

        本文标题:详尽Redis有序集合指令

        本文链接:https://www.haomeiwen.com/subject/lzitahtx.html