Working an learning some Redis and I am running into an issue that I can’t figure out why it is not working.
It is my understanding from some posts and documentation I read that I can store data with similar keys like this
redis.set("fruit:1", "apple")
# OK
redis.set("fruit:2", "banana")
# OK
and it is my understanding I should be able to get all fruit like this
redis.get("fruit:*")
But I am missing something because this keep returning null and I cannot figure out what I need to do to return something like
=> apple, banana
I was able to figure out, using scan (suggested in answer below as well) how to return all matching fruit keys, but what I need is to search for all matching fruit keys, and then return the values for them.
@redis.scan_each(match: "fruit:*") do |fruit|
Rails.logger.debug('even run?')
fruits << fruit
end
=> fruit:1, fruit:2 # What I need though is apple, banana
What solved it (at least so far) is using mGet
@redis.scan_each(match: "fruit:*") do |fruit|
Rails.logger.debug('even run?')
fruits << @redis.mGet(fruit)
end
2
Answers
As far as I know, you can not do that (it would be cool to be possible).
Instead you have to run a scan
SCAN 0 MATCH "fruit:*" COUNT 500
where500
is number of keys to parse in the first iteration. So you have to run multiple iterations… until you reach the end of your key count.If you want to get all keys with a single iteration, first you need to know how many keys there are in your DB, so you can run a command to find the total amount of keys:
dbsize
which you can use instead of the500
value in my example.redis-cli dbsize
or
redis-cli INFO Keyspace | grep ^db0 | cut -f 1 -d "," | cut -f 2 -d"="
To return all values from all keys you can use MGET
https://redis.io/commands/mget
Maybe you can also take a deeper look at data structures
Maybe the solution above is not the correct one, in your case you can also use a set just to add your fruits in there.
https://redis.io/commands/sadd
SCAN can be a very expensive operation as it must traverse all the keys, even if you use a pattern. Because Redis is single-threaded, while that SCAN is happening, nothing else can happen and other requests are blocked. If you only have a few keys, this is fine. But if you have a lot of keys, this can cause serious performance issues.
What you need is an index that contains the keys of all of your fruits. You could use a Set to do this and whenever you add a fruit, you add the key to the Set:
Then, when you need all the fruits, you just get the members of the Set:
Then get the values of the fruits: