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.