简体   繁体   中英

Redis lexicographical ordering doesn't work

I'm trying to create a basic autocomplete feature (I created those below manually to test it out first), but somehow I don't get the result I want after adding some keys.

I add every possible version of a word and keep the exact words with * to mark them (For example, if 10 keys are returned and 3 of them have asterisk, they'll be shown as suggestions), so I can query my hash database after that and get hash results.

There are a few duplicate entry attempts, but since it returns integer 0 for them, I presumed that they weren't added for the second time.

I use Redis 3.0.6

127.0.0.1:6379> zadd zset 0 b
(integer) 1
127.0.0.1:6379> zadd zset 0 ba
(integer) 1
127.0.0.1:6379> zadd zset 0 bar
(integer) 1
127.0.0.1:6379> zadd zset 0 bar*
(integer) 1
127.0.0.1:6379> zadd zset 0 f
(integer) 1
127.0.0.1:6379> zadd zset 0 fo
(integer) 1
127.0.0.1:6379> zadd zset 0 foo
(integer) 1
127.0.0.1:6379> zadd zset 0 foo*
(integer) 1
127.0.0.1:6379> zadd zset 0 foob
(integer) 1
127.0.0.1:6379> zadd zset 0 fooba
(integer) 1
127.0.0.1:6379> zadd zset 0 foobar
(integer) 1
127.0.0.1:6379> zadd zset 0 foobar*
(integer) 1

No problem so far. I want all words that start with fo

127.0.0.1:6379> zrank zset fo
(integer) 5

It gives five, so I increment by one (like shown here if I get it right) and query all keys.

127.0.0.1:6379> zrange zset 6 -1
1) "foo"
2) "foo*"
3) "foob"
4) "fooba"
5) "foobar"
6) "foobar*"

No problem, I get the desired result.

I keep adding keys.

127.0.0.1:6379> zadd zset 0 a
(integer) 1
127.0.0.1:6379> zadd zset 0 b
(integer) 0
127.0.0.1:6379> zadd zset 0 c
(integer) 1
127.0.0.1:6379> zadd zset 0 fi
(integer) 1
127.0.0.1:6379> zadd zset 0 fil
(integer) 1
127.0.0.1:6379> zadd zset 0 filli
(integer) 1
127.0.0.1:6379> zadd zset 0 fillib
(integer) 1
127.0.0.1:6379> zadd zset 0 fillibo
(integer) 1
127.0.0.1:6379> zadd zset 0 filliboy
(integer) 1
127.0.0.1:6379> zadd zset 0 filliboya
(integer) 1
127.0.0.1:6379> zrank zset fo
(integer) 14

I do another search.

127.0.0.1:6379> zrange zset 15 -1
1) "foo"
2) "foo*"
3) "foob"
4) "fooba"
5) "foobar"
6) "foobar*"

Ok again. I keep adding.

127.0.0.1:6379> zadd zset 0 d
(integer) 1
127.0.0.1:6379> zadd zset 0 e
(integer) 1
127.0.0.1:6379> zadd zset 0 x
(integer) 1
127.0.0.1:6379> zadd zset 0 y
(integer) 1
127.0.0.1:6379> zadd zset 0 z
(integer) 1
127.0.0.1:6379> zadd zset 0 filli*
(integer) 1
127.0.0.1:6379> zadd zset 0 filliboya*
(integer) 1

This is the part where things get interesting. I want to get all the words that start with filli , but I can't. Why?

127.0.0.1:6379> zrank zset filli
(integer) 11
127.0.0.1:6379> zrange zset 12 -1
 1) "filli*"
 2) "fillib"
 3) "fillibo"
 4) "filliboy"
 5) "filliboya"
 6) "filliboya*"
 7) "fo"
 8) "foo"
 9) "foo*"
10) "foob"
11) "fooba"
12) "foobar"
13) "foobar*"
14) "x"
15) "y"
16) "z"
127.0.0.1:6379>

The lexicographical ordering is working, but you're asking for the entire range from the member you've retrieved to the end (-1). Since Redis v2.8 you should be using the ZRANGEBYLEX command for that purpose. In your case, it should be as follows:

ZRANGEBYLEX zset [filli [filli\xff

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM