I am trying to pull out documents with highest mark for a student in a collection and formed a query below:
{ name: "Person1", marks: 20 }
{ name: "Person2", marks: 20 }
{ name: "Person1", marks: 30 }
{ name: "Person1", marks: 25 }
{ name: "Person2", marks: 50 }
{ name: "Person1", marks: 90 }
{ name: "Person3", marks: 990 }
An my query:
db.mytest1.aggregate( [
{ $sort : { "name" : 1,"marks" : -1} },
{$group:
{
_id: "$name",
name: { $first: "$name" },
marks: { $first: "$marks" }
}}
])
Is there a better way to do this?
And if my scenario was to number the documents based on marks, how can I achieve it?
I'd like to get the following result:
{ name: "Person1", marks: 90, rank: 1 }
{ name: "Person1", marks: 30, rank: 2 }
{ name: "Person1", marks: 25, rank: 3 }
{ name: "Person1", marks: 20, rank: 4 }
{ name: "Person2", marks: 50, rank: 1 }
{ name: "Person2", marks: 20, rank: 2 }
{ name: "Person3", marks: 990, rank: 3 }
Starting in Mongo 5
, it's a perfect use case for the new $setWindowFields
aggregation operator:
// { name: "Person1", marks: 20 }
// { name: "Person2", marks: 20 }
// { name: "Person1", marks: 30 }
// { name: "Person1", marks: 25 }
// { name: "Person2", marks: 50 }
// { name: "Person1", marks: 90 }
// { name: "Person3", marks: 990 }
db.collection.aggregate([
{ $setWindowFields: {
partitionBy: "$name",
sortBy: { marks: -1 },
output: { rank: { $denseRank: {} } }
}}
])
// { name: "Person1", marks: 90, rank: 1 }
// { name: "Person1", marks: 30, rank: 2 }
// { name: "Person1", marks: 25, rank: 3 }
// { name: "Person1", marks: 20, rank: 4 }
// { name: "Person2", marks: 50, rank: 1 }
// { name: "Person2", marks: 20, rank: 2 }
// { name: "Person3", marks: 990, rank: 1 }
For each name (partitionBy: "$name"
), this:
sortBy: { marks: -1 }
rank
field in each document (output: { rank: { $denseRank: {} } }
)
rank: { $denseRank: {} }
.
$denseRank
and $rank
.window
)
window
parameter that we ignored as its default value is what we need here).If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With