42

I'm using hash keys to store user details like:

 hmset user:1 user_name lee  age 21
 hmset user:2 user_name david  age 25
 hmset user:3 user_name chris  age 25

I need to search for users having age = 25, name = lee. How to do a search for a specified value in a given field?

Khaled
  • 1,114
  • 14
  • 31
Heera
  • 495
  • 1
  • 4
  • 6
  • 1
    A recently added page in Redis' documentation provides more information about [Secondary indexing with Redis](http://redis.io/topics/indexes) and covers this case under the [Non range indexes](http://redis.io/topics/indexes#non-range-indexes) section. – Itamar Haber Mar 04 '16 at 14:51

3 Answers3

71

You cannot. Redis is a key-value store, not a relational database.

In order to search for a specific data, you need to build an access path to this data. For instance, to get the users having age = 25, you need to build an index to map the age values to users. It can be done with a set. This is the same for the name.

Once you have sets for age and name, you can search users by intersecting the sets. For example:

# Add 3 users
hmset user:1 user_name lee age 21
hmset user:2 user_name david age 25
hmset user:3 user_name chris age 25

# Maintain age index
sadd age:21 1
sadd age:25 2 3

# Maintain name index
sadd name:lee 1
sadd name:david 2
sadd name:chris 3

# Get the ID of users having age = 25 and name = lee
sinter age:25 name:lee
  -> will return an empty set
admdrew
  • 3,790
  • 4
  • 27
  • 39
Didier Spezia
  • 70,911
  • 12
  • 189
  • 154
  • I'm facing same design problem, but my question is after the command "sinter age:25 name:lee", the result should be list of id. So I need to query second time to get the real user data. Is this the only way to do? – Ray Shih Oct 04 '13 at 01:52
  • 5
    If you want to perform a single roundtrip, a server-side Lua script will do what you want (i.e. sinter, and then one hgetall per selected item). – Didier Spezia Oct 04 '13 at 07:08
  • It doesn't makes sense to maintain the HASH itself coz you're already storing the reverse index for all the HASH fields. – droidlabour Jan 25 '15 at 17:43
  • So really the only advantage of using hashes in Redis rather than just saving marshalled objects (like JSON) as strings is that you can fetch single fields? – Hubro Mar 25 '18 at 17:15
  • Now you can! This answer only applies to early versions of Redis. – FredTheWebGuy Mar 04 '23 at 03:39
8

Acually You can do it with put values in key

HMSET lee:25 user_name lee age 25
HMSET massi:43 user_name massi age 43
HMSET lee:24 user_name lee age 24
HMSET lee:28 user_name lee age 28 city Berlin

Now you can find them with "keys" command

127.0.0.1:6379> keys *:25
1) "lee:25"
127.0.0.1:6379> keys lee*
1) "lee:25"
2) "lee:24"
3) "lee:28"
127.0.0.1:6379> keys massi:43
1) "massi:43"

Finally find specific hashes

127.0.0.1:6379> HGETALL lee:24
1) "user_name"
2) "lee"
3) "age"
4) "24"

All that I said is that you can do it in two steps put any number of values that you need in key then find them. But consider that it's not a good idea to put all values inside key Just put ones that you need to do filtering with. Cheers :)

Ario
  • 1,822
  • 1
  • 21
  • 31
  • 12
    While this may work, I really would recommend against this for building anything serious. In the Redis docs, there's a specific warning against using the KEYS command in a production environment as it can degrade performance in a large database: https://redis.io/commands/keys. – xiy Aug 13 '17 at 22:49
0

SCAN is the recommended way to search keys in Redis v6.0 and later.

 127.0.0.1:6379>  SCAN 0 TYPE hash COUNT 1000000

COUNT needs to be passed as last parameter, otherwise there will be a limit of 10 records returned by default.

FredTheWebGuy
  • 2,546
  • 3
  • 27
  • 34