redis_zrevrangeSorted set reverse range by rank — linear in the number of elements returned
ZREVRANGE returns elements from a sorted set in descending score order between two rank positions. It is the reverse-order counterpart to ZRANGE and carries the same O(log N + M) cost. Without explicit rank bounds it returns entire collections. As of Redis 6.2, ZREVRANGE is superseded by ZRANGE with the REV flag.
Common Causes
- —Leaderboard queries that return all players in descending order
- —Timeline feeds retrieved in reverse chronological order without pagination
- —Top-N queries that use ZREVRANGE 0 -1 and slice in application code
- —Feed assemblies that fetch all historical entries to display the latest few
How to Fix
- 1.Use explicit start and stop rank bounds — ZREVRANGE 0 9 for the top 10
- 2.Migrate to ZRANGE with REV flag for Redis 6.2+ (consistent API, same performance)
- 3.Use ZREVRANK and ZSCORE for point lookups instead of fetching ranges
- 4.Page results with offset-based rank windows for large collections
Deprecated in Redis 6.2
ZREVRANGE is superseded by
ZRANGE key start stop REV. The unified ZRANGE command handles all direction and range-type combinations. Consider migrating for consistency in new code.Example
typescript
// BAD — entire sorted set in reverse order (all N members)
const allPlayers = await redis.zrevrange('leaderboard', 0, -1, 'WITHSCORES');
// GOOD — top 10 only, explicit bounds
const top10 = await redis.zrevrange('leaderboard', 0, 9, 'WITHSCORES');
// GOOD — Redis 6.2+ equivalent
const top10Modern = await redis.zrange('leaderboard', 0, 9, 'REV', 'WITHSCORES');
// GOOD — paginated leaderboard
async function getLeaderboardPage(redis: Redis, page: number, pageSize = 25) {
const start = page * pageSize;
const stop = start + pageSize - 1;
return redis.zrevrange('leaderboard', start, stop, 'WITHSCORES');
}
// GOOD — point lookups for a specific user
const userRank = await redis.zrevrank('leaderboard', userId); // rank (0-indexed)
const userScore = await redis.zscore('leaderboard', userId); // score value
// GOOD — user's surrounding context
async function getContextWindow(redis: Redis, userId: string, radius = 2) {
const rank = await redis.zrevrank('leaderboard', userId);
if (rank === null) return [];
const start = Math.max(0, rank - radius);
const stop = rank + radius;
return redis.zrevrange('leaderboard', start, stop, 'WITHSCORES');
}