Mongo count occurrences of each value for a set of documents

MongodbMongodb Query

Mongodb Problem Overview


I have some documents like this:

{
  "user": '1'
},
{ "user": '1'
},
{
  "user": '2'
},
{
  "user": '3'
}

I'd like to be able to get a set of all the different users and their respective counts, sorted in decreasing order. So my output would be something like this:

{
  '1': 2,
  '2': 1,
  '3': 1
}

I think this can be done with a Mongo aggregate(), but I'm having a lot of trouble figuring out the right flow for this.

Mongodb Solutions


Solution 1 - Mongodb

You can get result (not in your required format) via aggregation

db.collection.aggregate(
   {$group : { _id : '$user', count : {$sum : 1}}}
).result

the output for your sample documents is:

"0" : {
    "_id" : "2",
    "count" : 1
},
"1" : {
    "_id" : "3",
    "count" : 1
},
"2" : {
    "_id" : "1",
    "count" : 2
}

Solution 2 - Mongodb

For anyone reading this in Jan 2019 the accepted answer does not currently work in Robo3T (returns a pipeline.length - 1 error).

You must:

a) wrap the query in a set of square brackets []

b) remove .result from the end

https://github.com/Studio3T/robomongo/issues/1519#issuecomment-441348191

Here's an update to the accepted answer by @disposer that works for me in Robo3T.

db.getCollection('collectionName').aggregate(
    [ {$group : { _id : '$user', count : {$sum : 1}}} ]
)

Solution 3 - Mongodb

With MongoDb 3.6 and newer, you can leverage the use of $arrayToObject operator and a $replaceRoot pipeline to get the desired result. You would need to run the following aggregate pipeline:

db.collection.aggregate([
    {  "$group": {
        "_id": "$user",
        "count": { "$sum": 1 }
    } },
    { "$sort": { "_id": 1 } },
    {  "$group": {
        "_id": null,
        "counts": {
            "$push": {
                "k": "$_id",
                "v": "$count"
            }
        }
    } },
    { "$replaceRoot": {
        "newRoot": { "$arrayToObject": "$counts" }
    } }    
])

which yields

{
    "1" : 2,
    "2" : 1,
    "3" : 1
}

Solution 4 - Mongodb

You can use the below aggregation query, It will also sort the results in decreasing order as desired.

db.collection.aggregate([
    { $group: { _id: "$user", count: { $sum: 1 } } },
    { $sort: { count: -1 } }
  ])

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionritmatterView Question on Stackoverflow
Solution 1 - MongodbDisposerView Answer on Stackoverflow
Solution 2 - MongodbRuben MurrayView Answer on Stackoverflow
Solution 3 - MongodbchridamView Answer on Stackoverflow
Solution 4 - MongodbRajdeep GautamView Answer on Stackoverflow