How to write the below in Redis
"Create a sorted set myset1 with the following values ( 1, 'a', 2, 'b', 3 , 'c').Create a sorted set myset 2 with the following values (4, 'b', 1, 'c', 0, 'd').Find the intersection of myset1 and myset2 : - Write a command to find the intersection of myset1 and myset2 and store the intersection in out- Write a command to see the resulting intersection output Sorted set "out" : Find the union of myset1 and myset2 - Write a command to take the union of myset1 and myset2 and store the output in unout - Write a command to see the resulting intersection output Sorted set "unout" "
I wrote the code like below and it says 80% correct.
127.0.0.1:6379> zadd myset1 0 1 0 a 0 2 0 b 0 3 0 c (integer) 6 127.0.0.1:6379> zadd myset2 0 4 0 b 0 1 0 c 0 0 0 d (integer) 6 127.0.0.1:6379> zinterstore out 2 myset1 myset2 (integer) 3 127.0.0.1:6379> zrange out 0 -1 1) "1" 2) "b" 3) "c" 127.0.0.1:6379> zunionstore unout 2 myset1 myset2 (integer) 9 127.0.0.1:6379> zrange unout 0 -1 1) "0" 2) "1" 3) "2" 4) "3" 5) "4" 6) "a" 7) "b" 8) "c" 9) "d" 127.0.0.1:6379>
You can use ZINTERSTORE and ZUNIONSTORE commands to computer intersection and union of intersection of sorted sets.
ZINTERSTORE
ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]
Computes the intersection of numkeys sorted sets given by the
specified keys, and stores the result in destination. It is mandatory
to provide the number of input keys (numkeys) before passing the input
keys and the other (optional) arguments.
By default, the resulting score of an element is the sum of its scores
in the sorted sets where it exists. Because intersection requires an
element to be a member of every given sorted set, this results in the
score of every element in the resulting sorted set to be equal to the
number of input sorted sets.
ZUNIONSTORE
ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]
Computes the union of numkeys sorted sets given by the specified keys,
and stores the result in destination. It is mandatory to provide the
number of input keys (numkeys) before passing the input keys and the
other (optional) arguments.
By default, the resulting score of an element is the sum of its scores
in the sorted sets where it exists.
Edit:
It's not accepting since you're adding score as key as well
Yout ZADD commands should be
ZADD myset1 1, a 2 b 3 c
zadd myset2 4 b 1 c 0 d
Try this
ZADD myset1 1 a 2 b 3 c
ZADD myset2 4 b 1 c 0 d
ZINTERSTORE out 2 myset1 myset2
ZUNIONSTORE unout 2 myset1 myset2
Related
I am new to Redis.
127.0.0.1:6379> zadd myset 1 'one'
(integer) 1
127.0.0.1:6379> zadd myset 2 'two'
(integer) 1
127.0.0.1:6379> zadd myset 3 'three' 4 'four'
(integer) 2
127.0.0.1:6379> zadd myset 10 'ten' 9 'nine'
(integer) 2
I tried ZRANGEBYSCORE, but it shows member only..
127.0.0.1:6379> ZRANGEBYSCORE myset -inf +inf
1) "one"
2) "two"
3) "three"
4) "four"
5) "nine"
6) "ten"
But I want to get Score / Member pairs.
How can I get these pairs ?
As #Ersoy already commented:
you need to add WITHSCORES at the end, ZRANGEBYSCORE myset -inf +inf WITHSCORES
The reply is sent in a format as follows:
1) MEMBER_1
2) SCORE_1
3) MEMBER_2
4) SCORE_1
...
If you want the reply as a list/array of pair, like:
1) MEMBER_1, SCORE_1
2) MEMBER_2, SCORE_2
...
Any sane Redis client[1], even in your preferred language, is likely to convert it as such.
[1] not including redis-cli
When I have a sorted set with scores, I'd like to have the right rank even when multiple items have the same score.
For instance, when there are 5 items with scores: 1, 2, 2, 2, 3, I'd like to have those three central items to have the same rank (1), while the highest score gets rank 0 (with ZREVRANGE), and the lowest gets rank 4.
I see that it's possible to query the amount of keys with the same score somewhat efficiently O(log(N)), but it looks like if I want to have the scores as I want them, I'd have to use zscan, which is O(N).
Edit: add complete example based on the accepted solution
Our dataset is a sorted set with scores. For example: a has score 1, b, c and d have score 2, and e has score 3:
127.0.0.1:6379> zadd aset 1 a
(integer) 1
127.0.0.1:6379> zadd aset 2 b
(integer) 1
127.0.0.1:6379> zadd aset 2 c
(integer) 1
127.0.0.1:6379> zadd aset 2 d
(integer) 1
127.0.0.1:6379> zadd aset 3 e
(integer) 1
ZREVRANK works for those items with a unique score:
127.0.0.1:6379> zrevrank aset a
(integer) 4
127.0.0.1:6379> zrevrank aset e
(integer) 0
But it fails for those items with the same score:
127.0.0.1:6379> zrevrank aset b
(integer) 3
127.0.0.1:6379> zrevrank aset c
(integer) 2
127.0.0.1:6379> zrevrank aset d
(integer) 1
To solve that, first get the score with ZSCORE:
127.0.0.1:6379> zscore aset c
"2"
The other items have the same score, of course:
127.0.0.1:6379> zscore aset b
"2"
127.0.0.1:6379> zscore aset d
"2"
To get their rank, just use ZCOUNT with the score:
127.0.0.1:6379> zcount aset (2 +inf
(integer) 1
This also works for those items that have a unique score:
127.0.0.1:6379> zcount aset (1 +inf
(integer) 4
127.0.0.1:6379> zcount aset (3 +inf
(integer) 0
Writing this as an atomic lua script is left as an exercise for the reader.
For a given item with score x, you can determine its rank in O(log(N)) time with ZCOUNT (X +inf.
Exactly how you make use of that will depend on the details of your implementation.
ZREVRANGEBYLEX could be used in this case. The time complexity in this case would be O(log(N)+M) with N being the number of elements in the sorted set and M the number of elements being returned. Please look at ZRANGEBYLEX for syntax.
Lex family of sorted set commands allow you to specify lexicographical ordering for keys with same values.
From a redis sorted set, how do I retrieve the rank of highest value that has a score just less than a given score?
For instance, imagine my sorted set is:
rank value score
1) 'a' -10
2) 'd' -4
3) 'c' 0
4) 'b' 2
5) 'e' 10
Specifically, If I'm given the score 12, I want to retrieve rank 5. If I'm given the score 1, I want to retrieve rank 3. If I'm given a score -11, I want to retrieve nothing.
Note #1: rank in a Sorted Set is 0-based
Note #2: you'll have to do two queries, one for finding the element and the other for obtaining its rank.
Example using redis-cli:
127.0.0.1:6379> ZADD z -10 a -4 d 0 c 2 b 10 e
(integer) 5
127.0.0.1:6379> ZREVRANGEBYSCORE z (12 -inf LIMIT 0 1
1) "e"
127.0.0.1:6379> ZRANK z e
(integer) 4
127.0.0.1:6379> ZREVRANGEBYSCORE z (1 -inf LIMIT 0 1
1) "c"
127.0.0.1:6379> ZRANK z c
(integer) 2
127.0.0.1:6379> ZREVRANGEBYSCORE z (-11 -inf LIMIT 0 1
(empty list or set)
Naturally, a Lua script would be ideal for this case, i.e:
$ cat script.lua
local r=redis.call('ZREVRANGEBYSCORE', KEYS[1], '('..ARGV[1], '-inf', 'LIMIT', 0, 1)
if #r > 0 then
r=redis.call('ZRANK', KEYS[1], r[1])
end
return r
$ redis-cli --eval script.lua z , 12
(integer) 4
$ redis-cli --eval script.lua z , 1
(integer) 2
$ redis-cli --eval script.lua z , -11
(empty list or set)
I am using a command line client. Looks like the ZREM doesn't help much. Now I wonder whether that is possible at all.
To remove the element with the highest rank, use zremrangebyrank <key> -1 -1. Here's an example:
127.0.0.1:6379> zadd test 1 one
(integer) 1
127.0.0.1:6379> zadd test 2 two
(integer) 1
127.0.0.1:6379> zadd test 3 three
(integer) 1
127.0.0.1:6379> zrange test 0 -1
1) "one"
2) "two"
3) "three"
127.0.0.1:6379> zremrangebyrank test -1 -1
(integer) 1
127.0.0.1:6379> zrange test 0 -1
1) "one"
2) "two"
Since zrange "Lexicographical order is used for elements with equal score" how do I go around this issue?
For example:
zadd s 0 1
zadd s 0 2
zadd s 0 10
zadd s 0 3
zrange s 0 4
1) 1
2) 10
3) 2
4) 3
How do I make it sort like this (while ofc honor the score):
1) 1
2) 2
3) 3
4) 10
You cannot alter the lexicographic order.
However, you could store a value whose lexicographic order matches with numerical order. For instance instead of storing:
1
2
12
15
122
321
you could store:
A1
A2
B12
B15
C122
C321
The first letter is just a code to indicate the number of digits of the numerical value (A=1, B=2, etc ...), so that numerical and lexicographic order is the same. The client application can easily add/remove this prefix at store/retrieve time.
zadd s 0 A1
zadd s 0 A2
zadd s 0 B10
zadd s 0 A3
zrange s 0 4
1) "A1"
2) "A2"
3) "A3"
4) "B10"