Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to get keys which does not match a particular pattern in redis?

Tags:

In Redis, keys user* will print all keys starting with user. For example:

keys user* 1) "user2" 2) "user1" 

Now, I want all keys that don't start with user to be printed. How could I do that?

like image 648
Karthikeyan Gopall Avatar asked Apr 29 '15 11:04

Karthikeyan Gopall


People also ask

How do I delete all keys matching a pattern in Redis?

Redis does not offer a way to bulk delete keys. You can however use redis-cli and a little bit of command line magic to bulk delete keys without blocking redis. This command will delete all keys matching users:* If you are in redis 4.0 or above, you can use the unlink command instead to delete keys in the background.

How do I get all Redis keys?

To list the keys in the Redis data store, use the KEYS command followed by a specific pattern. Redis will search the keys for all the keys matching the specified pattern. In our example, we can use an asterisk (*) to match all the keys in the data store to get all the keys.

Can Redis have duplicate keys?

You can use the DUMP and RESTORE commands to duplicate the key: use the DUMP command to serialize the value of a key. use the RESTORE command to restore the serialized value to another key.

Which command is used to obtain all the keys in a database?

The Redis KEYS command returns all the keys in the database that match a pattern (or all the keys in the key space). Similar commands for fetching all the fields stored in a hash is HGETALL and for all fetching the members of a SMEMBERS. The keys in Redis themselves are stored in a dictionary (aka a hash table).


2 Answers

IMPORTANT: always use SCAN instead of (the evil) KEYS
do not use <code>KEYS</code>

Redis' pattern matching is somewhat functionally limited (see the implementation of stringmatchlen in util.c) and does not provide that which you seek ATM. That said, consider the following possible routes:

  1. Extend stringmatchlen to match your requirements, possibly submitting it as a PR.
  2. Consider what you're trying to do - fetching a subset of keys is always going to be inefficient unless you index them, consider tracking the names of all non-user keys (i.e.g. in a Redis Set) instead.
  3. If you are really insistent on scanning the entire keyspace and match against negative patterns, one way to accomplish that is with a little bit of Lua magic.

Consider the following dataset and script:

127.0.0.1:6379> dbsize (integer) 0 127.0.0.1:6379> set user:1 1 OK 127.0.0.1:6379> set use:the:force luke OK 127.0.0.1:6379> set non:user a OK 

Lua (save this as scanregex.lua):

local re = ARGV[1] local nt = ARGV[2]  local cur = 0 local rep = {} local tmp  if not re then   re = ".*" end  repeat   tmp = redis.call("SCAN", cur, "MATCH", "*")   cur = tonumber(tmp[1])   if tmp[2] then     for k, v in pairs(tmp[2]) do       local fi = v:find(re)        if (fi and not nt) or (not fi and nt) then         rep[#rep+1] = v       end     end   end until cur == 0 return rep 

Output - first time regular matching, 2nd time the complement:

foo@bar:~$ redis-cli --eval scanregex.lua , "^user" 1) "user:1" foo@bar:~$ redis-cli --eval scanregex.lua , "^user" 1 1) "use:the:force" 2) "non:user" 
like image 144
Itamar Haber Avatar answered Oct 16 '22 23:10

Itamar Haber


@Karthikeyan Gopall you nailed it in your comment above and this saved me a bunch of time. Thanks!

Here's how you can use it in various combinations to get what you want:

redis.domain.com:6379[1]> set "hello" "foo" OK redis.domain.com:6379[1]> set "hillo" "bar" OK redis.domain.com:6379[1]> set "user" "baz" OK redis.domain.com:6379[1]> set "zillo" "bash" OK redis.domain.com:6379[1]> scan 0 1) "0" 2) 1) "zillo"    2) "hello"    3) "user"    4) "hillo" redis.domain.com:6379[1]> scan 0 match "[^u]*" 1) "0" 2) 1) "zillo"    2) "hello"    3) "hillo" redis.domain.com:6379[1]> scan 0 match "[^u^z]*" 1) "0" 2) 1) "hello"    2) "hillo" redis.domain.com:6379[1]> scan 0 match "h[^i]*" 1) "0" 2) 1) "hello" 
like image 33
systemjack Avatar answered Oct 16 '22 21:10

systemjack