I have the following documents:
_id: "Team 1"
count: 1200
_id: "Team 2"
count: 1170
_id: "Team 3"
count: 1006
_id: "Team 4"
count: 932
_id: "Team 5"
count: 931
_id: "Team 6"
count: 899
_id: "Team 7"
count: 895
The list is already sorted and everything, I just need to project this as an array of top 5 based on count and then the rest should be summed as ‘others’. If possible I’d like to also add the percentage that each element in the list makes up of the full count. Like this:
[
{"name":"Team 1", "count":1200, "percent":25},
{"name":"Team 2", "count":1170,"percent":15},
{"name":"Team 3", "count":1006,"percent":10},
{"name":"Team 4", "count":932,"percent":5},
{"name":"Team 5", "count":931,"percent":5},
{"name":"Other", "count":1794, "percent":40}]
]
3
Answers
Query
$setWindowFields
to sort and add the sort-rank to each documentnull
with 3 accumulators$map
to divide the counts with the total sum for the 5 top documents, to get the percentage alsoPlaymongo (put the mouse at the end of each stage to see the stage in and out)
If you have mongoDB version 5.0 or higher you can use
$setWindowFields
like in @Takis nice answer. Otherwise, you cangroup
,$slice
and$reduce
your way to the answer:$sort
to have the highest count on top and group to put them all in one array calledall
and to$sum
up.$slice
theall
array to keep only the top N.$reduce
the top N to sum them up.others
to the top N array with countsum-sum(topN)
$unwind
and formatPlayground example
another way to do it using
$facet
since$setWindowFields
only works with mongodb v5 or latermongoPlayground