Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redis: Is it possible sort ordered set result with same score by other key value

ZADD myset 1 ad1
ZADD myset 1 ad2

SET order:ad1 1
SET order:ad2 2

How to sort firstly by ordered set score then the order value?

like image 317
Bruce Dou Avatar asked May 02 '12 09:05

Bruce Dou


People also ask

What is the difference between set and sorted set in Redis?

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. In Redis sorted set, add, remove, and test for the existence of members in O (1) ...

How is the leaderboard sorted in Redis?

The leaderboard has been sorted in ascending order, based on the scores. Scores can be duplicated, but the members can not. If two members have the same score, Redis sorts them based on members’ lexicographical order. For example, Jennifer and Peter have the same score of 690.

What is the difference between a sorted set and a score?

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.

Can scores be duplicated in Redis?

Scores can be duplicated, but the members can not. If two members have the same score, Redis sorts them based on members’ lexicographical order. For example, Jennifer and Peter have the same score of 690. But Redis makes sure to put Jennifer before Peter because J comes before P.


1 Answers

If you want to store a result (not altering the way data are stored), then you can use the SORT command. It can be applied to zset.

For instance:

> zadd myset 1 albert
> zadd myset 1 joseph
> zadd myset 4 bertrand
> zadd myset 2 casimir
> zadd myset 3 alfred

You can sort by value:

> sort myset alpha
1) "albert"
2) "alfred"
3) "bertrand"
4) "casimir"
5) "joseph"

You can sort by score AND value:

> zrange myset 0 -1
1) "albert"
2) "joseph"
3) "casimir"
4) "alfred"
5) "bertrand"

Now let's add a new property to these objects:

> set order:albert 5
> set order:alfred 3
> set order:casimir 1
> set order:joseph 4
> set order:bertrand 2

You can sort by the new order property:

> sort myset by order:*
1) "casimir"
2) "bertrand"
3) "alfred"
4) "joseph"
5) "albert"

Now if you need to sort by score AND this order property, then you have no other choice than materialize the order property in the zset OR materialize the score in the order property.

For instance, adding the order property in the zset, we get:

> del myset
> zadd myset 1 5:albert
> zadd myset 1 4:joseph
> zadd myset 4 2:bertrand
> zadd myset 2 1:casimir
> zadd myset 3 3:alfred
> zrange myset 0 -1
1) "4:joseph"
2) "5:albert"
3) "1:casimir"
4) "3:alfred"
5) "2:bertrand"

Beware: in that case, the property field is sorted according to the lexicographic order, so the value may have to be normalized if you need numerical order and multiple digits. There are various tricks to do this. For instance, instead of storing "1", "12" or "123", you can store "11", "212" or "3123", the first digit representing the number of digits of your number.

If both the score and the order property can change, this is not very convenient and you will be better served by sorting on client side. This can be achieved in two roundtrips by retrieving the zset with scores on one side, and the corresponding order values on the other side.

> zrange myset 0 -1 withscores
> sort myset by order:* get order:* get #

Up to the client to join the two results (using some kind of dictionary or associative array), and sort to get the final result.

like image 67
Didier Spezia Avatar answered Nov 13 '22 18:11

Didier Spezia