**Tags**

I’ve been using Redis extensively in a project in the last couple of weeks. And this post is on a small trick I had to resort to while using sorted sets. If you don’t already know, the rank of an element in a Redis sorted set is its index in the sorted order. And rank starts at 0.

Let’s create a sorted set of three members A, B, C with scores 40, 10 and 40.

` redis.zadd 'myset', 40, 'A'`

redis.zadd 'myset', 10, 'B'

redis.zadd 'myset', 40, 'C'

And when you do `redis.zrange 'myset', 0, -1`

, you get `["B", "A", "C"]`

and you can see that B is ranked first (rank 0), followed by A (rank 1) and then C (rank 2). This can also be verified by calling zrank on each item.

` redis.zrank 'myset', 'A'`

=> 1

redis.zrank 'myset', 'B'

=> 0

redis.zrank 'myset', 'C'

=> 2

My use case required the same rank for same scores and this is how I made Redis do what I wanted:

- I created a sorted set with the scores being the members themselves.

`redis.zadd 'newset', 10, 10`

redis.zadd 'newset', 40, 40

- Then I saved the member-score mapping in a hash separately.

`redis.hset 'myhash', 'A', 40`

redis.hset 'myhash', 'B', 10

redis.hset 'myhash', 'C', 40

- Now, when I need the rank of a member, I just need to look up the member’s score in the hash and find the rank of that score from the new sorted set.

`r = redis.hget 'myhash', 'A'`

=> "40"

redis.zrank 'newset', r

=> 1

r = redis.hget 'myhash', 'B'

=> "10"

redis.zrank 'newset', r

=> 0

r = redis.hget 'myhash', 'C'

=> "40"

redis.zrank 'newset', r

=> 1

That is, rank(A) and rank(C) are equal to rank(40) and rank(B) is equal to rank(10). This gives rank 1 for A and C and rank 0 for B which is exactly what I wanted. Yay!

Vaidik Kapoor

said:Interesting! I have used this kind of approach (i.e. using hashes) a couple of times myself.

lemig

said:Hi. you can do easily like this:

a_score = $r.zscore(‘myset’, ‘A’)

a_rank = $r.zcount(‘myset’, ‘-inf’, “(#{a_score}”)

=> 1

# 0 for b

# 1 for c

Cheers.

Miguel