ZRANGEBYLEX && ZLEXCOUNT
这两个放在一起,是因为涉及到这个
LEX
,也就是lexicographical。这个主要是用于统计或者查询有序集合内,分数相同
的一些成员。这个分数相同
很重要。因为分数如果不同,ZRANGEBYLEX或者ZLEXCOUNT命令不会返回想要的结果。
在使用时,
-
表示不限制start,+
表示不限制end,[
表示包含,(
表示不包含
先说ZRANGEBYLEX
1. 当分数相同时
Command
- 先创建一个有序集合
127.0.0.1:6379> zadd s1 0 Tom 0 Lily 0 Jesse 0 Paul
(integer) 4
- 查询整个区间的成员,可以看到是按字母顺序排列的
127.0.0.1:6379> ZRANGEBYLEX s1 - +
1) "Jesse"
2) "Lily"
3) "Paul"
4) "Tom"
- 查询到P之前的成员,可以看到Paul没被返回,因为Pa在P之后,这个容易理解
127.0.0.1:6379> ZRANGEBYLEX s1 - [P
1) "Jesse"
2) "Lily"
- 查询到Paul(含)之前的成员
127.0.0.1:6379> ZRANGEBYLEX s1 - [Paul
1) "Jesse"
2) "Lily"
3) "Paul"
- 查询到paul(不含)之前的成员
127.0.0.1:6379> ZRANGEBYLEX s1 - (Paul
1) "Jesse"
2) "Lily"
- 查询P之后的成员,可以看到Paul被返回,因为Pa在P之后
127.0.0.1:6379> ZRANGEBYLEX s1 [P +
1) "Paul"
2) "Tom"
- 查询Paul(不含)之后的成员
127.0.0.1:6379> ZRANGEBYLEX s1 (Paul +
1) "Tom"
- 查询a(含)之前的成员
这个没懂,留个TODO:为什么字典里的顺序,小写字母排在大写字母后面
127.0.0.1:6379> ZRANGEBYLEX s1 - [a
1) "Jesse"
2) "Lily"
3) "Paul"
4) "Tom"
- LIMIT option
ZRANGEBYLEX s1 - + [LIMIT offset count]
offset表示从前面
ZRANGEBYLEX s1 - +
获得的结果中的什么位置开始,count表示从offset开始取几个
127.0.0.1:6379> ZRANGEBYLEX s1 - + LIMIT 0 2
1) "Jesse"
2) "Lily"
Code
代码也是非常简单,为了节省篇幅,这里就不处理错误了。
func zrangebylex(c redis.Conn) {
defer c.Do("DEL", "s1")
c.Do("ZADD", "s1", 0, "Tom", 0, "Lily", 0, "Jesse", 0, "Paul")
// 1. Query all the members
memberList, _ := redis.Strings(c.Do("ZRANGEBYLEX", "s1", "-", "+"))
for i, m := range memberList {
fmt.Println("Member", i, "is:", m)
}
fmt.Println("------------------")
// 2. Query members before P. Will not return "Paul", because "Paul" is after "P".
memberList, _ = redis.Strings(c.Do("ZRANGEBYLEX", "s1", "-", "[P"))
for i, m := range memberList {
fmt.Println("Member", i, "is:", m)
}
fmt.Println("------------------")
// 3. Query members before "Paul"(included).
memberList, _ = redis.Strings(c.Do("ZRANGEBYLEX", "s1", "-", "[Paul"))
for i, m := range memberList {
fmt.Println("Member", i, "is:", m)
}
fmt.Println("------------------")
// 4. Query members before "Paul"(Not included).
memberList, _ = redis.Strings(c.Do("ZRANGEBYLEX", "s1", "-", "(Paul"))
for i, m := range memberList {
fmt.Println("Member", i, "is:", m)
}
fmt.Println("------------------")
// 5. Query members after "P". Result will include "Paul", because "Paul" is after "P".
memberList, _ = redis.Strings(c.Do("ZRANGEBYLEX", "s1", "[P", "+"))
for i, m := range memberList {
fmt.Println("Member", i, "is:", m)
}
fmt.Println("------------------")
// 6. Query members after "Paul"(Not included).
memberList, _ = redis.Strings(c.Do("ZRANGEBYLEX", "s1", "(Paul", "+"))
for i, m := range memberList {
fmt.Println("Member", i, "is:", m)
}
fmt.Println("------------------")
// 7. Query members before "a".
memberList, _ = redis.Strings(c.Do("ZRANGEBYLEX", "s1", "-", "[a"))
for i, m := range memberList {
fmt.Println("Member", i, "is:", m)
}
fmt.Println("------------------")
// 8. Use LIMIT option to limit results.
memberList, _ = redis.Strings(c.Do("ZRANGEBYLEX", "s1", "-", "+", "LIMIT", 0, 2))
for i, m := range memberList {
fmt.Println("Member", i, "is:", m)
}
}
Output
$ go run main.go
Member 0 is: Jesse
Member 1 is: Lily
Member 2 is: Paul
Member 3 is: Tom
------------------
Member 0 is: Jesse
Member 1 is: Lily
------------------
Member 0 is: Jesse
Member 1 is: Lily
Member 2 is: Paul
------------------
Member 0 is: Jesse
Member 1 is: Lily
------------------
Member 0 is: Paul
Member 1 is: Tom
------------------
Member 0 is: Tom
------------------
Member 0 is: Jesse
Member 1 is: Lily
Member 2 is: Paul
Member 3 is: Tom
------------------
Member 0 is: Jesse
Member 1 is: Lily
2. 当分数不同时
Command
$ redis-cli.exe -h 127.0.0.1 -p 6379
127.0.0.1:6379> del s1
(integer) 1
127.0.0.1:6379> zadd s1 7 Tom 2 Lily 6 Jesse 4 Paul
(integer) 4
127.0.0.1:6379> ZRANGEBYLEX s1 - +
1) "Lily"
2) "Paul"
3) "Jesse"
4) "Tom"
很明显能看到不是想要的按lexicographical
排序了。
再说ZLEXCOUNT
127.0.0.1:6379> del s1
(integer) 1
127.0.0.1:6379> zadd s1 0 Tom 0 Lily 0 Jesse 0 Paul
(integer) 4
// 对照ZRANGEBYLEX来看就清晰了,ZRANGEBYLEX获取到多少元素,那么ZLEXCOUNT使用相同的条件就返回对应元素的个数
127.0.0.1:6379> ZRANGEBYLEX s1 - [P
1) "Jesse"
2) "Lily"
127.0.0.1:6379> ZLEXCOUNT s1 - [P
(integer) 2
Code
func zlexcount(c redis.Conn) {
defer c.Do("DEL", "s1")
c.Do("ZADD", "s1", 0, "Tom", 0, "Lily", 0, "Jesse", 0, "Paul")
// Use ZRANGEBYLEX to query at first
memberList, _ := redis.Strings(c.Do("ZRANGEBYLEX", "s1", "-", "[P"))
for i, m := range memberList {
fmt.Println("Member", i, "is:", m)
}
fmt.Println("Number of members is:", len(memberList))
// If the query condition is the same, the result of ZLEXCOUNT will be same with len(memberList).
memberCount, _ := redis.Int(c.Do("ZLEXCOUNT", "s1", "-", "[P"))
fmt.Println("Number of members is:", memberCount)
}
Output
$ go run main.go
Member 0 is: Jesse
Member 1 is: Lily
Number of members is: 2
Number of members is: 2