一、前言

关于redis的zrangebylex的使用,官网和各种课程,给的案例很粗糙,难以理解。

本文带你了解以下内容:

1、zrangebylex它是干什么的

2、zrangebylex命令到底是怎么用?

3、sorted_set有哪些不可不知的秘密?

二、zrangebylex详解

1.zrangebylex的作用和注意事项

作用:按字典从低到高排序,取索引范围内的元素(集合内的分值需相同) 

127.0.0.1:6379> help zrangebylex

ZRANGEBYLEX key min max [LIMIT offset count]
summary: Return a range of members in a sorted set, by lexicographical range
since: 2.8.9
group: sorted_set

注意事项:
1.分数必须相同! 如果有序集合中的成员分数有不一致的,返回的结果就不准。
2.成员字符串作为二进制数组的字节数进行比较。
3.默认是以ASCII字符集的顺序进行排列。如果成员字符串包含utf-8这类字符集(比如:汉字)的内容,就会影响返回结果,所以建议不要使用。
4.默认情况下, “max” 和 “min” 参数前必须加 “[” 符号作为开头。”[” 符号与成员之间不能有空格, 返回成员结果集会包含参数 “min” 和 “max” 。
5.“max” 和 “min” 参数前可以加 “(” 符号作为开头表示小于, “(” 符号与成员之间不能有空格。返回成员结果集不会包含 “max” 和 “min” 成员。
可以使用 “-” 和 “+” 表示得分最小值和最大值
6.zrangebylex(它的参数是min 在前 max在后)获取顺序相反的指令是zrevrangebylex (它的参是 max 在前 min 在后)。
7.源码中采用C语言中memcmp() 函数, 从字符的第0位到最后一位进行排序,如果前面部分相同,那么较长的字符串比较短的字符串排序靠后。

 使用场景:分数相同的有序集合中;LEX结尾的指令是要求分数必须相同。

 2.zrangebylex的经典案例

1.用 “-” 和 “+” 表示得分最小值和最大值

127.0.0.1:6379> zadd num 100 aa  100 cc 100 bb 100 ff 100 ee 100 gg 添加分值相同的元素
6
127.0.0.1:6379> zrangebylex num - +  获取所有元素
aa
bb
cc
ee
ff
gg

2.limit分页的使用

语法: zrangebylex  key min max [LIMIT offset count]
min 是起始元素位置,- 代表从第0位开始
max 是终止元素位置,+ 代表到最后一个元素
offset 是指下标索引的起始值,
count 是指,从下标索引offset的位置开始(包含offset所对应的元素),向后取几个元素 

127.0.0.1:6379> flushdb
127.0.0.1:6379> zadd num 100 aa  100 cc 100 bb 100 ff 100 ee 100 gg
6
127.0.0.1:6379> zrangebylex num - + limit 0 2  每页2条数据,取第1页
aa
bb
127.0.0.1:6379> zrangebylex num - + limit 2 2 每页2条数据,取第2页
cc
ee
127.0.0.1:6379> zrangebylex num - + limit 4 2 每页2条数据,取第3页
ff
gg
127.0.0.1:6379>

3.用[和(获取成员之间的的元素

[ 包含该元素
( 不包含该元素
提示:
1、[或者(与 元素之间,不能有空格;
2 、他们后面都紧跟元素(或元素前几个字母)
3、如果元素都是字母时,且 [ 或( 后面紧跟不是整个元素,是元素的几个首字母,结果可能不准确!!! 

127.0.0.1:6379> flushdb
127.0.0.1:6379> zadd num 100 aa  100 cc 100 bb 100 ff 100 ee 100 gg  添加分值相同的元素
6
127.0.0.1:6379> zrangebylex num - +  查元素列表
aa
bb
cc
ee
ff
gg
127.0.0.1:6379> zrangebylex num [bb [ee  从元素bb开始取元素,直到ee的位置(包含起止位置)
bb
cc
ee
127.0.0.1:6379> zrangebylex num [bb (ee 从元素bb开始取元素,直到ee的位置(包含起始位置,不包含终止位置)
bb
cc
127.0.0.1:6379> zrangebylex num (bb (ee  从元素bb开始取元素,直到ee的位置(不包含起止位置)
cc
127.0.0.1:6379>

4.获取指定号段的手机号码

127.0.0.1:6379> flushall
OK
127.0.0.1:6379> zadd phone 0 13100111100 0 13110114300 0 13132110901 添加131号段的数据
3
127.0.0.1:6379> zadd phone 0 13200111100 0 13210414300 0 13252110901 添加132号段的数据
3
127.0.0.1:6379> zadd phone 0 13300111100 0 13310414300 0 13352110901 添加133号段的数据
3
127.0.0.1:6379> zrangebylex phone - +  获取全部号段的数据
13100111100
13110114300
13132110901
13200111100
13210414300
13252110901
13300111100
13310414300
13352110901
127.0.0.1:6379> zrangebylex phone [132 (133   仅获取132号段的数据
13200111100
13210414300
13252110901
127.0.0.1:6379> zrangebylex phone [133 (134  仅获取133号段的数据
13300111100
13310414300
13352110901
127.0.0.1:6379> zrangebylex phone [132 (134  获取132和133号段的数据
13200111100
13210414300
13252110901
13300111100
13310414300
13352110901
127.0.0.1:6379>

5.获取指定字母开头的姓名

127.0.0.1:6379> zadd names 0 meimei  0 jiji 0 tom 0 green 0 mali 0 ali 0 xiaoming 添加测试数据
7
127.0.0.1:6379> zrangebylex names - +  获取全部元素(默认自带排序)
ali
green
jiji
mali
meimei
tom
xiaoming
127.0.0.1:6379> zrangebylex names [j [m  希望得到j开头的姓名到m开头的姓名,事与愿违(得到的是不准确答案,没有取到m开头的元素)
jiji
127.0.0.1:6379> zrangebylex names [j [t 希望得到j开头的姓名到t开头的姓名,事与愿违(依然得到的是不准确答案,没有取到t开头的元素)
jiji
mali
meimei
127.0.0.1:6379> zrangebylex names [j (t  得到了准确的答案
jiji
mali
meimei
127.0.0.1:6379> zrangebylex names [a [m 得到的依然不准确的答案,m开头的元素没有取到
ali
green
jiji
127.0.0.1:6379> zrangebylex names [ji [me 得到的依然不准确的答案,meimei显然没有被取到
jiji
mali
127.0.0.1:6379> zrangebylex names [jiji [meimei 得到了准确的答案(原因是写的元素全拼)
jiji
mali
meimei
127.0.0.1:6379>

综上所述,在使用[或(获取一定范围的元素时,如果临界元素不是全拼,得到的结果可能是不准确的。 

三、sorted_set不可不知的秘密

首先,看到这个命令,必须把“它内部存储的是有序的不重复的成员”刻在骨子里。

其次是它比set集合多了一个score分值,用法更加灵活。

1.所有命令均以z开头

常用的有:

zadd 添加一/多个元素[更新分值]

zscore 获取元素分值

zcard 获取集合中元素的个数

zcount 指定分值区间,获取元素的个数

zrank 确定排序集中成员的索引(分数从低到高排列)

zrevrank 确定排序集中成员的索引(分数从高到低排列)

zrange 根据索引范围获取集合元素,从低到高取(索引从0开始)

zrevrange 根据索引范围获取集合元素,从高到低取

……还有很多

2. 关于排序(重要)

1.默认排序

默认按分值从到高排序,因为zset集合不允许存在重复元素,所以添加元素时,如有相同的,后面的会覆盖前面的。

127.0.0.1:6379> flushall
OK
127.0.0.1:6379> zadd num 14 aa 8 bb 2 cc 19 dd 6 ff  添加不同分值的元素
5
127.0.0.1:6379> zrange num 0 -1 withscores  查看元素列表,可以看到是默认按由低到高排的
cc
2
ff
6
bb
8
aa
14
dd
19
127.0.0.1:6379>

2.分值不同优先按分值排序,分值相同的成员,按字典(二进制)排序(lex结尾的命令需要用到这个知识点)

有序集合里面的成员是不能重复的都是唯一的,但是,不同成员间有可能有相同的分数。当多个成员有相同的分数时,他们将是有序的字典(ordered lexicographically)(仍由分数作为第一排序条件,然后,相同分数的成员按照字典规则相对排序)。

字典顺序排序用的是二进制,它比较的是字符串的字节数组。

如果用户将所有元素设置相同分数(例如0),有序集合里面的所有元素将按照字典顺序进行排序,范围查询元素可以使用zrangebylex命令(注:范围查询分数可以使用zrangebyscore命令)。

3.zadd或zincrby命令更新分值

分数可以通过zadd命令进行更新或者也可以通过zincrby命令来修改之前的值,相应的他们的排序位置也会随着分数变化而改变。
注:当用zadd添加一个已存在元素时,默认会更新该元素的分值(因为zset中不允许存在重复元素)。
所以,zadd添加一个重复元素时,相当于zincrby修改元素的分值。

127.0.0.1:6379> flushall
OK
127.0.0.1:6379> zadd str 100 aa 100 bb 100 cc 添加元素
3
127.0.0.1:6379> zrange str 0 -1 withscores  查看元素列表
aa
100
bb
100
cc
100
127.0.0.1:6379> zadd str 99 aa  添加元素aa,会自动覆盖原有的aa
0
127.0.0.1:6379> zscore str aa  查看aa的分值,已经由原来的100被后面的99覆盖了
99
127.0.0.1:6379> zrange str 0 -1 withscores
aa
99
bb
100
cc
100
127.0.0.1:6379> zincrby str 10 aa 给aa的分值增加10
109
127.0.0.1:6379> zscore str aa  查看aa的分值,已增加10
109
127.0.0.1:6379>

 4.zscore获取成员分值/验证成员是否存在

获取一个成员当前的分数可以使用ZSCORE命令,也可以用它来验证成员是否存在。

127.0.0.1:6379> zscore k1 aa 查分值
55
127.0.0.1:6379> zscore k1 xx 没有给出分值,则说明元素不存在

5.命令以lex结尾的命令,主要就是处理分值相同的元素集合

操作这样的命令,需要用 [ 或 ( 后面紧跟元素,来代表元素的起止位置,来进行操作。
注:[代表包含后面紧跟的元素; (代表不包含后面紧跟的元素。中括号和小括号后紧跟的元素之间不能有空格。

127.0.0.1:6379> zadd num 100 aa  100 cc 100 bb 100 ff 100 ee 100 gg
6
127.0.0.1:6379> zrangebylex num [bb [ee  从元素bb开始取元素,直到ee的位置(包含起止位置)
bb
cc
ee

6.rev和rem开头的命令,分别表示从高到低排列和移除元素

sort_set 是一个有序的无重复元素的集合,默认是分值,从低到高排序。

rev开头的命令,都表示该命令下的元素列表都是按从高到底排序的(和默认排序相反)。
rem开头的命令,都表示移除remove的意思,可以按rank下标索引移除,也可以按score分值移除,还可以按lex字典区间(中括号和小括号)移除。

zrevrank 、zrevrange、zrevrangebyscore、zrevrangebylex、

zremrangebyrank、zremrangebylex、zremrangebyscore、

7.关于weights权重的用法

127.0.0.1:6379>zinterstore inkey 2 k1 k2 weights 1 0.5 指定权重后,取交集

指定权重后,在计算时根据权重后的分值进行并集、交集或其他操作。 

8.关于timeout 阻塞的时间单位都是秒,0代表一直阻塞

127.0.0.1:6379> zadd num 11 aa 33 bb 88 cc 99 ee 4 127.0.0.1:6379> bzpopmax num 0  每次删除并弹出最大元素,元素不存在时,一直等待,知道超时或者消费到需要的元素 num ee 99

四、尾言

看到这里,相信你对zrangebylex 的作用和用法,已经有了深入的了解。
关于sorted的命令还有很多,主要挑拣难点说,因实验数据的局限性,与实际运用场景可能存在偏差,希望能起到抛砖引玉的作用,与爱学习的你共勉!

RedisGeoCommands 最近距离 redis zrangebyscore_数据库