Aggregation Framework on Date

I'm trying to aggregate datas by Date in Mongo, but I can't quite achieve what I want. Right now, I'm using this:

db.aggregData.aggregate( { $group: {_id: "$Date".toString(),  
                                   tweets: { $sum: "$CrawledTweets"} } }, 
                         { $match:{ _id: {$gte: ISODate("2013-03-19T12:31:00.247Z") }}}, 
                         { $sort: {Date:-1} } 
                       )

It results with this:

"result" : [
                {
                        "_id" : ISODate("2013-03-19T12:50:00.641Z"),
                        "tweets" : 114
                },
                {
                        "_id" : ISODate("2013-03-19T12:45:00.631Z"),
                        "tweets" : 114
                },
                {
                        "_id" : ISODate("2013-03-19T12:55:00.640Z"),
                        "tweets" : 123
                },
                {
                        "_id" : ISODate("2013-03-19T12:40:00.628Z"),
                        "tweets" : 91
                    },
                {
                        "_id" : ISODate("2013-03-19T12:31:00.253Z"),
                        "tweets" : 43
                },
                {
                        "_id" : ISODate("2013-03-19T13:20:00.652Z"),
                        "tweets" : 125
                },
                {
                        "_id" : ISODate("2013-03-19T12:31:00.252Z"),
                        "tweets" : 30
                }
 ],
        "ok" : 1

It seems to do the job, but with further inspection, we see that there is repetition:
ISODate("2013-03-19T12:31:00.253Z") and ISODate("2013-03-19T12:31:00.252Z").
The only thing that changes is the last bit before the Z.

So here is my question. What is this part ? And how can I do to ignore it in the aggregation ?

Thank you in advance.

EDIT: I wanna aggregate by date, so whole year/month/day + hour and minute. I don't care of the rest.

EDIT: My db in on mongolab, so I'm on 2.2

Well, I did it another way: I save all my date with seconds/milliseconds at 0. So I can keep a simple aggregate, with not a little more code server side, thanks to moment.js

You are trying to aggregate by "whole" date, in other words to drop the time from ISODate(), right? There are several ways to do it, I describe them in detail on my blog in the post called

Stupid Date Tricks with Aggregation Framework.

You can see the full step-by-step breakdown there, but to summarize you have two choices:

  • if you don't care about the aggregated-on value to be an ISODate() then you can use the {$year}, {$month} and {$dayOfMonth} operators in {$project} phase to pull out just Y-M-D to then {$group} on.

  • if you do care about the grouped-on value staying an ISODate you can {$subtract} the time part in {$project} phase and be left with ISODate() type - the caveat is that this method requires MongoDB 2.4 (just released) which adds support for date arithmetic and for $millisecond operator (see exact code in the blog post).

Here is probably what you want:

db.aggregData.aggregate([
  { 
    $project:{ 
        CrawledTweets: 1,
        newDate: { 
            year:{$year:"$Date"}, 
            month: {$month:"$Date"}, 
            day: {$dayOfMonth:"$Date"}, 
            hour: {$hour: "$Date"}, 
            min: {$minute: "$Date"}
        }   
    }   
  },
  { 
    $group: {
        _id: "$newDate",
        tweets: { $sum: "$CrawledTweets"}
    }   
  }
])

Without being a Mongo expert and without knowing your db fields I'd come up with something like this. Perhaps you can build upon this:

db.aggregData.aggregate(
{ 
    $project:{ 
        CrawledTweets: 1,
        groupedTime: { 
            year:{$year:"$_id"}, 
            month: {$month:"$_id"}, 
            day: {$dayOfMonth:"$_id"}, 
            hour: {$hour: "$_id"}, 
            min: {$minute: "$_id"}
        }   
    }   
},
{ 
    $group: {
        _id: { groupedTime: "$CrawledTweets" },
        tweets: { $sum: "$tweets"}
    }   
}
)

You can now use the MongoDB date aggregation operators, I have a post on my blog that goes over the Schema setup, using it in Node.js, etc:

http://smyl.es/how-to-use-mongodb-date-aggregation-operators-in-node-js-with-mongoose-dayofmonth-dayofyear-dayofweek-etc/