I need to get all score available for a redis sorted set.
redis> ZADD myzset 10 "one"
(integer) 1
redis> ZADD myzset 20 "two"
(integer) 1
redis> ZADD myzset 30 "three"
(integer) 1
Now I want to retrieve all score for myzset, ie. 10,20,30.
Redis Sorted Sets are similar to Redis Sets with the unique feature of values stored in a set. The difference is, every member of a Sorted Set is associated with a score, that is used in order to take the sorted set ordered, from the smallest to the greatest score.
ZSET is a short name for Redis Sorted Set, a Redis data type documented here. Each key in a sorted set has multiple values inside, associated with a floating value score.
Sorted set is essentially a unique collection of ordered Redis Strings that have a numeric score associated with them. Ordering is based on scores and the string lexicographical order (more on this later). The strings must be unique while the scores might be repeated.
Sorted Set is similar to the Set data structure in Redis. Members can be a list of non-repeating strings. The only difference is that each member is associated with a score, a floating-point number that provides a sorting order for the Sorted Set. Members are always sorted from the smallest to the greatest score.
EDIT: Since your problem with the size of the values wasn't obvious before, I did some additional research.
There is according to the current documentation no way to get just the scores from a sorted set.
What you'll need to do to get just the scores is to simultaneously add them to a separate set and get them from there when needed.
What you should probably do first though is to try to map your problem differently into data structures. I can't tell from your question why you'd need to get the scores, but there may be other ways to structure the problem that will map better to Redis.
--
I'm not sure there is any way to get all scores without getting the keys, but ZRANGE
will at least get the information you're looking for;
redis> ZADD myzset 10 "one"
(integer) 1
redis> ZADD myzset 20 "two"
(integer) 1
redis> ZADD myzset 30 "three"
(integer) 1
redis> ZRANGE myzset 0 -1 WITHSCORES
["one","10","two","20","three","30"]
One way to address this problem is to use server-side Lua scripting.
Consider the following script:
local res = {}
local result = {}
local tmp = redis.call( 'zrange', KEYS[1], 0, -1, 'withscores' )
for i=1,#tmp,2 do
res[tmp[i+1]]=true
end
for k,_ in pairs(res) do
table.insert(result,k)
end
return result
You can execute it by using the EVAL command.
It uses the zrange command to extract the content of the zset (with scores), then it builds a set (represented with a table in Lua) to remove redundant scores, and finally build the reply table. So the values of the zset are never sent over the network.
This script has a flaw if the number of items in the zset is really high, because it copies the entire zset in a Lua object (so it takes memory). However, it is easy to alter it to iterate on the zset incrementally (20 items per 20 items). For instance:
local res = {}
local result = {}
local n = redis.call( 'zcard', KEYS[1] )
local i=0
while i<n do
local tmp = redis.call( 'zrange', KEYS[1], i, i+20, 'withscores' )
for j=1,#tmp,2 do
res[tmp[j+1]]=true
i = i + 1
end
end
for k,_ in pairs(res) do
table.insert(result,k)
end
return result
Please note I am a total newbie in Lua, so there are perhaps more elegant ways to achieve the same thing.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With