Search code examples
mongodbmongo-shell

Aggregate (group by) query in MongoDB by 2 fields


I am using MongoDB. My collection object structure is like the following:

{
"_id" : ObjectId("5a58800acebcda57188bf0aa"),
"title" : "Article title",
"categories" : "politics",
"url" : "https://example.com",
"article_date" : ISODate("2018-01-11T10:00:00.000Z"),
"content" : "content here..."
},
{
"_id" : ObjectId("5a58800acebcda57188bf0aa"),
"title" : "Article title 2",
"categories" : "economics",
"url" : "https://example.com",
"article_date" : ISODate("2018-01-12T10:00:00.000Z"),
"content" : "content here..."
}

Articles are publishing each day and I have many categories. How can I group the data by date and count documents by specific category, for example:

{
 "date": ISODate("2018-01-11T10:00:00.000Z"),
 "result": [{
     "category": "politics",
     "count": 2
  }, {
    "category": "economics",
    "count": 1
 }]
},
{
 "date": ISODate("2018-01-12T10:00:00.000Z"),
 "result": [{
     "category": "politics",
     "count": 2
  }, {
    "category": "economics",
    "count": 1
 }]
}

Thank you in advance


Solution

  • you need to $group twice to get the result, first by article_date and categories then $group on article_date

    db.art.aggregate([
        {$group : {
            _id : {article_date : "$article_date", categories : "$categories"},
            count : {$sum : 1}
        }},
        {$group : {
            _id : {article_date : "$_id.article_date"},
            result : {$push : {category : "$_id.categories", count : "$count"}}
        }},
        {$addFields :{
            _id : "$_id.article_date"
        }}
    ]).pretty()
    

    result for sample data in question

    {
        "_id" : ISODate("2018-01-11T10:00:00Z"),
        "result" : [
            {
                "category" : "politics",
                "count" : 1
            }
        ]
    }
    {
        "_id" : ISODate("2018-01-12T10:00:00Z"),
        "result" : [
            {
                "category" : "economics",
                "count" : 1
            }
        ]
    }