0

The use case:

We've got 500 million players of a videogame in a MongoDB collection playerProfiles. Each document has several properties like wins or kills. Now we'd like to create a leaderboard for these properties so that we can figure out each player's rank for wins or kills.

For the Top 100 leaderboard I would simply sort the collection by one of these properties and cache the result for let's say 5 minutes in redis. What I am struggling with is how I can make this work for all player profiles.

The question:

How should I get every player's rankings for wins or kills so that it doesn't overwhelm the database server? If it makes sense I am free to use other database systems to solve this issue.

My idea:

My first idea was to create an own mongodb collection which only contains the player's id and it's rankings for kills and wins. I would then regularly update this collection. But even updating this collection of 500m player profiles should take a significant time. Is there a better approach for this type of problem?

kentor
  • 16,553
  • 20
  • 86
  • 144
  • You could use only redis to power the rankings. It's very good. https://redis.io/commands#sorted_set https://www.1and1.com/cloud-community/learn/database/redis/how-to-implement-a-simple-redis-leaderboard/ – Sergio Tulentsev Apr 23 '18 at 09:19
  • Interesting idea, but I potentially see two issues. First one is that I need to query the leaderboard ranking by playerId (because I want to lookup a player's ranking and not the player who is rank x). The second concern is the amount of data, is redis a good idea for 500m rankings? – kentor Apr 23 '18 at 09:53
  • 1) there's a command for that (ZRANK). 2) just have enough ram. – Sergio Tulentsev Apr 23 '18 at 09:55

1 Answers1

1

you could use mongodb aggregate to achieve this.You basically sort the documents by wins and kills and then push each user in a new array while preserving the index, this index is the users' rank after that you can simply use 'unwind' on this newly created array and find the user in question, this will give you the user's rank with other details.

Here is a sample aggregate pipeline:

[{
    "$sort": { 
        "wins": -1
    }
},
{
    "$group": {
        "_id": false,
        "players": {
            "$push": {
                "_id": "$_id",
                "playerId": "$playerId",
                "wins": "$wins"
            }
        }
    }
},
{
    "$unwind": {
        "path": "$players",
        "includeArrayIndex": "rank"
    }
},
{
    "$match": {
        "players._id": 1234567890
    }
}]

Now you should have a rank field with the player details which will tell you the rank of the player based on wins, you can extend and add kills to the sort.

Hope this helps! :)

Hardik Shah
  • 111
  • 7