Reputation: 1197
I'm using Firestore to build a game and I'd like to show a list of high scores.
I'm currently getting the 10 highest scores with the following query:
const q = query(doc(db, "scores", title), orderBy("score", "desc"), limit(10));
In addition to this, I'd like to let the player know how they fared compared to global high scores. For example, if they got the 956th-highest score, I'd like them to know their relative position is 956.
I've seen that, for cursors, one can provide an offset with a given document, ie:
const q = query(doc(db, "scores", title), orderBy("score", "desc"), limit(10), startAt(myScoreDocRef));
Is there any way from this to get the score's logical index in the sorted result set?
Upvotes: 3
Views: 448
Reputation: 50830
Firestore recently added getCountFromServer()
(API reference) function that is perfect for this use case. You can create a query that matches documents with score greater than current user's score and fetch the count as shown below:
const currentUserScore = 24;
const q = query(
collection(db, 'users'),
orderBy('score', 'desc'),
where('score', '>', currentUserScore)
)
// number of users with higher score
const snapshot = await getCountFromServer(q)
console.log(`Your rank: ${snapshot.data().count + 1}`)
However, in case multiple users have same score, they will all see same rank with this query. As a workaround you can add another parameter to the ranking apart from score, like querying users with same score and checking user age or so.
The count query costs only 1 read for each batch of up to 1000 index entries matched by the query (as per the documentation) so it's much for efficient than querying users with some offset and manually calculating the rank.
Upvotes: 4