REDIS/jedis update scores of all members in a sorted set
batch-updates, jedis, redis, sortedset
Solution
Communicating between the client and redis may take a lot of time. To avoid that, you can take a "SET-type" copy of the sorted set. For instance, say you have a sorted set "key1":
1 a
2 b
3 c
And you have a set "key2":
a, b, c
Than you can implement the increment easily:
def increase_sorted_set(increment = 1)
redis.ZINTERSTORE("key1", 2, "key1", "key2", "WEIGHTS", "1", increment)
end
Redis will give each member of the (non-sorted) set `key2` a default score of `1`.
For example:
redis 127.0.0.1:6379> ZADD key1 1 a 2 b 3 c
(integer) 3
redis 127.0.0.1:6379> SADD key2 a b c
(integer) 3
redis 127.0.0.1:6379> ZINTERSTORE key1 2 key1 key2 WEIGHTS 1 7
(integer) 3
redis 127.0.0.1:6379> ZRANGE key1 0 -1 WITHSCORES
1) "a"
2) "8"
3) "b"
4) "9"
5) "c"
6) "10"
Problem
What's the best way to increment a medium size sorted set in REDIS? (Preferably with java driver JEDIS) Set has about 100-200K records in it. I want to increment their score by a given double number. before ``` 1 a 2 b 3 c ``` after (increment by 1) ``` 2 a 3 b 4 c ``` The only possible solution i came up with is: - Fetch all sorted set (say A) contents over the network. (REDIS -> application). - Create a pipeline, increment them in the same setA with ZADD or ZINCRBY in a loop - Then execute the pipeline. Is there another/better way to do it? UPDATE Here's how to do a for loop to increment all sorted set members using EVAL and Lua in REDIS. ``` local members = redis.call('zrange',KEYS[1],0,-1) for i, member in ipairs(members) do redis.call('zincrby',KEYS[1],inc,member) end ``` Save this into a string and run eval using your driver (java in this case). Execution returns nothing. using Jedis ``` // script is the script string // 1 is the number of keys- keep it this way for this script // myzset is the name of your sorted set // 1.5 is the increment, you can use +/- values to inc/dec. jedis.eval(script, 1, "myzset", "1.5"); ```