ZADD ...">

Redis: get all grades for a sorted set

I need to get all the ratings 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 get all the ratings for myzset, i.e. 10,20,30.

+6
source share
4 answers

One way to solve this problem is to use server-side Lua scripts.

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 using the EVAL command.

It uses the zrange command to retrieve the contents of the zset (with grades), then it creates a set (represented by a table in Lua) to remove excess points and finally creates a response table. Thus, zset values ​​are never sent over the network.

This script has a drawback if the number of elements in zset is really large, as it copies the entire zset in the Lua object (therefore, it takes memory). However, it is easy to change it to iterate over zset gradually (20 elements by 20 elements). 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 

Note that I'm new to Lua, so there are more elegant ways to achieve the same.

+3
source

EDIT . Since your problem with the size of the values ​​was not obvious before, I did some additional research.

According to current documentation, it is not possible to get only grades from a sorted set.

What you need to do to get only grades is to add them to a separate set at the same time and get them from there when necessary.

What you should probably do first is try to map your problem differently with data structures. I can’t say from your question why you need to get points, but there may be other ways to structure the problem that Redis displays better.

-

I'm not sure that you can get all the points without getting the keys, but ZRANGE will at least get the information you are 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"] 
+8
source

You need to pass the optional WITHSCORES argument. See the documentation here:

Key stop button ZREVRANGE [WITHSCORES] Returns the range of members in a sorted set by index, with ratings rated high to low

+1
source

When it comes to ruby, the following command will execute

 redis.zrange("zset", 0, -1, :with_scores => true) # => [["a", 32.0], ["b", 64.0]] 

source Ruby Docs

0
source

All Articles