Maintenance

Site is under maintenance — quizzes are still available.

Go to quizzes

ZRANK and ZSCORE

Learn how to retrieve the rank of a member and its score from a sorted set using ZRANK and ZSCORE commands in Redis.

Focus: use zrank and zscore

Sponsored

Imagine you're running a leaderboard for an online game — thousands of players, scores changing every second. Without a way to ask "What's this player's current position?" or "What score do they have right now?", you'd have to sort through the entire dataset each time. In Redis, sorted sets solve this perfectly, and with ZRANK and ZSCORE you can instantly answer those two critical questions: a member's rank and their exact score.

The problem this lesson solves

Sorted sets are powerful — they maintain elements ordered by a numeric score, making leaderboards, priority queues, and real-time rankings easy to implement. But once you've added members to a sorted set (using ZADD), you often need to look up individual positions or scores without re-sorting. That's where ZRANK and ZSCORE come in: they provide O(log N) lookups for rank and score, but they behave differently depending on ordering direction, missing members, and edge cases. Without understanding these nuances, your application might return confusing results or even crash on nil values.

Core concept / mental model

Think of a sorted set as a double-entry directory: each member has a unique name (the element) and a file (the score). The set keeps members ordered by score, from lowest to highest.

  • ZSCORE is like asking: "What is this person's file number?" — it returns the score associated with a given member.
  • ZRANK is like asking: "Which position does this person occupy in line?" — it returns the zero-based index (rank) of that member, assuming ascending order (lowest score first).

There's also ZREVRANK, which reverses the order (highest score becomes rank 0). Both commands rely on the internal skip list data structure, giving them O(log N) performance.

Pro Tip: ZRANK returns a zero-based index. Rank 0 means the member has the lowest score. If you need the highest score first (like a leaderboard with winner at top), use ZREVRANK.

How it works step by step

1. Adding data to a sorted set (prerequisite)

Before querying ranks and scores, you need a sorted set with some members. Use ZADD:

127.0.0.1:6379> ZADD leaderboard 100 "Alice" 200 "Bob" 150 "Charlie"
(integer) 3

This creates a sorted set named leaderboard with three members and their scores.

2. Using ZSCORE to retrieve a member's score

ZSCORE takes the key and member name, and returns the score as a floating-point number.

127.0.0.1:6379> ZSCORE leaderboard "Alice"
"100"
127.0.0.1:6379> ZSCORE leaderboard "Bob"
"200"

If the member doesn't exist, it returns (nil).

3. Using ZRANK to get the ascending rank

ZRANK returns the zero-based rank of the member when sorted by score from low to high.

127.0.0.1:6379> ZRANK leaderboard "Alice"
(integer) 0
127.0.0.1:6379> ZRANK leaderboard "Charlie"
(integer) 1
127.0.0.1:6379> ZRANK leaderboard "Bob"
(integer) 2

Alice has the lowest score (100) → rank 0. Bob has the highest (200) → rank 2.

4. Using ZREVRANK for descending order

If you want the highest score to be rank 0 (e.g., winner of a contest), use ZREVRANK:

127.0.0.1:6379> ZREVRANK leaderboard "Bob"
(integer) 0
127.0.0.1:6379> ZREVRANK leaderboard "Alice"
(integer) 2

Hands-on walkthrough

Let's run through a complete example in the Redis CLI. First, set up a leaderboard with varying scores:

127.0.0.1:6379> DEL leaderboard
(integer) 1
127.0.0.1:6379> ZADD leaderboard 50 "Emma" 75 "Liam" 100 "Olivia" 60 "Noah"
(integer) 4

Now practice retrieving rank and score:

127.0.0.1:6379> ZSCORE leaderboard "Liam"
"75"
127.0.0.1:6379> ZRANK leaderboard "Liam"
(integer) 2           # Because sorted order: Emma(50 rank0), Noah(60 rank1), Liam(75 rank2), Olivia(100 rank3)
127.0.0.1:6379> ZREVRANK leaderboard "Liam"
(integer) 1           # Because descending order: Olivia(rank0), Liam(rank1), Noah(rank2), Emma(rank3)

Working with ties

What if two members have the same score? Redis uses lexicographic ordering as a tiebreaker — the members are sorted alphabetically.

127.0.0.1:6379> ZADD leaderboard 100 "Zara" 100 "Adam"
(integer) 2
127.0.0.1:6379> ZRANK leaderboard "Adam"
(integer) 0           # Adam comes before Zara because 'A' < 'Z'
127.0.0.1:6379> ZRANK leaderboard "Zara"
(integer) 1

Using with Redis from Python

Here's how you'd use zrank and zscore in Python with the redis-py library:

import redis

r = redis.Redis(host='localhost', port=6379, decode_responses=True)

# Add some players
r.zadd('game_scores', {'Alice': 1200, 'Bob': 800, 'Charlie': 1500})

# Get Bob's score
score = r.zscore('game_scores', 'Bob')
print(f"Bob's score: {score}")  # Output: 800

# Get Alice's rank (ascending)
rank = r.zrank('game_scores', 'Alice')
print(f"Alice's rank: {rank}")  # Output: 1 (Bob is 0, Alice 1, Charlie 2)

# Get Charlie's rank in descending (best first)
rev_rank = r.zrevrank('game_scores', 'Charlie')
print(f"Charlie's reverse rank: {rev_rank}")  # Output: 0

Compare options / when to choose what

Command Purpose Returns Order Use case
ZSCORE Get the score of a member Float or nil N/A When you need the actual value (e.g., points, timestamps)
ZRANK Get the position from low to high Integer or nil Ascending (lowest score first) When you need a rank where smaller is better (e.g., race times)
ZREVRANK Get the position from high to low Integer or nil Descending (highest score first) Most leaderboards (highest score = 1st place)
ZRANK WITHSCORE (Redis 7.2+) Get both rank and score in one call Array Ascending When you need both in a single round trip

Pro Tip: In Redis 7.2 and later, ZRANK and ZREVRANK accept a WITHSCORE option that returns both the rank and score as an array — reducing round trips.

Troubleshooting & edge cases

1. Member doesn't exist

127.0.0.1:6379> ZSCORE leaderboard "MissingUser"
(nil)
127.0.0.1:6379> ZRANK leaderboard "MissingUser"
(nil)

Always check for None/nil in your application code to avoid errors.

2. Empty sorted set

127.0.0.1:6379> ZSCORE empty_set "anything"
(nil)
127.0.0.1:6379> ZRANK empty_set "anything"
(nil)

3. Key doesn't exist at all

127.0.0.1:6379> ZSCORE nonexistent_key "member"
(nil)

Redis treats it the same as an empty sorted set — (nil).

4. Using wrong data type

127.0.0.1:6379> SET mystring "hello"
OK
127.0.0.1:6379> ZSCORE mystring "anything"
(error) WRONGTYPE Operation against a key holding the wrong kind of value

Always ensure the key holds a sorted set, not a string or other type.

5. Negative or floating scores

127.0.0.1:6379> ZADD scores -5.5 "negative" 3.1415 "pi"
(integer) 2
127.0.0.1:6379> ZSCORE scores "negative"
"-5.5"
127.0.0.1:6379> ZRANK scores "negative"
(integer) 0           # Negative scores are sorted first

6. Performance considerations

Both ZRANK and ZSCORE are O(log N) — fast even for millions of members. However, if you need to get the rank and score for many members in a loop, consider using ZRANK ... WITHSCORE (if on Redis ≥7.2) or batch with a Lua script to minimize round trips.

What you learned & what's next

You now know how to use ZRANK and ZSCORE to: - Retrieve a member's score from a sorted set (ZSCORE) - Get a member's rank in ascending or descending order (ZRANK / ZREVRANK) - Handle common edge cases (missing members, wrong types, tie-breaking) - Apply these commands in real-world leaderboard and scoring scenarios

Next step: In the following lesson, you'll learn about ZRANGE and ZREVRANGE — commands that retrieve ranges of members from sorted sets, allowing you to paginate through leaderboards or extract subsets of data. That's the natural companion to the positional queries you just mastered.

Key takeaway: ZSCORE gives you the actual value; ZRANK gives you position. Together, they unlock efficient, O(log N) lookups on sorted sets — essential for any real-time ranking system.

Practice recap

Practice by creating a sorted set called high_scores with members Alice (score 850), Bob (1200), and Charlie (950). Use ZSCORE to get Charlie's score. Use ZRANK to find Alice's ascending rank. Then use ZREVRANK to see who is in first place. Add a new member with a score that ties Charlie, and observe how the rank changes. This solidifies your understanding of edge cases.

Common mistakes

  • Forgetting that ZRANK returns a zero-based index — rank 0 means the first element, not the second.
  • Using ZRANK when you need the highest score first — use ZREVRANK instead for descending leaderboards.
  • Not checking for None/nil return when a member doesn't exist, causing a TypeError in Python code.
  • Applying ZSCORE or ZRANK on a key that holds a non-sorted-set type, leading to a WRONGTYPE error.
  • Assuming member order is stable when scores are equal — ties are broken lexicographically by member name.

Variations

  1. Use ZREVRANK when you need descending rank (highest score gets rank 0) — ideal for typical leaderboards.
  2. In Redis 7.2+, ZRANK key member WITHSCORE returns both rank and score in a single round trip.
  3. For batch queries, consider a Lua script to fetch multiple ranks/scores atomically instead of looping.

Real-world use cases

  • Gaming leaderboard: get a player's current rank and score after each match to display on the dashboard.
  • Real-time bidding system: retrieve the bid score of a participant and their rank among all bidders in an auction.
  • Priority queue monitoring: check the priority (score) and position of a job in a processing queue to estimate wait time.

Key takeaways

  • ZSCORE returns the numeric score of a member from a sorted set, or nil if the member doesn't exist.
  • ZRANK returns the zero-based rank in ascending order (lowest score first); ZREVRANK for descending.
  • Both commands run in O(log N) time and require a sorted set key — wrong types produce WRONGTYPE errors.
  • Tied scores are ordered lexicographically by member name; plan accordingly when equal scores are possible.
  • Always check for nil returns when the member might not exist to avoid crashes in application code.

Sponsored

Sponsored

Discussion

Questions, corrections, and tips help everyone reading this page.

0 comments

Add a comment

Shown publicly with your comment.

Be constructive · max 4,000 characters

No comments yet — start the thread.

Related tutorials, quizzes, and articles for this topic.