I have multiple hash-keys organized in "folders" like MOC273,
127.0.0.1:6379> HMSET MOC273:123654789 "H_W" "json->H_W->123654789" "H_Y" "json->H_Y->123654789"
OK
127.0.0.1:6379> HMSET MOC273:987654321 "H_W" "json->H_W->987654321" "H_Y" "json->H_Y->987654321"
OK
With HGETALL I can get all the data from a hash
127.0.0.1:6379> HGETALL MOC273:123654789
1) "H_W"
2) "json->H_W->123654789"
3) "H_Y"
4) "json->H_Y->123654789"
How can I get all the hashes contained in MOC273(where the name starts with MOC273) Something like.
127.0.0.1:6379> HGETALL MOC273*
It's possible ?
Current structure of the redis
So you can use Redisearch to create a secondary index around the HASH data structure. This will allow you to search through HASH data more efficiently.
https://oss.redis.com/redisearch/ - Quick start should help you to get started
Related
I am new to Redis I tried to figure out this problem going through Redis documentation but no luck. Here are the details.
Lets say I inserted Strings like below.
Set category:1 "Men"
Set category:2 "Women"
Set category:3 "Kids"
Set category:4 "Home"
Set category:5 "shoes" ...
Now I want to get all the values by querying with keys which follow certain pattern in this case category:*.
Get category:*
Is there any way to get all categories like this?
Use SCAN. SCAN is the only safe way to iterate through the keys in a Redis database. SCAN will chunk out a portion of the keyspace and return a cursor (always the first result) and any values it found in that chunk. You start with a cursor of 0.
> SCAN 0 MATCH "category:*"
1) "1904"
2) (empty list or set)
Then you pass that cursor back into the SCAN command with the same pattern:
> SCAN 1904 MATCH "category:*"
1) "0"
2) 1) "category:3"
2) "category:2"
3) "category:4"
4) "category:1"
In this case the cursor returned is 0 which is the signal that the SCAN command has completed. The second response is an array with the keys found. Note that you need to run the SCAN command in a loop and none or only part of keys that match the pattern will be returned each time.
After you get the keys, you'll need to retrieve the values as normal (GET).
Just a note: From the look of how your data is structured, you're likely using an inappropriate data type: The categories would be better organized into a hash (e.g. HSET categories 1 men then you can use HGETALL)
I've been experimenting with Redis today. I've managed to store cached values from Drupal, but I'm looking to investigate a bit further and view the value stored in cache_my_custom_cache..
127.0.0.1:6379> keys *
1) "ff3169bd93659dc31322abc32835ef3e:cache_bootstrap:lookup_cache"
2) "ff3169bd93659dc31322abc32835ef3e:cache_bootstrap:module_implements"
3) "ff3169bd93659dc31322abc32835ef3e:cache_bootstrap:bootstrap_modules"
4) "ff3169bd93659dc31322abc32835ef3e:cache_bootstrap:system_list"
5) "ff3169bd93659dc31322abc32835ef3e:cache_bootstrap:variables"
6) "ff3169bd93659dc31322abc32835ef3e:path:a:und"
7) "myhash"
8) "ff3169bd93659dc31322abc32835ef3e:path:s:und"
9) "ff3169bd93659dc31322abc32835ef3e:cache_my_custom_cache:custom_cache_markup"
10) "ff3169bd93659dc31322abc32835ef3e:cache_bootstrap:hook_info"
127.0.0.1:6379> type ff3169bd93659dc31322abc32835ef3e:cache_my_custom_cache:custom_cache_markup
hash
this reveals it's of type hash.. But when I run:
127.0.0.1:6379> HGET ff3169bd93659dc31322abc32835ef3e:cache_qbe:qbe_markup
(error) ERR wrong number of arguments for 'hget' command
It doesn't like it! Completely new to this, can someone offer a solution?
Besides the key you will need to specify the field in the HGET command.
To get a list of all fields in the hash you can run this:
hkeys ff3169bd93659dc31322abc32835ef3e:cache_my_custom_cache:custom_cache_markup
Then you can do:
hget ff3169bd93659dc31322abc32835ef3e:cache_my_custom_cache:custom_cache_markup FIELD
You can also get all the values in the hash like this:
hvals ff3169bd93659dc31322abc32835ef3e:cache_my_custom_cache:custom_cache_markup
HGET expects an additional parameter after the key name that enumerates which field of your hash you would like returned. Something like this:
HGET my_hash_key my_hash_field
If you're trying to retrieve all fields of your hash at once, you should use HGETALL:
HGETALL my_hash_key
Documentation for HGET: here
Documentation for HGETALL: here
Discussion of Redis types (including hashes): here
I'm trying to implement the redis solution suggested here: http://www.slideshare.net/cacois/cois-palkostrata2013: it is the best I have found so far.
I have the following data structure "hash"
{'user': username, 'text': sometext, 'time': 1400543375}
I want to save the data in a log, the slides suggest saving it in a sorted list. When I try this:
zadd mysortedset 1400543375 {'user': username, 'text': sometext, 'time': 1400543375}
I get
Invalid argument(s)
so I thought I should create the hash first and then add it to the set
127.0.0.1:6379> HMSET setmember:1400543375 user username text sometext time 1400543375
OK
and then
127.0.0.1:6379> zadd mysortedset 1400543375 setmember:1400543375
(integer) 1
Is this the way it is supposed to be done?
What’s simply missing are the quotes around your JSON. Otherwithe it tries to interpret your zadd as scove value score value. And „username,“ is no valid score. ;) I tried it with
zadd mysortedset 1234 ”{’user’: foo …}”
and it works.
A log suggest you get the entries in the right order to begin with. In which case use the l* commands (lpush,lpop etc)
In Redis, to store an array of objects we should use hash for the object and add its key to a list:
HMSET concept:unique_id name "concept"
...
LPUSH concepts concept:unique_id
...
I want to retrieve all hash values (or objects) in the list, but the list contains only hash keys so a two step command is necessary, right? This is how I'm doing in python:
def get_concepts():
list = r.lrange("concepts", 0, -1)
pipe = r.pipeline()
for key in list:
pipe.hgetall(key)
pipe.execute()
Is it necessary to iterate and fetch each individual item? Can it be more optimized?
You can use the SORT command to do this:
SORT concepts BY nosort GET concept:*->name GET concept:*->some_key
Where * will expand to each item in the list.
Add LIMIT offset count for pagination.
Note that you have to enumerate each field in the hash (each field you want to fetch).
Another option is to use the new (in redis 2.6) EVAL command to execute a Lua script in the redis server, which could do what you are suggesting, but server side.
I'm currently playing around with Redis and i've got a few questions. Is it possible to get values from an array of keys?
Example:
users:1:name "daniel"
users:1:age "24"
users:2:name "user2"
users:2:age "24"
events:1:attendees "users:1", "users:2"
When i redis.get events:1:attendees it returns "users:1", "users:2". I can loop through this list and get users:1, get users:2. But this feels wrong, is there a way to get all the attendees info on 1 get?!
In rails i would do something like this:
#event.attendees.each do |att|
att.name
end
But in redis i can't because it returns the keys and not the actual object stored at that key.
thanks :)
Doing a loop on the items and synchronously accessing each element is not very efficient. With Redis 2.4, there are various ways to do what you want:
by using the sort command
by using pipelining
by using variadic parameter commands
With Redis 2.6, you can also use Lua scripting, but this is not really required here.
By the way, the data structure you described could be improved by using hashes. Instead of storing user data in separate keys, you could group them in a hash object.
Using the sort command
You can use the Redis sort command to retrieve the data in one roundtrip.
redis> set users:1:name "daniel"
OK
redis> set users:1:age 24
OK
redis> set users:2:name "user2"
OK
redis> set users:2:age 24
OK
redis> sadd events:1:attendees users:1 users:2
(integer) 2
redis> sort events:1:attendees by nosort get *:name get *:age
1) "user2"
2) "24"
3) "daniel"
4) "24"
Using pipelining
The Ruby client support pipelining (i.e. the capability to send several queries to Redis and wait for several replies).
keys = $redis.smembers("events:1:attendees")
res = $redis.pipelined do
keys.each do |x|
$redis.mget(x+":name",x+":age")
end
end
The above code will retrieve the data in two roundtrips only.
Using variadic parameter command
The MGET command can be used to retrieve several data in one shot:
redis> smembers events:1:attendees
1) "users:2"
2) "users:1"
redis> mget users:1:name users:1:age users:2:name users:2:age
1) "daniel"
2) "24"
3) "user2"
4) "24"
The cost here is also two roundtrips. This works if you can guarantee that the number of keys to retrieve is limited. If not, pipelining is a much better solution.
You can use Redis' EVAL command to send it a Lua script that runs a loop "server side" and return the results in a block.