What does it mean value "-1" of a Redis Key? - caching

Consider a simple Redis TTL command as follows:
127.0.0.1:6379> ttl cache/employee/jackson_ray/login
(integer) -1
127.0.0.1:6379>
What does the -1 value means ?

Related

Getting an intersection of two Redis sets in Laravel

I have a set looking like this (except that it has about 8000 items):
{"id":563244,"stock_id":693,"value":"9.17","span_minutes":1440,"symbol":"BCS"}
{"id":565527,"stock_id":10093,"value":"21.09","span_minutes":2880,"symbol":"GDXS"}
{"id":564311,"stock_id":4241,"value":"91.52","span_minutes":7200,"symbol":"NDAQ"}
{"id":565269,"stock_id":8883,"value":"127.60","span_minutes":5760,"symbol":"SAA"}
Now, what I want is to get entries with:
value between 20 and 100
span_minutes between 5000 and 8000
I can get these by first creating 2 new sorted sets and then using zrangebyscore to extract the entries I want:
ZADD values 9.17 '{"id":563244,"stock_id":693,"value":"9.17","symbol":"BCS"}'
ZADD values 21.09 {"id":565527,"stock_id":10093,"value":"21.09","span_minutes":2880,"symbol":"GDXS"}
ZADD values 91.52 {"id":564311,"stock_id":4241,"value":"91.52","span_minutes":7200,"symbol":"NDAQ"}
ZADD values 127.60 {"id":565269,"stock_id":8883,"value":"127.60","span_minutes":5760,"symbol":"SAA"}
ZADD spans 1440 '{"id":563244,"stock_id":693,"value":"9.17","symbol":"BCS"}'
ZADD spans 2880 {"id":565527,"stock_id":10093,"value":"21.09","span_minutes":2880,"symbol":"GDXS"}
ZADD spans 7200 {"id":564311,"stock_id":4241,"value":"91.52","span_minutes":7200,"symbol":"NDAQ"}
ZADD spans 5760 {"id":565269,"stock_id":8883,"value":"127.60","span_minutes":5760,"symbol":"SAA"}
Now, if I want to filter these sets to get the values I want, I can do this:
$value_range = Redis::zrangebyscore('values',20,100);
$span_range = Redis::zrangebyscore('spans',5000,8000);
These return, respectively:
1) {"id":565527,"stock_id":10093,"value":"21.09","span_minutes":2880,"symbol":"GDXS"}
2) {"id":564311,"stock_id":4241,"value":"91.52","span_minutes":7200,"symbol":"NDAQ"}
and
1) {"id":565269,"stock_id":8883,"value":"127.60","span_minutes":5760,"symbol":"SAA"}
2) {"id":564311,"stock_id":4241,"value":"91.52","span_minutes":7200,"symbol":"NDAQ"}
Now what I need is a way to combine these two sets. From what I can see in the Redis docs, I should be able to use zinterstore for this purpose, but I don't understand the syntax and whatever I try keeps either throwing an error or returning the integer 0. For example:
Redis::zinterstore('intersection', 2, $value_range, $span_range); returns an error.
$intereseciton = Redis::zinterstore(2, $value_range, $span_range); returns 0.
What I should be getting is:
1) {"id":564311,"stock_id":4241,"value":"91.52","span_minutes":7200,"symbol":"NDAQ"}
because it's the only element of the original set that matches both of my conditions.
Maybe I have the wrong syntax, or the wrong approach altogether. How do I effectively get an intersection of the two sorted sets?
As I mentioned in the comments, you need to do the intersection on the client side. Otherwise, you have to write a Lua script to do the job:
--inter.lua
local value_key = KEYS[1]
local span_key = KEYS[2]
local value_min = ARGV[1]
local value_max = ARGV[2]
local span_min = ARGV[3]
local span_max = ARGV[4]
local value_range = redis.call("zrangebyscore", value_key, value_min, value_max)
local span_range = redis.call("zrangebyscore", span_key, span_min, span_max)
-- do intersection
local value_set = {}
for _, item in ipairs(value_range) do
value_set[item] = true
end
local result = {}
for _, item in ipairs(span_range) do
if value_set[item] ~= nil then table.insert(result, item) end
end
return result
Run it like this: redis-cli --eval inter.lua values spans , 20 100 5000 8000

How to get index of value if exists?

I need to store strings and associate a unique integer to each one. The integer must be as short/small as possible . Is it possible to do that in Redis? Basically I need something like SADD but instead to return the number of elements in the set I need it to return the index of the element inserted(newly stored or existing).
Pseudo code:
// if mystring already exists in myset it returns its index
// otherwise stores it and returns its index.
index := storeOrReturnIndex(myset, mystring)
Would using a hashmap cover what you are looking for?
> HSET hashmap 0 "first string"
(integer) 1
> HSET hashmap 1 "second string"
(integer) 1
> HSET hashmap 2 "third string"
(integer) 1
> HGET hashmap 1
"second string"
> HLEN hashmap
3
You can store the last modified index in a key with:
> SET last_modified 1
Then retrieve it with:
> GET last_modified
You can use the Redis INCR command to atomically acquire a new, unique index.
Pattern: Counter
The counter pattern is the most obvious thing you can do with Redis atomic increment operations. The idea is simply send an INCR command to Redis every time an operation occurs. For instance in a web application we may want to know how many page views this user did every day of the year.
To do so the web application may simply increment a key every time the user performs a page view, creating the key name concatenating the User ID and a string representing the current date.
This simple pattern can be extended in many ways:
So use INCR to get the next unique, smallest index in an atomic way wherever you want to store a new item (URL). Then you can use HSET to store the index associated with your item, and HGET to get the associated index for an item.

Rails Redis Reset Counters to 0

I would like to reset the value of a REDIS counter to 0 in a Rails 4 app.
I use hincrby to increment counters
$redis.hincrby("user:likes", "key", 1)
I can't delete the key with hdel http://redis.io/commands/hdel because I need to get the key often.
GETSET is atomic and could do the job http://redis.io/commands/getset, as in the example
GETSET mycounter "0"
But since I use hashes I need to use HSET http://redis.io/commands/hset
$redis.hset("user:likes", "key", "0")
It's not specified if hset is atomic, anyone used hset to reset redis counters to 0? If it's not a good option to reset a counter to 0, any idea how to do it?
It is atomic, so if you run $redis.hset("user:likes", "key", "0"), it doesn't affect other fields inside the "user:likes" hash besides the field: "key"

How to sort a redis hash by values in keys

is there a good way in redis to get keys in a hash sorted by values? I've looked at the documentation and haven't found a straightforward way.
Also could someone please explain how sorting is achieved in redis, and what this documentation is trying to say?
I have a very simple hash structure which is something like this:
"salaries" - "employee_1" - "salary_amount"
I'd appreciate a detailed explanation.
You can achieve it by sorting a SET by one of your HASH fields. So you should create an indices SET of all of your hashes, and use the BY option.
Also, you can use DESC option to get the results sorted from high to low.
e.g.
localhost:6379> sadd indices h1 h2 h3 h4
(integer) 4
localhost:6379> hset h1 score 3
(integer) 1
localhost:6379> hset h2 score 2
(integer) 1
localhost:6379> hset h3 score 5
(integer) 1
localhost:6379> hset h4 score 1
(integer) 1
localhost:6379> sort indices by *->score
1) "h4"
2) "h2"
3) "h1"
4) "h3"
localhost:6379> sort indices by *->score desc
1) "h3"
2) "h1"
3) "h2"
4) "h4"
From SORT's documentation page:
Returns or stores the elements contained in the list, set or sorted set at key
So you can't really use it to sort the fields by their values in a Hash data structure. To achieve your goal you should either do the sorting in your application's code after getting the Hash's contents or use a Redis-embedded Lua script for that purpose.
Edit: After speaking with #OfirLuzon we realized that there is another, perhaps even preferable, approach which would be to use a more suitable data structure for this purpose. Instead of storing the salaries in a Hash, you should consider using a Sorted Set in which each member is an employee ID and the score is the relevant salary. This will give you ordering, ranges and paging for "free" :)

Empty/delete a set in Redis?

Maybe I'm just blind, but I don't see an explicit set command in Redis for emptying an existing set (without emptying the entire database). For the time being, I'm doing a set difference on the set with itself and storing it back into itself:
redis> SMEMBERS metasyn
1) "foo"
2) "bar"
redis> SDIFFSTORE metasyn metasyn metasyn
(integer) 0
redis> SMEMBERS metasyn
(empty list or set)
But that looks a little silly... is there a better way to do this?
You could delete the set altogether with DEL.
DEL metasyn
From redis console,
redis> SMEMBERS metasyn
1) "foo"
2) "bar"
redis> DEL metasyn
(integer) 1
redis> SMEMBERS metasyn
(empty list or set)

Resources