Reputation: 129
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
}
]
Is it possible to add new fields to result that no exist in collection something like "date"?
Is it possible to add missing date fields with dummy data?
Upvotes: 4
Views: 11177
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
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
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