what is the max value of an offset in setbit - redis

I have tried to store bit using setbit in redis like
setbit mykey 123 1 and also use more than maximal int value 2147483647 + 100 as the offset value so it would be like this :
setbit mykey 2147483747 1 this one works.
And also I tried to add severals number until hit the 4547483747 and got
ERR bit offset is not an integer or out of range
my question is : what is the maximal exact value of the offset?

According to the documentation:
The offset argument is required to be greater than or equal to 0, and smaller than 2³²
So the maximum value is 4,294,967,295 (or 2³² - 1). Confirmation via the CLI:
127.0.0.1:6379> setbit mykey 4294967295 1
(integer) 1
127.0.0.1:6379> setbit mykey 4294967296 1
(error) ERR bit offset is not an integer or out of range

Related

Redis BITCOUNT behavior

How does redis bitcount command work?
setbit test 1 1
setbit test 3 1
count bits.
bitcount test
returns 2
Range count.
bitcount test 1 2
returns 0
Why? I thought I should get 1 for the bit position between 1 and 2, we have only one bit set.
The start and end arguments refer to bytes. So you're asking for the number of bits in the second and third bytes of the string. You've only set bits in the first byte, so the answer is 0.
It's unfortunate that the documentation for BITCOUNT doesn't explain that, but it is mentioned in the documentation for BITPOS:
It is possible to look for bits only in a specified interval passing the additional arguments start and end.... The range is interpreted as a range of bytes and not a range of bits, so start=0 and end=2 means to look at the first three bytes.

Reset value for key in redis

I am storing some values in redis like for key: 1 the value will be
{"counter":1,"counter1":2}
Now I need to reset value of counter while the counter1 should be remaining same.
To increase counter I am use the command SETEX mykey 60 redis .
But it will also reset the value of counter1. So is there any way I can reset one value for a single key.
Let me know if I need to add some more info.
Instead of string you may use hash, then it will be easy. you can increment by some other value, delete counter etc etc. Each key in your json will be hash field.
127.0.0.1:6379> hset mykey counter 1 counter1 2
(integer) 2
127.0.0.1:6379> hgetall mykey
1) "counter"
2) "1"
3) "counter1"
4) "2"
127.0.0.1:6379> hset mykey counter 25
(integer) 0
127.0.0.1:6379> hgetall mykey
1) "counter"
2) "25"
3) "counter1"
4) "2"
127.0.0.1:6379> HINCRBY mykey counter 15
(integer) 40
127.0.0.1:6379> hgetall mykey
1) "counter"
2) "40"
3) "counter1"
4) "2"
127.0.0.1:6379>

how to add TTL value of a key in hset in Redis(Jedis)

I have set a key with an expire timer using:
SETEX mykey 200 "Hello"
I want to add the value of TTL mykey to hset:
hset myhash f1 TTL mykey
But, it shows the following error:
ERR wrong number of arguments for HMSET
I am trying to implement this functionality using Jedis,is there any solution specific to jedis?
You want to get TTL value of some key and put it to a hash? Then try this:
EVAL 'local ttl=redis.call("ttl",KEYS[1]) redis.call("hset","myhash",KEYS[2],ttl)' 2 mykey f1
This script gets TTL value of mykey (1st argument) and puts it into myhash field f1 (2nd argument).
127.0.0.1:6370> SETEX mykey 2000 "Hello"
OK
127.0.0.1:6370> eval 'local ttl=redis.call("ttl",KEYS[1]) redis.call("hset","myhash",KEYS[2],ttl)' 2 mykey f1
(nil)
127.0.0.1:6370> hget myhash f1
"1861"
Update
What you described in comment is another thing. Here is the design I suggest:
along with your data key x create a lock key x:lock when needed. Do write operations only via custom LUA, that checks the key.
LOCK eval 'local l=redis.call("get",KEYS[1]..":lock") if (l==false) then redis.call("setex",KEYS[1]..":lock",10,"t") return 1 end return 0' 1 mykey
UNLOCK del mykey:lock
SETEX (lock-aware) eval 'local l=redis.call("get",KEYS[1]..":lock") if (l==false) then return redis.call("setex",KEYS[1],KEYS[2],KEYS[3]) end return nil' 3 mykey 2000 Hello. It will return OK if succeded or (nil) when not.

Redis get member where score is between min and max

I have a table in sql with 3 columns: BIGINT StartNumber, BIGINT EndNumber, BIGINT LocationId, and I need to be able to do something like this
Select LocationId where StartNumber < #number and EndNumber > #number.
for example:
StartNumber EndNumber LocationId
1 5 1
6 9 1
10 16 2
and when I have #number = 7 I should get LocationId = 1
How can I do this in redis?
I was thinking to move this table to redis, use sorted set and ZRANGEBYSCORE but it did't work for me:
1) When I am using ZADD key score member [score] [member], I am unable to add 2 elements with the same member and different score even with nx parameter:
zadd myset nx 1 "17" 2 "17" - it will add one element and then update its score instead of adding two elements.
2) when I am adding this: zadd set1 2 "a" 4 "b" 6 "c" 10 "d" and then trying to do zrangebyscore set1 3 3 (want to get member whose score include 3) I em getting empty result
P.s. All commands are executed on the example pages of redis website.
So as I understood the task, you don't have overlaps and each interval maps to only one location (?) and intervals don't have gaps. Based on this you can use only one sorted list with lower (or upper) bound values:
ZADD StartNumber 1 "1:5:1" 6 "6:9:1" 10 "10:16:2"
Then you can use:
ZREVRANGEBYSCORE StartNumber 7 -inf LIMIT 0 1
And it will be O(log(N)).
Put differently, your question is "how can I map N ranges of numbers to a location". One way of doing this is using two Sorted Sets, one for the StartNumber and the other one for EndNumber. Since members have to be unique, we'll also need to ensure that by using the Start/End values as part of the member. For example, with your example data, this could be done like so:
ZADD StartNumber 1 "1:5:1" 6 "6:9:1" 10 "10:16:2"
ZADD EndNumber 5 "1:5:1" 9 "6:9:1" 16 "10:16:2"
To find the location for #number=7, do ZRANGEBYSCORE StartNumber -inf 7 and ZRANGEBYSCORE EndNumber 7 +inf and intersect the results. All that remains is to split the intesect's result(s) on the colon (:) and use the 3rd element as the location.
Note: if your app ensures that there are no overlapping ranges and that there can be only one location per "number", you can get the same results with only one set.
(this is the first time that I'm giving two answers to the same question - maybe I'll get a badge or sumthin' ;))
The double Sorted Set approach is a generalization and, as such, aims to solve a bigger set of problems than what the OP needs (as put in the comments to the first answer). That approach is also not effective as the query is O(logn)+O(N) so when N is large (e.g. 5M) that's probably not a good idea.
However, to satisfy the requirements and given that the ranges do not overlap, one could actually use only a single Sorted Set and a simpler query. The set's members should be added by concatenating the EndNumber and LocationId and the their scores should be set to their respective StartNumber, so for the sake of the example:
ZADD ranges 1 "5:1" 6 "9:1" 10 "16:2"
Given #number, obtain the relevant LocationId with the following Redis Lua code (O(logn)):
-- rangelookup.lua
-- http://stackoverflow.com/questions/32185898/redis-get-member-where-score-is-between-min-and-max/32186675
-- A **non inclusive** range search on a Sorted Set with the following data:
-- score = <StartNumber>
-- member = <EndNumber>:<LocationId>
--
-- KEYS[1] - Sorted Set key name
-- ARGV[1] - the number to search
--
-- reply - the relevant id, nil if range doesn't exist
--
-- usage example: redis-cli --eval rangelookup.lua ranges , 7
local number = tonumber(ARGV[1])
local data = redis.call('ZREVRANGEBYSCORE', KEYS[1], number, '-inf', 'WITHSCORES', 'LIMIT', 0, 1)
local reply = nil
if data ~= nil and number > tonumber(data[2]) then
local to, id = data[1]:match( '(.*):(.*)' )
if tonumber(to) > number then
reply = id
end
end
return reply
Sample output:
$ redis-cli --eval rangelookup.lua ranges , 7
"1"
$ redis-cli --eval rangelookup.lua ranges , 9
(nil)
$ redis-cli --eval rangelookup.lua ranges , 99
(nil)

How do I get the size of a set on Redis?

For lists I can do the operation:
LLEN KeyName
and it will return the size of a list in Redis. What is the equivalent command for sets? I can't seem to find this in any documentation.
You are looking for the SCARD command:
SCARD key
Returns the set cardinality (number of elements) of the set stored at
Return value
Integer reply: the cardinality (number of elements) of the set, or 0 if key does not exist.
You can view all of the set commands on the documentation webpage.
If it's a sorted set, you can use
ZCOUNT myset -inf +inf
or
ZCARD myset
zCard is short for cardinality (cardinality is the number of elements in a set). It gives you total number of members inside of a "sorted set".
Sometimes you might wanna extract how many members are inside of a range in a sorted set. For that you can use zCount.
ZCOUNT cars 0 50 // inclusive
this will include 0 and 55. 0 <= .... <=50. But if you do not want to include them
ZCOUNT cars (0 (50
if it is regular set
SCARD cars