数据类型;有序集合类型(sorted set)


有序集合sortedset

一特点

1、有序、去重
2、元素是字符串类型
3、每个元素都关联着一个浮点数分值(score),并按照分支从小到大的顺序排列集合中的元素(分值可以相同)
4、最多包含2^32-1元素

示例1:一个保存了水果价格的有序集合

分值 2.0 4.0 6.0 8.0
元素 西瓜 葡萄 芒果 香蕉

示例2:一个保存了员工薪水的有序集合

分值 6000 8000 10000 12000
元素 lucy tom jim jack

示例3:一个保存了正在阅读某些技术书的人数

分值 300 400 500 600
元素 核心编程 数据库 django redis

二命令汇总

# 在有序集合中添加一个成员
    zadd key score member
# 查看指定区间元素(升序)
    zrange key start stop [withscores]
# 查看指定区间元素(降序)
    ZREVRANGE key start stop [withscores]
# 查看指定元素的分值
    ZSCORE key member
# 返回指定区间元素
# offset : 跳过多少个元素
# count : 返回几个
# 小括号 : 开区间  zrangebyscore fruits (2.0 8.0
    zrangebyscore key min max [withscores]     [limit offset count]
# 删除成员
    zrem key member
# 增加或者减少分值
    zincrby key increment member
                   值      成员
# 返回元素排名
    zrank key member
# 返回元素逆序排名
    zrevrank key member
# 删除指定区间内的元素
    zremrangebyscore key min max
# 返回集合中元素个数
    zcard key
# 返回指定范围中元素的个数
    zcount key min max
    zcount fruits 4 7 
    zcount fruits (4 7   4#'('是开区间不包括
                  (4 (7  4# 并集
zunionstore destination numkeys key [weights 权重值] [AGGREGATE SUM|MIN|MAX]
# 有几个集合numkeys就是几  权重值也要相应的给几个
# 交集:和并集类似,只取相同的元素
ZINTERSTORE destination numkeys key1 key2 WEIGHTS weight AGGREGATE SUM|MIN|MAX

操作命令演示

1.查看: 指定索引区间元素(升序)

  zrange key start stop [withscores]

127.0.0.1:6379> ZRANGE salary 0 -1
1) "lucy"
2) "tom"
3) "jim"
4) "jack"
127.0.0.1:6379> ZRANGE salary 0 -1 withscores
1) "lucy"
2) "6000"
3) "tom"
4) "8000"
5) "jim"
6) "10000"
7) "jack"
8) "12000"

2.查看: 指定索引区间元素(降序)

 

  ZREVRANGE key start stop [withscores]

3.显示指定元素的分值

  ZSCORE key member

127.0.0.1:6379> zscore salary jack
"14000"

4.返回指定区间元素

  zrangebyscore key min max [withscores] [limit offset count]

  offset : 跳过多少个元素

  count : 返回几个

  小括号 : 开区间 zrangebyscore fruits (2.0 8.0

127.0.0.1:6379> ZRANGEBYSCORE salary (8000 12000
1) "jim"
2) "jack"
127.0.0.1:6379> ZRANGE salary 0 -1 withscores
1) "lucy"
2) "6000"
3) "tom"
4) "8000"
5) "jim"
6) "10000"
7) "jack"
8) "12000"

5.删除

  zrem key member

127.0.0.1:6379> ZREM salary jim
(integer) 1
127.0.0.1:6379> ZRANGE salary 0 -1 withscores
1) "lucy"
2) "6000"
3) "tom"
4) "8000"
5) "jack"
6) "12000"

6.增加或者减少分值

  zincrby key increment member

127.0.0.1:6379> ZINCRBY salary 2000 jack
"14000"
127.0.0.1:6379> ZRANGE salary 0 -1 withscores
1) "lucy"
2) "6000"
3) "tom"
4) "8000"
5) "jack"
6) "14000"

7.返回元素的排名(索引)

  zrank key member

127.0.0.1:6379> zrank salary jack
(integer) 2

8.返回元素逆序排名

  zrevrank key member

127.0.0.1:6379> ZREVRANK salary jack
(integer) 0
127.0.0.1:6379> ZREVRANK salary lucy
(integer) 2

9.删除指定区间内的元素

  zremrangebyscore key min max

127.0.0.1:6379> ZREMRANGEBYSCORE salary 4000 6000
(integer) 1
127.0.0.1:6379> ZRANGE salary 0 -1 withscores
1) "tom"
2) "8000"
3) "jack"
4) "14000"

10.返回集合中元素个数

  zcard key

127.0.0.1:6379> ZCARD salary
(integer) 2

11.返回指定范围中元素的个数

  zcount key min max

  zcount fruits 4 7

  zcount fruits (4 7

127.0.0.1:6379> ZRANGE salary 0 -1 withscores
1) "tom"
2) "8000"
3) "jack"
4) "14000"
127.0.0.1:6379> zcount salary 8000 14000
(integer) 2
# 不包含8000,包含14000
127.0.0.1:6379> zcount salary (8000 14000
(integer) 1

12.并集

  zunionstore destination numkeys key [weights ] [AGGREGATE SUM|MIN|MAX]

127.0.0.1:6379> zadd stu_score1 60 tom 70 jim
(integer) 2
127.0.0.1:6379> zadd stu_score2 80 tom 90 lucy
(integer) 2
# 默认为SUM
127.0.0.1:6379> ZUNIONSTORE stu_score3 2 stu_score1 stu_score2
(integer) 3
127.0.0.1:6379> ZRANGE stu_score3 0 -1 withscores
1) "jim"
2) "70"
3) "lucy"
4) "90"
5) "tom"
6) "140"
127.0.0.1:6379> 
# WEIGHTS 和 AGGREGATE 
127.0.0.1:6379> ZRANGE stu_score1 0 -1 withscores
1) "tom"
2) "60"
3) "jim"
4) "70"
127.0.0.1:6379> ZRANGE stu_score2 0 -1 withscores
1) "tom"
2) "80"
3) "lucy"
4) "90"
# 权重1给stu_score1,权重0.5给stu_score2,算完权重之后求和SUM
127.0.0.1:6379> ZUNIONSTORE stu_score8 2 stu_score1 stu_score2 weights 1 0.5 AGGREGATE SUM
(integer) 3
127.0.0.1:6379> ZRANGE stu_score8 0 -1 withscores
1) "lucy"
2) "45"
3) "jim"
4) "70"
5) "tom"
6) "100"
127.0.0.1:6379> 

12.交集

  ZINTERSTORE destination numkeys key1 key2 WEIGHTS weight AGGREGATE SUM|MIN|MAX

  和并集类似,只取相同的元素

python操作sorted set

import redis

r = redis.Redis(host='192.168.43.49',port=6379,password='123456',db=0)
# 注意第二个参数为字典
r.zadd('salary',{'tom':6000,'jim':8000,'jack':12000})
# 结果为列表中存放元组[(),(),()]
print(r.zrange('salary',0,-1,withscores=True))
print(r.zrevrange('salary',0,-1,withscores=True))
# start:起始值,num:显示条数
print(r.zrangebyscore('salary',6000,12000,start=1,num=2,withscores=True))
# 删除
r.zrem('salary','tom')
print(r.zrange('salary',0,-1,withscores=True))
# 增加分值
r.zincrby('salary',5000,'jack')
print(r.zrange('salary',0,-1,withscores=True))
# 返回元素排名
print(r.zrank('salary','jack'))
print(r.zrevrank('salary','jack'))
# 删除指定区间内的元素
r.zremrangebyscore('salary',6000,8000)
print(r.zrange('salary',0,-1,withscores=True))
# 统计元素个数
print(r.zcard('salary'))
# 返回指定范围内元素个数
print(r.zcount('salary',6000,20000))
# 并集
r.zadd('salary2',{'jack':17000,'lucy':8000})
r.zunionstore('salary3',('salary','salary2'),aggregate='max')
print(r.zrange('salary3',0,-1,withscores=True))
# 交集
r.zinterstore('salary4',('salary','salary2'),aggregate='max')
print(r.zrange('salary4',0,-1,withscores=True))

 案例1:网易音乐排行榜

1、每首歌的歌名作为元素(先不考虑重复)
2、每首歌的播放次数作为分值
3、使用ZREVRANGE来获取播放次数最多的歌曲

import redis

r = redis.Redis(host='192.168.43.49',port=6379,password='123456',db=0)

r.zadd('ranking',{'song1':1,'song2':1,'song3':1,'song4':1})
r.zadd('ranking',{'song5':1,'song6':1,'song7':1})
r.zadd('ranking',{'song8':1,'song9':1})

r.zincrby('ranking',50,'song3')
r.zincrby('ranking',60,'song5')
r.zincrby('ranking',80,'song7')
# 获取前3名
rlist = r.zrevrange('ranking',0,2,withscores=True)

i = 1
for r in rlist:
    print('第%d名:%s' % (i,r[0].decode()))
    #print('第{}名:{}播放次数:{}'.format(i,name[0].decode(),int(name[1])))
    i += 1

案例2: 京东商品畅销榜

# 第1天
  ZADD mobile-001 5000 'huawei' 4000 'oppo' 3000 'iphone'
# 第2天
  ZADD mobile-002 5200 'huawei' 4300 'oppo' 3230 'iphone'
# 第3天
  ZADD mobile-003 5500 'huawei' 4660 'oppo' 3580 'iphone'
问题:如何获取三款收集的销量排名?
  ZUNIONSTORE mobile-001:003 mobile-001 mobile-002 mobile-003 # 可否?
# 正确
  1、ZADD mobile-003 5500 'huawei' 4660 'oppo' 3580 'iphone'
  2、ZUNIONSTORE mobile-001:003 mobile-001 mobile-002 mobile-003 AGGREGATE MAX

import redis

r = redis.Redis(host='127.0.0.1', port=6379, db=0)
# 先定义三个集合mobile-001,mobile-002,mobile-003
# 定义三个字典
day01_dict = {
  'huawei': 5000,
  'oppo': 4000,
  'iphone': 3000
}
day02_dict = {
  'huawei': 5200,
  'oppo': 4300,
  'iphone': 3890
}
day03_dict = {
  'huawei': 5500,
  'oppo': 4600,
  'iphone': 3500
}
r.zadd('mobile-001', day01_dict)
r.zadd('mobile-002', day02_dict)
r.zadd('mobile-003', day03_dict)
r.zinterstore(
  'mobile-001:003',
  ('mobile-001', 'mobile-002', 'mobile-003'),
  aggregate='max'
)
# 逆序
res = r.zrevrange('mobile-001:003', 0, 2, withscores=True)
for i in res:
  print('{}-{}'.format(i[0].decode(), i[1]))