Kepler
Kepler

Reputation: 129

How can i add new field to Mongo aggregate result?

I have following mongodb aggregate query,that group by date (1-05-2017 to 1-13-2017)

CampaignActivity.aggregate([
        {
        "$match": {
            "$and":[{updatedAt: {$lt: new Date('1-13-2017')}},{updatedAt: {$gte: new Date('1-05-2017')}}]
        }
    },
    {
        "$project" :
        {
           _id : 0,
           "datePartDay" : {"$concat" : [
               {"$substr" : [{"$dayOfMonth" : "$updatedAt"}, 0, 2]}, "-",
               {"$substr" : [{"$month" : "$updatedAt"}, 0, 2]}, "-",
               {"$substr" : [{"$year" : "$updatedAt"}, 0, 4]}
          ] },
          "isdelivered": {"$cond": { if: { $eq: [ "$delivered", true ] }, then: 1, else: 0 }},
          "isclicked": {"$cond": { if: { $eq: [ "$clicked", true ] }, then: 1, else: 0 }},
          "isunsubscribe": {"$cond": { if: { $eq: [ "$unsubscribed", true ] }, then: 1, else: 0 }}

        }
    },

    { "$group" :
        { "_id" : "$datePartDay",
          "delivered" : { "$sum" :'$isdelivered' }, 
          "clicked" : { "$sum" :'$isclicked' }, 
          "unsubscribed" : { "$sum" :'$isunsubscribe' } 
        }
    }
    ],function (err, result) {
        if (err) {
            console.log(err);
        } else {
            console.log(result);
        }
    });

Aggregate result :

 [
       {
         "_id": "12-1-2017",
         "delivered": 0,
         "clicked": 1,
         "unsubscribed": 1
       },
       {
         "_id": "11-1-2017",
         "delivered": 2,
         "clicked": 1,
         "unsubscribed": 0
       }
   ]

Upvotes: 4

Views: 11177

Answers (3)

AlexZeDim
AlexZeDim

Reputation: 4352

arr.map is good, but there is a better way to achieve the same result via $addFields, just insert code below right after $group stage

{ $group :
    { _id : "$datePartDay",
        delivered : { "$sum" :'$isdelivered' }, 
        clicked : { "$sum" :'$isclicked' }, 
        unsubscribed : { "$sum" :'$isunsubscribe' } 
    }
}
{ $addFields: 
    { 
        date: new Date() 
    }
}

And you'll receive:

[
   {
     "_id": "12-1-2017",
     "delivered": 0,
     "clicked": 1,
     "unsubscribed": 1
     "date": 2018-02-17T06:12:53.538Z
   },
   {
     "_id": "11-1-2017",
     "delivered": 2,
     "clicked": 1,
     "unsubscribed": 0
     "date": 2018-02-17T06:12:53.538Z
   }
]

Upvotes: 3

s7vr
s7vr

Reputation: 75924

The $project stage you've is redundant. You can easily move all that logic to $group stage and finish with $project stage to reformat your response.

Something like this below.

[{
    "$match": {
        "$and": [{
            updatedAt: {
                $lt: new Date('1-13-2017')
            }
        }, {
            updatedAt: {
                $gte: new Date('1-05-2017')
            }
        }]
    }
}, {
    "$group": {
        "_id": {
            $dateToString: {
                format: "%m-%d-%Y",
                date: "$updatedAt"
            }
        },
        "delivered": {
            $sum: {
                "$cond": {
                    if: {
                        $eq: ["$delivered", true]
                    },
                    then: 1,
                    else: 0
                }
            }
        },
        "clicked": {
            $sum: {
                "$cond": {
                    if: {
                        $eq: ["$clicked", true]
                    },
                    then: 1,
                    else: 0
                }
            }
        },
        "unsubscribed": {
            $sum: {
                "$cond": {
                    if: {
                        $eq: ["$unsubscribed", true]
                    },
                    then: 1,
                    else: 0
                }
            }
        }
    }
}, {
    "$project": {
        "_id": 0,
        "date": "$_id",
        "delivered": 1,
        "clicked": 1,
        "unsubscribed": 1
    }
}]

Upvotes: 8

Carolina
Carolina

Reputation: 457

It's possible.

I will show you my way to do that:

function (err, res) {             
    if (err) {
      console.log(err);
    } else {
        console.log(res);
        var result = res.map(function(item) {
                  var jsonValue = {};
                  jsonValue["_id"] = item._id;
                  jsonValue["delivered"]= item.delivered;
                  jsonValue["clicked"]  = item.clicked;
                  // You can add what you want
                  jsonValue["date"]  = new Date();
                  return  jsonValue;
        }
    }     
}

Upvotes: 1

Related Questions