MongoDB aggregate within daily grouping

aggregation-framework, mongodb, mongodb-query

Solution

In Mongo 2.8 RC2 there is a new data aggregation operator: $dateToString which can be used to group by a day and simply have a "YYYY-MM-DD" in the result:

Example from the documentation:

db.sales.aggregate(
  [
     {
         $project: {
                yearMonthDay: { $dateToString: { format: "%Y-%m-%d", date: "$date" } },
                time: { $dateToString: { format: "%H:%M:%S:%L", date: "$date" } }
         }
     }
  ]
)

will result in:

{ "_id" : 1, "yearMonthDay" : "2014-01-01", "time" : "08:15:39:736" }

Problem

I have some docs in mongo that looks something like this: ``` { _id : ObjectId("..."), "make" : "Nissan", .. }, { _id : ObjectId("..."), "make" : "Nissan", "saleDate" : ISODate("2013-04-10T12:39:50.676Z"), .. } ``` Ideally, I'd like to be able to count, by make, the number of vehicles sold per day. I'd then like to view either today, or a window such as today through the last seven days. I was able to accomplish the daily view with some ugly code ``` db.inventory.aggregate( { $match : { "saleDate" : { $gte: ISODate("2013-04-10T00:00:00.000Z"), $lt: ISODate("2013-04-11T00:00:00.000Z") } } } , { $group : { _id : { make : "$make", saleDayOfMonth : { $dayOfMonth : "$saleDate" } }, cnt : { $sum : 1 } } } ) ``` Which then yields the results ``` { "result" : [ { "_id" : { "make" : "Nissan", "saleDayOfMonth" : 10 }, "cnt" : 2 }, { "_id" : { "make" : "Toyota", "saleDayOfMonth" : 10 }, "cnt" : 4 }, ], "ok" : 1 } ``` So that is ok, but I would much prefer to not have to change the two datetime values in the query. Then, as I mentioned above, I'd like to be able to run this query (again, without having to modify it each time) and see the same results binned by day over the last week. Oh and here is the sample data I've been using for the query ``` db.inventory.save({"make" : "Nissan","saleDate" : ISODate("2013-04-10T12:39:50.676Z")}); db.inventory.save({"make" : "Nissan"}); db.inventory.save({"make" : "Nissan","saleDate" : ISODate("2013-04-10T11:39:50.676Z")}); db.inventory.save({"make" : "Toyota","saleDate" : ISODate("2013-04-09T11:39:50.676Z")}); db.inventory.save({"make" : "Toyota","saleDate" : ISODate("2013-04-10T11:38:50.676Z")}); db.inventory.save({"make" : "Toyota","saleDate" : ISODate("2013-04-10T11:37:50.676Z")}); db.inventory.save({"make" : "Toyota","saleDate" : ISODate("2013-04-10T11:36:50.676Z")}); db.inventory.save({"make" : "Toyota","saleDate" : ISODate("2013-04-10T11:35:50.676Z")}); ``` Thanks in advance, Kevin

Original source

Related problems