I'd like to get percentages from a group pipeline in a MongoDB aggregate.
My data:
{
_id : 1,
name : 'hello',
type : 'big'
},
{
_id : 2,
name : 'bonjour',
type : 'big'
},
{
_id : 3,
name : 'hi',
type : 'short'
},
{
_id : 4,
name : 'salut',
type : 'short'
},
{
_id : 5,
name : 'ola',
type : 'short'
}
My request group by type, and count:
[{
$group : {
_id : {
type : '$type'
},
"count" : {
"$sum" : 1
}
}
}]
Result:
[
{
_id {
type : 'big',
},
count : 2
},
{
_id {
type : 'short',
},
count : 3
}
]
But I'd like to have count AND percentage, like that:
[
{
_id {
type : 'big',
},
count: 2,
percentage: 40%
},
{
_id {
type : 'short',
},
count: 3,
percentage: 60%
}
]
But I've no idea how to do that. I've tried $divide
and other things, but without success. Could you please help me?
The $group stage separates documents into groups according to a "group key". The output is one document for each unique group key. A group key is often a field, or group of fields. The group key can also be the result of an expression.
MongoDB aggregate $count element in array In this topic, you will learn to count the elements in the array from the MongoDB collection. For this, MongoDB provides the $size aggregation to count and returns the total number of items in an array.
Unless you're stuck with legacy code, it makes sense to migrate to the aggregation framework. Comparing MySQL 8.0 and MongoDB 4.0. 3, it was seen that MongoDB is typically faster on more complex queries. It's faster from disk when there are no indexes, whereas MySQL is faster from RAM.
Well I think percentage
should be string if the value contains %
First get you will need to count
the number of document.
var nums = db.collection.count();
db.collection.aggregate(
[
{ "$group": { "_id": {"type": "$type"}, "count": { "$sum": 1 }}},
{ "$project": {
"count": 1,
"percentage": {
"$concat": [ { "$substr": [ { "$multiply": [ { "$divide": [ "$count", {"$literal": nums }] }, 100 ] }, 0,2 ] }, "", "%" ]}
}
}
]
)
Result
{ "_id" : { "type" : "short" }, "count" : 3, "percentage" : "60%" }
{ "_id" : { "type" : "big" }, "count" : 2, "percentage" : "40%" }
First find total number of documents in collections using count
method and used that count variable to calculate percentage
in aggregation like this :
var totalDocument = db.collectionName.count() //count total doc.
used totalDocument
in aggregation as below :
db.collectionName.aggregate({"$group":{"_id":{"type":"$type"},"count":{"$sum":1}}},
{"$project":{"count":1,"percentage":{"$multiply":[{"$divide":[100,totalDocument]},"$count"]}}})
EDIT
If you need to this in single aggregation
query then unwind
used in aggregation but using unwind
it creates Cartesian problem
check below aggregation query :
db.collectionName.aggregate({"$group":{"_id":null,"count":{"$sum":1},"data":{"$push":"$$ROOT"}}},
{"$unwind":"$data"},
{"$group":{"_id":{"type":"$data.type"},"count":{"$sum":1},
"total":{"$first":"$count"}}},
{"$project":{"count":1,"percentage":{"$multiply":[{"$divide":[100,"$total"]},"$count"]}}}
).pretty()
I recconmed first find out toatal count and used that count in aggregation as per first query.
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