Reputation: 134
I'm using Redis sorted set to keep some values in order. for example:
score | data
0 | a
1 | b
2 | c
3 | d
In some situations of my app, I have to remove some of the entries. for example, I delete scores 1 and 2 members:
score | data
0 | a
3 | d
I want to change the above to:
score | data
0 | a
1 | d
How can I do this?
please help, thanks in advance.
Upvotes: 1
Views: 830
Reputation: 134
After searching and hard work, I found the solution.
You can use Lua script and EVAL command:
EVAL
"
redis.call('ZREMRANGEBYSCORE', KEYS[1], KEYS[2], KEYS[2]);
local otherMembers = redis.call('ZRANGEBYSCORE', KEYS[1], KEYS[2], 1/0);
for k, v in ipairs(otherMembers) do
redis.call('ZINCRBY', KEYS[1], -1], v);
"
2 key index;
Upvotes: 0
Reputation: 22906
It seems that you don't need the score, instead, you need the rank.
You can keep a monotonically increasing counter, which starting from 0, and each time when you need to add an element to the set, call incr
on the counter to get a score, and insert the element into the set. So that, each new element will always has the largest score, i.e. new element will rank lower than old elements.
127.0.0.1:6379> incr counter
(integer) 1
127.0.0.1:6379> zadd set 1 a
(integer) 1
127.0.0.1:6379> incr counter
(integer) 2
127.0.0.1:6379> zadd set 2 b
(integer) 1
127.0.0.1:6379> incr counter
(integer) 3
127.0.0.1:6379> zadd set 3 c
(integer) 1
127.0.0.1:6379> incr counter
(integer) 4
127.0.0.1:6379> zadd set 4 d
You can use ZREMRANGEBYRANK
to remove elements, and ZRANK
to get the rank of each element (the rank always start from 0).
127.0.0.1:6379> zremrangebyrank set 1 2
(integer) 2 <------- remove b and c
127.0.0.1:6379> zrank set a
(integer) 0
127.0.0.1:6379> zrank set d
(integer) 1
Upvotes: 2
Reputation: 196
I think it's not possible to use a sorted list in Redis like an indexed array.
If you want to have a sorted list with a sequential score you should take care of it yourself so after every delete, you can overwrite your sorted list with new scores.
Upvotes: 2