Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting the rank of the Player in Firestore

I have 10k users in Firestore and each user’s documentId is their uid and scores are registered to their document. To find Top 20 of Leaderboard, it successfully gets query of Top 20 users based on its scores, as using composite index.

let query = usersRef.order(by: scores, descending: true).limit(to: 20)
query.getDocuments() //to get 20 documents

Unfortunately, i could not find a way to handle the rank (index No.) of the current player who is not involved in Top 20. Why does Firestore not return the rank (index No.) of the query based on each user’s uid? or any other way to solve the issue in Firestore?

like image 255
Sunrise17 Avatar asked Nov 16 '22 08:11

Sunrise17


1 Answers

You can use startAfter/startAt and provide a document reference to offset your query.

So, if you have a list of the top twenty records, you could repeat the exact same query but specify that it startAfter the last element in your list, then you'd return records for positions 20 to 39, etc.

You can also set the query offset to return the results that would return at a set position, however this is highly unrecommended because to use offset, you incur a write for every document you skip over. So if you wanted to fetch the bottom twenty players, you'd end up waiting 9,980 document reads!

You can check out Paginate data with query cursors for further information.

In terms of your existing data structure...

To find out the rank of a user by their user identifier, it is likely you'll need to manually cache their current ranking. You could set up a scheduled task to compute the ranking of the player, and compute the ranking of each player daily. This would be costly, since the number of writes per execution would scale with your number of users; and since it's cache-based, subject to timing constraints (a player wouldn't see their rank change until the next time you computed it.)

A more simplistic approach would be to take the top score, the bottom score, and scale their points to an equivalent rank based on the number of users (this doesn't necessarily have to be a linear scale, you could use a bell curve for example), however this would be imprecise, and possible for multiple users to appear to have the same rank. However, this might be a suitable concession depending on your use case.

Another method would be to have the users update the ranking system themselves when they attempt to view their own rank. It could look at the points of the user that comes ahead of it and below it, and have the ranks effectively maintain themselves by determining whether it should become before or after the neighbouring records. This would require a more elaborate rules structure to prevent cheating, and would introduce discontinuity in your ranking dataset.

like image 188
Mapsy Avatar answered Mar 02 '23 15:03

Mapsy