我在mongo中有一些看起来像这样的文档:
{
_id : ObjectId("..."),
"make" : "Nissan",
..
},
{
_id : ObjectId("..."),
"make" : "Nissan",
"saleDate" : ISODate("2013-04-10T12:39:50.676Z"),
..
}
理想情况下,我希望能够计算出每天销售的车辆数量 . 然后,我想要查看今天,或者像过去七天这样的窗口 .
我能用一些丑陋的代码完成日常视图
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 } } }
)
然后产生结果
{
"result" : [
{
"_id" : {
"make" : "Nissan",
"saleDayOfMonth" : 10
},
"cnt" : 2
},
{
"_id" : {
"make" : "Toyota",
"saleDayOfMonth" : 10
},
"cnt" : 4
},
],
"ok" : 1
}
所以这没关系,但我更希望不必更改查询中的两个日期时间值 . 然后,正如我上面提到的,我希望能够运行此查询(再次,无需每次都修改它),并查看在过去一周内按天分类的相同结果 .
哦,这是我一直用于查询的示例数据
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")});
凯文,提前谢谢
3 回答
在Mongo 2.8 RC2中有一个新的数据聚合运算符:$dateToString可用于按日分组,结果只有"YYYY-MM-DD":
文档中的示例:
将导致:
UPDATE 更新后的答案基于3.6中的日期功能,并显示如何在没有销售的范围内包含日期(包括我在内的任何原始答案中未提及) .
样本数据:
将
startDate
和endDate
定义为变量并在聚合中使用它们:在样本数据上,这给出了结果:
这个聚合也可以用两个
$group
阶段和一个简单的$project
而不是$group
和一个复杂的$project
来完成 . 这里是:相同的结果:
基于2.6的原始答案:
您可能需要查看我的博客文章,了解如何在Aggregation Framework _745757中处理各种日期操作 .
您可以做的是使用
$project
阶段将日期截断为每日解析,然后对整个数据集(或仅部分)进行聚合,并按日期和制作进行聚合 .根据您的样本数据,假设您想知道今年按日期销售的汽车数量:
现在运行聚合为您提供:
您可以添加另一个{$ project}阶段以完成输出,并且您可以添加{$ sort}步骤,但基本上对于每个日期,对于每个日期,您可以计算出已售出的数量 .
我喜欢user1083621的答案,但该方法在使用该字段的后续操作中会产生一些限制 - 因为您不能在(例如)下一个聚合管道阶段中将其用作日期字段 . 你既不能比较也不能使用任何date aggregation operations,并且在聚合后你会因为通过灌浆阶段保留它而遇到一些困难 . 毕竟,有时候你只想在一天的开始时操纵,而不是随意的一天 . 所以这是我的方法:
它给你这个:
不能说它是否比user1083621的方法更快 .