ZRANGEBYLEX && ZLEXCOUNT

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

你可能感兴趣的:(ZRANGEBYLEX && ZLEXCOUNT)