So this is how my mongoose schema looks like:
const QuizModel = new mongoose.Schema({
quizId: { type: String, required: true, trim: true },
userId: { type: String, required: true, trim: true },
result: {
score: { type: Number, required: true},
time: { type: Number, required: true },
},
});
This is a quiz application so there are multiple documents with same userId.
I am trying to make a query to build leaderboard and I came up with this.
const topUsers = await QuizModel.find({})
.sort({ "result.score": "desc", "result.time": "asc" })
.limit(10);
Now because I want to show only top 10 users, I have added .limit(10).
Now in these 10 documents, there is chance that all the 10 docs are of same user i.e. same userId.
How do I prevent this and still get 10 documents with all unique userId?
I don’t want a single user to occupy all 10 slots in leaderboard.
Example: User1 has 5 docs with above schema with scores 100, 95, 92, 90, 60 User2 has 5 docs with above schema with scores 95, 92, 90, 80, 60
Expected Output is:
[
{
quizId: "....",
userId: "user1",
result: {
score: 100,
time: "some_time"
}
},
{
quizId: "....",
userId: "user2",
result: {
score: 95,
time: "some_time"
}
}
]
Advertisement
Answer
You need $group along with $max in order to aggregate the scores per user, try:
const topUsers = await QuizModel.aggregate([
{
$group: {
_id: "$userId",
score: { $max: "$result.score" }
}
},
{
$sort: { score: 1 }
},
{
$limit: 10
}
])