Удаление нескольких ключей в redis-rb
Используя redis-rb в приложении Rails, следующее не работает:
irb> keys = $redis.keys("autocomplete*")
=> ["autocomplete_foo", "autocomplete_bar", "autocomplete_bat"]
irb> $redis.del(keys)
=> 0
Это отлично работает:
irb> $redis.del("autocomplete_foo", "autocomplete_bar")
=> 2
Я пропустил что-то очевидное? Источник:
# Delete a key.
def del(*keys)
synchronize do
@client.call [:del, *keys]
end
end
который выглядит так, как будто он должен работать, чтобы передать массив...?
Ответы
Ответ 1
Небольшое кодирование того, как работает оператор splat:
def foo(*keys)
puts keys.inspect
end
>> foo("hi", "there")
["hi", "there"]
>> foo(["hi", "there"])
[["hi", "there"]]
>> foo(*["hi", "there"])
["hi", "there"]
Таким образом, передача в регулярном массиве приведет к тому, что этот массив будет оцениваться как один элемент, так что вы получите массив внутри массива внутри вашего метода. Если вы предируете массив с * при вызове метода:
$redis.del(*keys)
Это позволяет методу знать, чтобы распаковать его/не принимать никаких дополнительных аргументов. Таким образом, это должно решить проблему, которая у вас есть!
Только для дальнейших разъяснений это работает:
>> foo("hello", *["hi", "there"])
Это вызывает синтаксическую ошибку:
>> foo("hello", *["hi", "there"], "world")
Ответ 2
Для приложения Rails, над которым я работаю, мне нужно было проверить результаты загрузки и выгрузки данных redis.
Пространство имен определяется средой, избегает взаимодействия с разработкой. Это хорошо работает.
def clear_redis_cache
keys = $redis.keys "#{namespace}*"
$redis.del(*keys) unless keys.empty?
end
Ответ 3
Это лучше достигается с помощью перечислителя, возвращаемого scan_each
.
scan_each(match: 'autocomplete_*').each do |key|
del key
end
Это не загружает все соответствующие ключи в память одновременно, поэтому оно не будет связано с памятью.