Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deleting multiple keys in redis-rb

Tags:

ruby

redis

Using redis-rb in a Rails app, the following doesn't work:

irb> keys = $redis.keys("autocomplete*")
=> ["autocomplete_foo", "autocomplete_bar", "autocomplete_bat"]
irb> $redis.del(keys)
=> 0

This works fine:

irb> $redis.del("autocomplete_foo", "autocomplete_bar")
=> 2

Am I missing something obvious? The source is just:

# Delete a key.
def del(*keys)
  synchronize do
    @client.call [:del, *keys]
  end
end

which looks to me like it should work to pass it an array...?

like image 923
shalott Avatar asked May 19 '11 16:05

shalott


People also ask

How do I delete multiple keys in Redis?

We can use keys command like below to delete all the keys which match the given patters “ user*" from the Redis. Note :- Not recommended on production Redis instance. I have written Lua script to delete multiple keys by pattern . Script uses the scan command to delete the Redis cache key in incremental iteration.

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.

Does Redis delete keys?

in redis you don't remove keys but keys remove themselves.


3 Answers

A little coding exploration of the way the splat operator works:

def foo(*keys)
  puts keys.inspect
end

>> foo("hi", "there")
["hi", "there"]

>> foo(["hi", "there"])
[["hi", "there"]]

>> foo(*["hi", "there"])
["hi", "there"]

So passing in a regular array will cause that array to be evaluated as a single item, so that you get an array inside an array within your method. If you preface the array with * when you call the method:

$redis.del(*keys)

That lets the method know to unpack it/not to accept any further arguments. So that should solve the problem that you're having!

Just for the sake of further clarification, this works:

>> foo("hello", *["hi", "there"])

This causes a syntax error:

>> foo("hello", *["hi", "there"], "world")
like image 94
Nancy Avatar answered Sep 21 '22 15:09

Nancy


For a Rails app I'm working on, I needed to test the results of loading and unloading redis data.

The namespace is determined by the environment, avoids interacting with development. This worked well.

def clear_redis_cache
  keys = $redis.keys "#{namespace}*"
  $redis.del(*keys) unless keys.empty?
end
like image 40
Mark Swardstrom Avatar answered Sep 21 '22 15:09

Mark Swardstrom


This is better achieved using the enumerator returned by scan_each.

scan_each(match: 'autocomplete_*').each do |key|
  del key
end

This does not load all of the matching keys into memory at once, so it will not be limited by local memory.

like image 32
Robin Daugherty Avatar answered Sep 22 '22 15:09

Robin Daugherty