# 2.6 针对有序集合的命令

zset:有序集合(sorted set),也叫zset.和集合有一定的相似性,其中都不能出现重复的元素.在有序集合中,每个元素都会对一个一个score参数,以该参数作为排序的依据

## 2.6.1 读写有序集合的命令

* `ZADD`
  * 语法:`ZADD key [NX|XX] [CH] [INCR] score member [score member ...]`.其中:
    * NX:当key对应的zset不存在时才能添加元素
    * XX:当key对应的zset存在时才能添加元素
    * CH:不指定该选项时,则`ZADD`默认只返回新添加到zset中的元素数量;指定该选项时,则`ZADD`命令将返回被更新或添加的元素数量
    * INCR:当待插入的member不存在时,该参数无效;当待插入的member已存在时,则表示指定一个增量添加到已有member的分数上
    * score:用于描述元素的数值(权重)
    * memeber:元素的值
* `ZRANGE`
  * 语法:`ZRANGE key start stop [WITHSCORES]`.其中:
    * start:起始索引位置
    * stop:结束索引位置
    * WITHSCORES:同时展示元素所对应的score值
    * 功能:通过索引区间返回zset中指定区间内的成员.该命令以元素在zset中score的**升序**排序

例:

创建一个zset:

```
127.0.0.1:6379> ZADD emp 4.0 Mike 2.0 Peter 1.0 Tim 0.5 Johnson 0.0 David
(integer) 5
```

按元素在zset中的score升序排序,查询索引在\[0,2]范围内的元素:

```
127.0.0.1:6379> ZRANGE emp 0 2
1) "David"
2) "Johnson"
3) "Tim"
```

按元素在zset中的score升序排序,查询索引在\[0,2]范围内的元素及其权重:

```
127.0.0.1:6379> ZRANGE emp 0 2 WITHSCORES
1) "David"
2) "0"
3) "Johnson"
4) "0.5"
5) "Tim"
6) "1"
```

可以看到,按索引从zset中读取元素时,是按照元素在zset中的score升序排序的

* `ZREVRANGE`
  * 语法:`ZREVRANGE key start stop [WITHSCORES]`.其中:
    * start:起始索引位置
    * stop:结束索引位置
    * WITHSCORES:同时展示元素所对应的score值
    * 功能:通过索引区间返回zset中指定区间内的成员.该命令以元素在zset中score的**降序**排序

例:

查看zset中的所有元素及其对应的权重:

```
127.0.0.1:6379> ZRANGE emp 0 -1 WITHSCORES
 1) "David"
 2) "0"
 3) "Johnson"
 4) "0.5"
 5) "Tim"
 6) "1"
 7) "Peter"
 8) "2"
 9) "Mike"
10) "4"
```

按元素在zset中的score降序排序,查询索引在\[0,2]范围内的元素:

```
127.0.0.1:6379> ZREVRANGE emp 0 2
1) "Mike"
2) "Peter"
3) "Tim"
```

按元素在zset中的score降序排序,查询索引在\[0,2]范围内的元素及其权重:

```
127.0.0.1:6379> ZREVRANGE emp 0 2 WITHSCORES
1) "Mike"
2) "4"
3) "Peter"
4) "2"
5) "Tim"
6) "1"
```

* `ZRANGEBYSCORE`
  * 语法:`ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]`.其中:
    * key:zset对应的key
    * min/max:类似查询条件.查询条件默认为:score ∈ \[min, max],可以使用`(min`的方式来调整区间的开闭
    * WITHSCORES:同上文
    * LIMIT:偏移量.offset表示偏移量,count表示取多少条
    * 功能:返回有序集中指定分数区间内的成员,分数从低到高排序

例:

使用`ZRANGEBYSCORE`命令查看zset中所有成员,score升序排序:

```
127.0.0.1:6379> ZRANGEBYSCORE emp -inf +inf WITHSCORES
 1) "David"
 2) "0"
 3) "Johnson"
 4) "0.5"
 5) "Tim"
 6) "1"
 7) "Peter"
 8) "2"
 9) "Mike"
10) "4"
```

使用`ZRANGEBYSCORE`命令查看zset中score ∈ \[0, 4]的成员及其权重:

```
127.0.0.1:6379> ZRANGEBYSCORE emp 0 4 WITHSCORES
 1) "David"
 2) "0"
 3) "Johnson"
 4) "0.5"
 5) "Tim"
 6) "1"
 7) "Peter"
 8) "2"
 9) "Mike"
10) "4"
```

使用`ZRANGEBYSCORE`命令查看zset中score ∈ (0, 4]的成员及其权重

```
127.0.0.1:6379> ZRANGEBYSCORE emp (0 4 WITHSCORES
1) "Johnson"
2) "0.5"
3) "Tim"
4) "1"
5) "Peter"
6) "2"
7) "Mike"
8) "4"
```

* `ZREVRANGEBYSCORE`
  * 语法:`ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count]`.其中:
    * key:zset对应的key
    * max/min:类似查询条件.查询条件默认为:score ∈ \[max, min],可以使用`(min`的方式来调整区间的开闭
    * WITHSCORES:同上文
    * LIMIT:偏移量.offset表示偏移量,count表示取多少条
    * 功能:返回有序集中指定分数区间内的成员,分数从高到低排序

例:

使用`ZREVRANGEBYSCORE`命令查看zset中所有成员,score降序排序:

```
127.0.0.1:6379> ZREVRANGEBYSCORE emp +inf -inf WITHSCORES
 1) "Mike"
 2) "4"
 3) "Peter"
 4) "2"
 5) "Tim"
 6) "1"
 7) "Johnson"
 8) "0.5"
 9) "David"
10) "0"
```

使用`ZREVRANGEBYSCORE`命令查看zset中score ∈ \[4, 0]的成员及其权重:

```
127.0.0.1:6379> ZREVRANGEBYSCORE emp 4 0 WITHSCORES
 1) "Mike"
 2) "4"
 3) "Peter"
 4) "2"
 5) "Tim"
 6) "1"
 7) "Johnson"
 8) "0.5"
 9) "David"
10) "0"
```

使用`ZREVRANGEBYSCORE`命令查看zset中score ∈ \[4, 0)的成员及其权重:

```
127.0.0.1:6379> ZREVRANGEBYSCORE emp 4 (0 WITHSCORES
1) "Mike"
2) "4"
3) "Peter"
4) "2"
5) "Tim"
6) "1"
7) "Johnson"
8) "0.5"
```

## 2.6.2 通过`ZINCRBY`命令修改元素的分值

* `ZINCRBY`
  * 语法:`ZINCRBY key increment member`.其中:
    * key:zset对应的键名
    * increment:score的变化量(可以为负数)
    * member:成员值
    * 功能:zset中对指定成员的分数加上增量increment.该命令的返回值为成员修改后的score

例:

查看有序集合中所有成员及其对应的score,按score升序排序:

```
127.0.0.1:6379> ZRANGEBYSCORE emp -inf +inf WITHSCORES
 1) "David"
 2) "0"
 3) "Johnson"
 4) "0.5"
 5) "Tim"
 6) "1"
 7) "Peter"
 8) "2"
 9) "Mike"
10) "4"
```

修改成员David的score,使该成员的score值减1:

```
127.0.0.1:6379> ZINCRBY emp -1 David
"-1"
```

对一个不存在于zset中的成员使用`ZINCRBY`命令:

```
127.0.0.1:6379> ZINCRBY emp -1 Kobe
"-1"
```

查看结果:

```
127.0.0.1:6379> ZRANGEBYSCORE emp -inf +inf WITHSCORES
 1) "David"
 2) "-1"
 3) "Kobe"
 4) "-1"
 5) "Johnson"
 6) "0.5"
 7) "Tim"
 8) "1"
 9) "Peter"
10) "2"
11) "Mike"
12) "4"
```

可以看到,对一个不存在于zset中的成员使用`ZINCRBY`命令后,该成员会被添加到zset中,并且该成员的score即为increment

## 2.6.3 用`ZSCORE`命令获取指定成员的分数

* `ZSCORE`
  * 语法:`ZSCORE key member`
  * 功能:查看key对应的set中,member的score.若key或member不存在则返回nil

例:

查看zset中的全部成员:

```
127.0.0.1:6379> ZRANGEBYSCORE emp -inf +inf WITHSCORES
 1) "David"
 2) "-1"
 3) "Kobe"
 4) "-1"
 5) "Johnson"
 6) "0.5"
 7) "Tim"
 8) "1"
 9) "Peter"
10) "2"
11) "Mike"
12) "4"
```

查看成员David的score:

```
127.0.0.1:6379> ZSCORE emp David
"-1"
```

查看zset中不存在的memeber:

```
127.0.0.1:6379> ZSCORE emp Allen
(nil)
```

对一个不存在的zset使用`ZSCORE`命令:

```
127.0.0.1:6379> ZSCORE notExist foo
(nil)
```

注意:`ZSCORE`命令只能返回1个元素的score

## 2.6.4 查看有序集合里的元素排名

* `ZRANK`
  * 语法:`ZRANK key member`
  * 功能:获取指定成员在zset中的索引,排序按score升序排序.若key或member不存在则返回nil
* `ZREVRANK`
  * 语法:`ZREVRANK key member`
  * 功能:获取指定成员在zset中的索引,排序按score降序排序.若key或member不存在则返回nil

例:

查看zset中所有成员及其对应score,按score升序排序:

```
127.0.0.1:6379> ZRANGEBYSCORE emp -inf +inf WITHSCORES
 1) "David"
 2) "-1"
 3) "Kobe"
 4) "-1"
 5) "Johnson"
 6) "0.5"
 7) "Tim"
 8) "1"
 9) "Peter"
10) "2"
11) "Mike"
12) "4"
```

查看David在zset中的索引,按score升序排序:

```
127.0.0.1:6379> ZRANK emp David
(integer) 0
```

查看zset中所有成员及其对应score,按score降序排序:

```
127.0.0.1:6379> ZREVRANGEBYSCORE emp +inf -inf WITHSCORES
 1) "Mike"
 2) "4"
 3) "Peter"
 4) "2"
 5) "Tim"
 6) "1"
 7) "Johnson"
 8) "0.5"
 9) "Kobe"
10) "-1"
11) "David"
12) "-1"
```

查看David在zset中的索引,按score降序排序:

```
127.0.0.1:6379> ZREVRANK emp David
(integer) 5
```

查看在zset中不存在的成员的索引:

```
127.0.0.1:6379> ZRANK emp Allen
(nil)
```

可以看到,当成员在zset中不存在时,返回值为nil

对一个不存在的zset查看其成员中的索引:

```
127.0.0.1:6379> ZRANK number one
(nil)
```

可以看到,当zset不存在时,返回值为nil

## 2.6.5 删除有序集合里的值

* `ZREM`
  * 语法:`ZREM key member [member ...]`
  * 功能:删除key指向的zset中的1个或多个成员.返回值为删除成员的数量

例:

查看zset中所有成员及其对应的score:

```
127.0.0.1:6379> ZRANGEBYSCORE emp -inf +inf WITHSCORES
 1) "David"
 2) "-1"
 3) "Kobe"
 4) "-1"
 5) "Johnson"
 6) "0.5"
 7) "Tim"
 8) "1"
 9) "Peter"
10) "2"
11) "Mike"
12) "4"
```

删除值为David的成员:

```
127.0.0.1:6379> ZREM emp David
(integer) 1
```

删除值为Kobe和值为Johnson的成员:

```
127.0.0.1:6379> ZREM emp Kobe Johnson
(integer) 2
```

查看zset中所有成员及其对应的score:

```
127.0.0.1:6379> ZRANGEBYSCORE emp -inf +inf WITHSCORES
1) "Tim"
2) "1"
3) "Peter"
4) "2"
5) "Mike"
6) "4"
```

删除一个zset中不存在的成员:

```
127.0.0.1:6379> ZREM emp Allen
(integer) 0
```

可以看到,对一个zset中不存在的成员执行删除操作,返回值为0

对一个不存在的zset执行`ZREM`命令:

```
127.0.0.1:6379> ZREM notExist one
(integer) 0
```

可以看到,对一个不存在的zset执行`ZREM`命令,返回值为0

* `ZREMRANGEBYRANK`
  * 语法:`ZREMRANGEBYRANK key start stop`
  * 功能:删除zset中索引在\[start, stop]范围内的成员,返回值为删除元素的个数.索引默认按score升序排序,但如果start和stop为负数,则表示要删除score较高的成员

例:

删除并创建一个zset:

```
127.0.0.1:6379> DEL emp
(integer) 1
127.0.0.1:6379> ZADD emp 0 David 0.5 Johnson 1 Tim 2 Peter 4 Mike
(integer) 5
```

查看zset中所有成员及其对应的score:

```
127.0.0.1:6379> ZRANGE emp 0 5 WITHSCORES
 1) "David"
 2) "0"
 3) "Johnson"
 4) "0.5"
 5) "Tim"
 6) "1"
 7) "Peter"
 8) "2"
 9) "Mike"
10) "4"
```

删除zset中索引在\[1,3]范围内的成员,按score升序排序:

```
127.0.0.1:6379> ZREMRANGEBYRANK emp 1 3
(integer) 3
```

查看删除后的zset:

```
127.0.0.1:6379> ZRANGE emp 0 5 WITHSCORES
1) "David"
2) "0"
3) "Mike"
4) "4"
```

注:没有`ZREVREMRANGEBYRANK`命令,但是可以通过负数索引的方式删除分数最高的几个成员

例:

删除并重新创建zset:

```
127.0.0.1:6379> DEL emp
(integer) 1
127.0.0.1:6379> ZADD emp 0 David 0.5 Johnson 1 Tim 2 Peter 4 Mike
(integer) 5
```

查看zset中所有成员及其对应的score:

```
127.0.0.1:6379> ZRANGE emp 0 5 WITHSCORES
 1) "David"
 2) "0"
 3) "Johnson"
 4) "0.5"
 5) "Tim"
 6) "1"
 7) "Peter"
 8) "2"
 9) "Mike"
10) "4"
```

按分数从高到低排序,删除分数排名第2到分数排名第4的3个成员:

```
127.0.0.1:6379> ZREMRANGEBYRANK emp -4 -2
(integer) 3
```

查看删除结果:

```
127.0.0.1:6379> ZRANGE emp 0 5 WITHSCORES
1) "David"
2) "0"
3) "Mike"
4) "4"
```

* `ZREMRANGEBYSCORE`
  * 语法:`ZREMRANGEBYSCORE key min max`
  * 功能:删除zset中score在\[min, max]范围内的成员,返回值为删除元素的个数

例:

删除并重新创建一个zset:

```
127.0.0.1:6379> DEL emp
(integer) 1
127.0.0.1:6379> ZADD emp 0 David 0.5 Johnson 1 Tim 2 Peter 4 Mike
(integer) 5
```

查看zset中所有成员及其对应的score:

```
127.0.0.1:6379> ZRANGE emp 0 5 WITHSCORES
 1) "David"
 2) "0"
 3) "Johnson"
 4) "0.5"
 5) "Tim"
 6) "1"
 7) "Peter"
 8) "2"
 9) "Mike"
10) "4"
```

删除score在\[0,1]范围内的成员:

```
127.0.0.1:6379> ZREMRANGEBYSCORE emp 0 1
(integer) 3
```

查看删除后的zset:

```
127.0.0.1:6379> ZRANGE emp 0 5 WITHSCORES
1) "Peter"
2) "2"
3) "Mike"
4) "4"
```

删除score在\[2,4)范围内的成员:

```
127.0.0.1:6379> ZREMRANGEBYSCORE emp 2 (4
(integer) 1
```

查看删除后的zset:

```
127.0.0.1:6379> ZRANGE emp 0 5 WITHSCORES
1) "Mike"
2) "4"
```

注:没有`ZREVREMRANGEBYSCORE`命令.因为无论是按score升序还是降序排序,最终要删除的都是给定score范围内的数据
