I have a problem with getting data from Redis. I want to get the object using not Id column. Can I do this in Redis? Or another case when I want to get the object using Id column, but I want to have my name of this column, not just 'Id', but I have the problem with this too.
Redis is primarily a Name/Value store.
You can set the NAME to anything you want. If you want to call it 'Id' you can. If you want to call it 'x-y-z' you can too and store the VALUE along with it.
Redis also supports Hashes. If you want to get an object "using not Id column" you can store similar object types in a Hash and retrieve the entire HashSet then find the object inside the list on the client side. This is not efficient if storing large objects or if you have many objects in a list.
Ex:
HMSET user:1000 username antirez password P1pp0 age 34
HGETALL user:1000
HSET user:1000 password 12345
HGETALL user:1000
Here is a list of datatypes Redis Supports.
https://redis.io/topics/data-types
The 2 popular libraries for using C# and Redis are:
https://github.com/ServiceStack/ServiceStack.Redis
https://github.com/StackExchange/StackExchange.Redis
Related
I have many different keys. some start with "user USERNAME" and many others.
is there a way to get a random key from the "user *" ?
if so, how can i get like 5 different users?
If you put all the usernames into a Redis set, then you could use the SRANDMEMBER command to randomly gets usernames from the set. Example from the documentation:
redis> SADD myset one two three
(integer) 3
redis> SRANDMEMBER myset
"three"
redis> SRANDMEMBER myset 2
1) "three"
2) "two"
The set seems to be the only Redis data type that can return random elements from the collection. You might have to process your data a little differently to do this.
You can definitely use a Set and store all your "user*" key names in it, as suggested by #Sunil D.
Alternatively, you could use a dedicated Redis database for your "user*" keys and then use the RANDOMKEY command to fetch keys from it. The nice thing about this is that you don't have to manage the Set of key names (i.e. add and remove to it whenever a key is created or deleted, respectively).
Note, however, that with both approaches, you'll have to check that the result you got wasn't returned earlier after each call to SRANDMEMBER or RANDOMKEY since both do not ensure that you'll get a different answer each time you invoke it.
On my current project I'm implementing autocompletion service on top of Redis, for it I use such approach (this article describes it more widely):
1) for storing dump of the data I have hash in which I put searchable objects as a values, for instance
HSET data 1 "{\"name\":\"Kill Bill\",\"year\":2003}"
HSET data 2 "{\"name\":\"King Kong\",\"year\":2005}"
2) for storing all possible sequences of input characters (that I generate in advance) which could be used in search I use sorted sets, like
ZADD search:index:k 0 1
ZADD search:index:ki 0 1
ZADD search:index:kil 0 1
ZADD search:index:kill 0 1
Where value stored in sorted set (in my example '1') is key for data from hash. So, for searching some data (for example where name started with 'ki') we need to make two steps:
data_keys = REDIS.zrevrange('search:index:ki', 0, -1)
matching_data = REDIS.hmget(data, *data_keys)
The issue I tried to solve - how automatically remove all data from sorted sets related to hash values when I removed it? In relational databases I can use cascade deletion for such cases, but how can I handle it in Redis?
Your design appears awkward to me, I'm unsure what you're actually trying to do with Redis and perhaps that could be the topic of another question.
That said, to address your question, Redis does offer a "cascading delete"-like behavior. Instead, if you're deleting hash "1", iterate the prefix and ZREM it from the relevant sorted sets.
Note: do not use a Lua script for this task, as it will generate key names (i.e. sorted sets by prefix) and that is against the recommendations (will not work on a cluster)
I am trying to write a query in Redis to get the first 2 field values of my hash key..
Basically, when I do HVALS hashname, I want to get the values of the first 2 fields added (the oldest 2). This is somewhat like getting the TOP 2 tuples in a SQL database.
Is this possible in redis?
No, this isn't possible. The order of fields and values in a Redis Hash is for all intents and purposes random (despite the empirical evidence obtained on from experimenting on smallish Hashes). For ordering elements, refer to Redis' Sorted Sets.
Update: to answer the question in the comment, IIUC it looks like you can solve it easily with just Strings. Because of Redis' nature, at any given moment there is either one user waiting for a specific match, or zero. You can SET matchmaking:blue username1:token if the key doesn't exist (i.e. zero users waiting for the match) and GET and DEL it if it exists. Be sure to use SET's "NX" subcommand, MULTI/EXEC and/or Lua to ensure the atomicity of these two logical operations.
From what I have experimented with, HVALS returns values for keys in the order you're looking for i.e. oldest key first. Now its up to you to only pick the first two values using the client program e.g. HSET myhmap name "abhi" , HSET myhmap email "test#test" , HSET myhmap planet "earth", HSET myhmap galaxy "andromeda". HVALS myhmap will return "abhi","test#test", "earth" , "andromeda"
I am trying to insert time based records with multiple fields on the values (with TTL enabled).
For the multiple fields the best way to do it via Redis is using HSET:
HSET user:32 name "johns" timecreated "3333311232" address "somewhere"
I also try to read those values via time range:
for example return all history records (for example user 32) which was inserted in the last day:
so the best for that would be storing via ZADD using scores(this time I am losing the hash-map structure for easy retrieval):
ZADD user:32 3333311232 "name=johns,timecreated=3333311232,address=somewhere"
On the top of the things I want to add TTL for each record
Any idea how I could optimize my design?
I could split into two but that will requires two queries when reading:
ZADD user:32 3333311232 "user:32:3333311232"
HMSET user:32:3333311232 name “johns” timecreated “3333311232” address="somewhere"
than to retrieve ill need:
//some range
ZRANGEBYSCORE user:32 3333311232 333331123
result: 1389772850
now to get all information: HGETALL user:32:1389772850
What do you think?
Thank you,
ray.
The two methods you describe are the two common approaches. If you store the entire object in the ZSET, you would typically store it as a JSON string. If you don't need "random" access to the object, that's a valid approach.
I usually go for the other approach; a ZSET combined with hashes. the two queries are not a big deal. You could even abstract it away with a Lua script; see EVAL.
Regarding the TTL, while you cannot expire individual ZSET values, you could expire the hash, and use keyspace notifications to listen for the expired event, and remove the corresponding value from the ZSET.
Let me know if you need some more specifics.
I have a redis table where values are stored like
key: "aa - 1" value {"price": "10"}
key: "aa - 2" value {"price": "8"}
key: "aa - 4" value {"price": "15"}
I am executing keys *aa* to get the list of keys. Is there a way to get this list ordered by the price as well?
thanks.
Redis is not very complex. It is for sure not document based, and doesn't have a json type.
From your comment I understand that you saved json within strings. There's no way to sort that.
Here is an overview of redis types: if you need sorting, you should decide for sorted sets, with price as score.
First of all this is not a table actually. You should consider your data as a set of objects which you can identify by key: you put your object with key1 and can get it back quickly using key. But your object is simply string or even byte[].
To store data in key-value storage many ways can be used. You can put whole object into the key and always get back whole object. No way to sort anything.
You may also to do some kind of vertical split on property level, and store each property or sub-object separately. Something like:
key: "aa - 1:price" value "10"
key: "aa - 1:name" value "CoolName"
Obvious drawback - it is hard to maintain in consistent way, you need many requests to get whole objects. Though GET "aa - 1:*" can be used as well
But as positive thing here, you may store different properties using different redis data structures.
For example you can store price using ZADD. Something like that:
ZADD pricesSet 10 "aa - 1"
ZADD pricesSet 4 "aa - 2"
Then you can use ZRANGEBYSCORE to take data from this key
ZRANGEBYSCORE priceSet 5 15
Means to get keys of all items with price from 5 to 15. You will get "aa - 1" and can then get it separately.
And YES, output of ZRANGEBYSCORE is sorted by price.