I have been reading around that I cannot have nested data structures in redis, and the only way to include it is to create a reference to it.
If I understand correct, a way to create a generic struct in redis would be:
hmset ARandomStringAsAKey name kostas address milky_way
I tried to store the hash in that way:
hmset ReferenceTest name kostas ref ARandomStringAsAKey
and then tried to get it back via:
hget ReferenceTest ref
but the only thing I got was a string saying ARandomKeyAsAString .
How could I possibly do that?
Thanks in advance!
You can't get what you want via hget ReferenceTest ref.
You shoud:
get the key via hget ReferenceTest ref
get the real data by the value it returns(ARandomKeyAsAString )
127.0.0.1:6379> hmget ReferenceTest ref
1) "ARandomStringAsAKey"
127.0.0.1:6379> hgetall ARandomStringAsAKey
1) "name"
2) "kostas"
3) "address"
4) "milky_way"
BTW: We don't store data like that, we transfer name kostas address milky_way into a json string, and store it.
127.0.0.1:6379> hmset ReferenceTest name kostas data "{\"name\":\"kostas\",\"address\": \"milky_way\"}"
OK
127.0.0.1:6379> hget ReferenceTest data
"{\"name\":\"kostas\",\"address\": \"milky_way\"}"
127.0.0.1:6379>
Related
I'm using the modules RedisJSON and RediSearch together to perform search queries on JSON data.
For every JSON object, I need to index all the string elements in an array field to be able to get this object by querying one of the strings in the array (i.e. get some book data by searching for one of the authors contained in a string array in the book JSON).
However, it seems to be currently not possible.
Is there any possible workaround or am I stuck?
You need to try the latest version of RediSearch+RedisJSON.
The example from the github issue you are referring to is working for me with RedisJSON 2.0.5 and RediSearch 2.2.5
127.0.0.1:6379> ft.create index on json schema $.names[0:].first as first tag
OK
127.0.0.1:6379> json.set pserson:1 $ '{"names":[{"first": "fname1","last": "lname1"},{"first": "fname2","last": "lname2"},{"first": "fname3", "last": "lname3"}]}'
OK
127.0.0.1:6379> ft.search index #first:{fname1}
1) (integer) 1
2) "pserson:1"
3) 1) "$"
2) "{\"names\":[{\"first\":\"fname1\",\"last\":\"lname1\"},{\"first\":\"fname2\",\"last\":\"lname2\"},{\"first\":\"fname3\",\"last\":\"lname3\"}]}"
127.0.0.1:6379> ft.search index #first:{fname2}
1) (integer) 1
2) "pserson:1"
3) 1) "$"
2) "{\"names\":[{\"first\":\"fname1\",\"last\":\"lname1\"},{\"first\":\"fname2\",\"last\":\"lname2\"},{\"first\":\"fname3\",\"last\":\"lname3\"}]}"
Here is the specific redis-cli info modules:
module:name=ReJSON,ver=20005,api=1,filters=0,usedby=[search],using=[],options=[handle-io-errors]
module:name=search,ver=20205,api=1,filters=0,usedby=[],using=[ReJSON],options=[handle-io-errors]
In the documentation is said that you can use hash to store objects or any kind of data, and later you can extract them. I want to save, for instance, ids from a few users by using hash, and later extract all the ids, or all the elements with ids (something, I didnt accomplish nothing similar), can you help me?
redis 127.0.0.1:6379> set user:id:1234 "content of my first user"
OK
redis 127.0.0.1:6379> set user:id:1235 "content of my second user"
OK
redis 127.0.0.1:6379> set user:id:1236 "content of my third user"
OK
redis 127.0.0.1:6379> get user:id
(nil) ####I hoped to see all my id's users listed, I want to make
something like that,in the documentation I saw an example, but
is not completed####
Those are plain top-level key sets. To make a hash, you should use HSET
hset user:id 1234 "content of my first user"
hset user:id 1235 "content of my second user"
hgetall user:id
Is there any quick command in REDIS which allows me to do the following
I want to set the Value of key Y equal to the value of Key X .
How do I go about doing this from the Redis Client .
I use the standard Redis-cli client .
Basically I am looking for some equivalent of the following -
Y.Val() = X.Val()
You can do this with a Lua script:
redis.call('SET', KEYS[2], redis.call('GET', KEYS[1])); return 1;
KEYS1 is the source key
KEYS2 is the target key
The example below uses SCRIPT LOAD to create the script and invokes it using EVALSHA passing the following arguments:
The SHA1 returned from the script load
a 2 for the number of keys that will be passed
The source key
The target key.
Output:
redis 127.0.0.1:6379> set src.key XXX
OK
redis 127.0.0.1:6379> get src.key
"XXX"
redis 127.0.0.1:6379> SCRIPT LOAD "redis.call('SET', KEYS[2], redis.call('GET', KEYS[1])); return 1;"
"1119c244463dce1ac3a19cdd4fda744e15e02cab"
redis 127.0.0.1:6379> EVALSHA 1119c244463dce1ac3a19cdd4fda744e15e02cab 2 src.key target.key
(integer) 1
redis 127.0.0.1:6379> get target.key
"XXX"
It does appear to be a lot of stuff compared to simply doing a GET and then s SET, but once you've loaded the script (and memorized the SHA1) then you can reuse it repeatedly.
If you dont want script loading then below will work as a single command.
127.0.0.1:6379> eval "return redis.call('SET', KEYS[2], redis.call('GET', KEYS[1]))" 2 key1 key2
OK
Note that key1 value should be already set else you will get the below error
Lua redis() command arguments must be strings or integers
So check like below and set
127.0.0.1:6379> GET key1
(nil)
127.0.0.1:6379> SET key1 hello
OK
Now it will work.
If you want copy map to another new map key
eval "return redis.call('HMSET', KEYS[2], unpack(redis.call('HGETALL', KEYS[1])))" 2 existingMapKey newMapKey
One more way is while inserting time itself you can insert the value to two keys using MSET.
redis> MSET key1 "Hello" key2 "Hello"
"OK"
redis> GET key1
"Hello"
redis> GET key2
"Hello"
Ofcource this will not solve the issue of copying when the key is already created.
Also note that there is no way in redis more than one key is referring the same value object. All these workaround will create duplicate value objects. So if one of the value is updated will not reflect in another value object.
Since 6.2.0 you have a COPY command :
https://redis.io/commands/copy
No, there is no quick command to do this. You have to GET the value of the source key, and then SET the value of the new key.
Source: http://redis.io/commands#string
I would like to store some information as follows (note, I'm not wedded to this data structure at all, but this shows you the underlying information I want to store):
{ user_id: 12345, page_id: 2, country: 'DE' }
In these records, user_id is a unique field, but the page_id is not.
I would like to translate this into a Redis data structure, and I would like to be able to run efficient searches as follows:
For user_id 12345, find the related country.
For page_id 2, find all related user_ids and their countries.
Is it actually possible to do this in Redis? If so, what data structures should I use, and how should I avoid the possibility of duplicating records when I insert them?
It sounds like you need two key types: a HASH key to store your user's data, and a LIST for each page that contains a list of related users. Below is an example of how this could work.
Load Data:
> RPUSH page:2:users 12345
> HMSET user:12345 country DE key2 value2
Pull Data:
# All users for page 2
> LRANGE page:2:users 0 -1
# All users for page 2 and their countries
> SORT page:2:users By nosort GET # GET user:*->country GET user:*->key2
Remove User From Page:
> LREM page:2:users 0 12345
Repeat GETs in the SORT to retrieve additional values for the user.
I hope this helps, let me know if there's anything you'd like clarified or if you need further assistance. I also recommend reading the commands list and documentation available at the redis web site, especially concerning the SORT operation.
Since user_id is unique and so does country, keep them in a simple key-value pair. Quering for a user is O(1) in such a case... Then, keep some Redis sets, with key the page_id and members all the user_ids..
I know you can pass a key or a range to return records in CouchDB, but I want to do something like this. Find X records that are X values.
So for example, in regular SQL, lets say I wanted to return records with ids that are 5, 7, 29, 102. I would do something like this:
SELECT * FROM sometable WHERE id = 5 OR id = 7 or id = 29 or id = 102
Is it possible to do this in CouchDB, where I toss all the values I want to find in the key array, and then CouchDB searches for all of those records that could exist in the "key parameter"?
You can do a POST as documented on CouchDB wiki. You pass the list of keys in the body of the request.
{"keys": ["key1", "key2", ...]}
The downside is that a POST request is not cached by the browser.
Alternatively, you can obtain the same response using a GET with the keys parameter. For example, you can query the view _all_docs with:
/DB/_all_docs?keys=["ID1","ID2"]&include_docs=true
which, properly URL encoded, becomes:
/DB/_all_docs?keys=%5B%22ID1%22,%22ID2%22%5D&include_docs=true
this should give better cacheability, but keep in mind that _all_docs changes at each doc update. Sometimes, you can workaround this by defining your own view with only the needed documents.
With a straight view function, this will not be possible. However, you can use a _list function to accomplish the same result.