Rockwell Rice
Rockwell Rice

Reputation: 3002

How to return all values with matched key from Redis store

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

Upvotes: 0

Views: 2739

Answers (2)

Guy Royse
Guy Royse

Reputation: 4312

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:

> SET fruit:1 apple
> SADD fruit:index 1

Then, when you need all the fruits, you just get the members of the Set:

> SMEMBERS fruit:index
1) "1"
2) "2"

Then get the values of the fruits:

> GET fruit:1
> GET fruit:2

Upvotes: 1

Mike
Mike

Reputation: 219

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 where 500 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 the 500 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

Upvotes: 1

Related Questions