This guide demonstrates how to build a real-time, filterable leaderboard using:
- Redis with
ZSETandHASHdata structures - RediSearch for advanced queries and filtering
RediSearch is not included in the default Redis image. You must use:
redis/redis-stack(Recommended)redislabs/redisearch(Deprecated)
docker compose up -dAccess Redis UI at: http://127.0.0.1:8001
- Username: (leave blank)
- Password:
password1999
This should be launched before inserting data to observe leaderboard changes in real time.
go run startLeaderboard.goYou will see the leaderboard interface in your terminal. Use the following keys:
←/→to switch between projects↑/↓to change timeframes (week,month,year)PgUp/PgDnto scroll leaderboard verticallyqto quit
Once the leaderboard UI is running, insert the simulated data:
go run insert.goThis generates:
- 100 users
- 5 projects
- 100,000 contributions across the last year
For displaying the necessary leaderboard data, including global rankings over the last week, month, and year, ZSET is preferred for real-time ranking. This allows us to efficiently maintain a leaderboard across different timeframes.
For more complex queries and detailed reporting or analytics, HASH and RediSearch are used. RediSearch allows us to:
- Query specific data (e.g., which user contributed on a particular date)
- Calculate total scores for users within specific timeframes
- Filter contributions by time period
- Aggregate and sort data more efficiently
For example, using RediSearch, we can answer questions like:
- Which user contributed on a specific date?
- What is the total score for a user on a project within a specific date range?
- How many contributions were made in the past week?
- What is the average score for users on project3?
In summary:
- ZSET is used to display global and per-project leaderboard rankings.
- RediSearch is used for detailed user activity insights, project analysis, and team management.
Each contribution updates 6 leaderboard keys:
leaderboard:global:{timeframe}:{period}
Example:
leaderboard:global:week:2025-W31
leaderboard:{project}:{timeframe}:{period}
Example:
leaderboard:project2:month:2025-07
Each contribution is stored in 3 HASH records (week/month/year):
user:{project}:{timeframe}:{period}:{user_id}:{contrib_id}
Example:
user:project1:year:2025:user9:contrib000001
Each hash contains:
user_idprojectscoretimeframe,periodcontribute_id
FT.CREATE contrib_idx ON HASH PREFIX 1 "user:" SCHEMA \
project TAG SEPARATOR , \
user_id TAG SEPARATOR , \
timeframe TAG \
period TEXT \
score NUMERIC SORTABLE ZREVRANGE leaderboard:global:month:2025-07 0 -1 WITHSCORES ZREVRANGE leaderboard:project2:year:2025 0 -1 WITHSCORES ZREVRANK leaderboard:global:week:2025-W31 user23
ZSCORE leaderboard:project3:month:2025-07 user23 FT.AGGREGATE contrib_idx "@timeframe:{week}" GROUPBY 0 REDUCE COUNT 0 AS total_contributions FT.AGGREGATE contrib_idx "@project:{project3}" GROUPBY 0 REDUCE AVG 1 @score AS avg_score FT.AGGREGATE contrib_idx "*" \
GROUPBY 1 @project \
REDUCE SUM 1 @score AS total_score \
SORTBY 2 @total_score DESCThis design ensures your leaderboard system is real-time, filterable, and scalable across teams and timeframes.