MongoDB Aggregation: How do I recombine a date using $project?

mongodb, mongoose

Solution

Assuming that, as you are grouping documents by year, month and day, hours and minutes are useless, you can use one of those operators to get a date sample: `$first`, `$last`, `$min` or `$max`.

Sentiment.aggregate([
    {
        $match: { 'content.term' : term_id }
    }, {
        $group: {
            _id: {
                year       : { $year       : '$created_at' },
                month      : { $month      : '$created_at' },
                dayOfMonth : { $dayOfMonth : '$created_at' },
            },
            dt_sample : { $first : '$created_at' },
            sum   : { $sum : '$score'},
            count : { $sum : 1 }
        },
    }, {
        $project: {
            _id   : 0,
            date  : '$dt_sample',
            sum   : 1,
            count : 1,
            avg   : { $divide: ['$sum', '$count'] }
        }
    }
], function(err, result){
    if(err) callback(err);
    else callback(null, result);
});

You'll have a date field with an arbitrary hour, minute and seconds.

Problem

I'm trying to aggregate my data by day so I can render it in a chart. I've managed to do this successfully by grouping by `$year`, `$month`, and `$dayOfMonth`. However, that means that my date is now split into three parts in the final result. Is there a way to concat the three numbers back into a date format or is there another way to group by day that doesn't split date? Below is a working example of what I have: ``` Sentiment.aggregate([ { $match: { 'content.term' : term_id } }, { $group: { _id: { year : { $year : '$created_at' }, month : { $month : '$created_at' }, dayOfMonth : { $dayOfMonth : '$created_at' }, }, sum : { $sum : '$score'}, count : { $sum : 1 } }, }, { $project: { _id : 0, date : '$_id', sum : 1, count : 1, avg : { $divide: ['$sum', '$count'] } } } ], function(err, result){ if(err) callback(err); else callback(null, result); }); ``` And here is a sample result: ``` [ { "sum": 201, "count": 3, "date": { "year": 2013, "month": 7, "dayOfMonth": 5 }, "avg": 67 }, { "sum": 186, "count": 6, "date": { "year": 2013, "month": 7, "dayOfMonth": 8 }, "avg": 31 }, { "sum": 834, "count": 9, "date": { "year": 2013, "month": 7, "dayOfMonth": 9 }, "avg": 92.66666666666667 } ] ``` Ideally, I'd like to have `date` be a valid date so I don't have to convert it later. I've tried using `$concat` but that only works with strings. I am using `Mongoose` if that makes a difference.

Original source