1

How do you search for keys with a value in Ruby? For example get all KEYS where the value is "somevalue".

My keys are

"xyz" => {:status=> "connected", :topic=> "ABC"}

"PQR" => {:status=> "connected", :topic=> "ABC"}

Now I need to find all the KEYS where topic is "ABC"

Shrikanth Hathwar
  • 1,140
  • 4
  • 14
  • 25

2 Answers2

6

Regardless the programming language, to do this efficiently you'll need to maintain an "index" key that maps somevalue to the key names. Using a Set or a Sorted Set for this is what you should usually do - i.e. add new key names to it and remove them according to their values - and get that key's contents when you want to "search".

There are some libraries (i.e. gems) that may provide this sort of functionality ready to use - look into the most excellent Ohm in your case.

EDIT

My keys are xyz => {:status=> "connected", :topic=> "ABC"} PQR => {:status=> "connected", :topic=> "ABC"} Now I need to find all the KEYS where topic is "ABC"

I would store xyz's value as a String or a Hash (depending on whether I need to update/read just parts of it or not). Then I would SADD topic:ABC xyz and do SMEMBERS or SSCAN on it to get the names of all keys with that topic. I'd also try to remember to SREM the relevant member from topic:ABC when I DEL its key...

Itamar Haber
  • 47,336
  • 7
  • 91
  • 117
  • My keys are xyz => {:status=> "connected", :topic=> "ABC"} PQR => {:status=> "connected", :topic=> "ABC"} Now I need to find all the KEYS where topic is "ABC" – Shrikanth Hathwar Aug 21 '15 at 10:40
  • Hi I am doing mapped_hmset "xyz", { status: "connected",topic: "ABC" } . Now how to move forward. I guess if I do smembers it will give me all the values in "XYZ". How can search with "ABC" – Shrikanth Hathwar Aug 21 '15 at 11:05
  • Sure, if that's what you need. Follow that with the `SADD` and wrap it with a `MULTI/EXE` block for atomicity. – Itamar Haber Aug 21 '15 at 11:07
  • I think if I do SMEMBERS it will print all the values in that particular key not searching – Shrikanth Hathwar Aug 21 '15 at 11:19
  • `SMEMBER topic:ABC` will return all key names who have :topic=>"ABC" if you took care of that as explained. The order of key names shouldn't matter unless I grossly misunderstood your question. – Itamar Haber Aug 21 '15 at 12:05
1

Depends on which version of redis you can use getkeys on redis >= 2.8.13 or you could use keys command taking care some performance issues (if you have few keys should not be a problem but if you have a large amount of keys take care with that, because keys command will block redis for a few moment in order to get all keys)

If you are running redis 2.8 you'll be able to use scan command instead keys.

EDIT: A recently added page in Redis' documentation provides more information about Secondary indexing with Redis and covers this case under the Non range indexes section. Additional topics in it include:

Itamar Haber
  • 47,336
  • 7
  • 91
  • 117
Horacio
  • 2,865
  • 1
  • 14
  • 24
  • I disagree - `COMMAND GETKEYS` isn't related to this at all, please RTFM. `KEYS` is not a command you want to use... ever (forget blocking, that's child's play, OOM is what you should fear). Regardless, both `KEYS` and `SCAN` take time and resources so they're a poor choice if you want a quick response. – Itamar Haber Aug 21 '15 at 11:03
  • I agree on that, and I said that using keys command is not a good thing to do on production and is not a safe solucion. But is part of the redis solution and commands that you could use if you need to (for example if you are debugging on development or reading from a slave node or whatever you want). – Horacio Aug 21 '15 at 11:07
  • If you're a dev or an admin you can also do `rm -rf /` :) `SCAN` isn't as bad as `KEYS`, but it still requires O(N) to traverse the keyspace (not to mention sending back the key names and then doing a read on each for the value...). As a debugging/ad-hoc approach, sure, whatever. As an approach to solve an application requirement - never! (BTW, see Redis Commandment VI: https://gist.github.com/itamarhaber/d125cec7ebc5ec3886ab) – Itamar Haber Aug 21 '15 at 11:14
  • 1
    Haha!! nice gist!!! I agree on that, but If I were you, I would never do rm -fr / , is not a good practice ;) – Horacio Aug 21 '15 at 11:17