我正在尝试按时间戳分组名为“foo”的集合{_id,TimeStamp}
db.foos.aggregate(
[
{$group : { _id : new Date (Date.UTC({ $year : '$TimeStamp' },{ $month : '$TimeStamp' },{$dayOfMonth : '$TimeStamp'})) }}
])
期待许多日期,但结果只是一个日期。我正在使用的数据是正确的(除了1970年以外有很多foo和不同的日期)。日期解析存在一些问题,但我还无法解决。
{
"result" : [
{
"_id" : ISODate("1970-01-01T00:00:00.000Z")
}
],
"ok" : 1
}
试过这一个:
db.foos.aggregate(
[
{$group : { _id : { year : { $year : '$TimeStamp' }, month : { $month : '$TimeStamp' }, day : {$dayOfMonth : '$TimeStamp'} }, count : { $sum : 1 } }},
{$project : { parsedDate : new Date('$_id.year', '$_id.month', '$_id.day') , count : 1, _id : 0} }
])
结果:
uncaught exception: aggregate failed: {
"errmsg" : "exception: disallowed field type Date in object expression (at 'parsedDate')",
"code" : 15992,
"ok" : 0
}
那一个:
db.foos.aggregate(
[
{$group : { _id : { year : { $year : '$TimeStamp' }, month : { $month : '$TimeStamp' }, day : {$dayOfMonth : '$TimeStamp'} }, count : { $sum : 1 } }},
{$project : { parsedDate : Date.UTC('$_id.year', '$_id.month', '$_id.day') , count : 1, _id : 0} }
])
无法在结果中看到日期
{
"result" : [
{
"count" : 412
},
{
"count" : 1702
},
{
"count" : 422
}
],
"ok" : 1
}
答案 0 :(得分:18)
db.foos.aggregate(
[
{ $project : { day : {$substr: ["$TimeStamp", 0, 10] }}},
{ $group : { _id : "$day", number : { $sum : 1 }}},
{ $sort : { _id : 1 }}
]
)
按日期分组可以在聚合框架中分两步完成,如果需要排序,还需要另外的第三步来排序结果:
$project
与$substr
结合使用来自每个文档的ISODate对象的前10个字符(YYYY:MM:DD)(结果是包含字段“_id”的文档集合, “天”); $group
个小组,为每个匹配的文档添加(求和)数字1; $sort
以“_id”递增,这是前一个聚合步骤的日期 - 如果需要排序结果,这是可选的。此解决方案无法利用db.twitter.ensureIndex( { TimeStamp: 1 } )
之类的索引,因为它可以动态地将ISODate对象转换为字符串对象。对于大型集合(数百万个文档),这可能是性能瓶颈,应该使用更复杂的方法。
答案 1 :(得分:12)
这取决于您是否希望在最终输出中将日期作为ISODate类型。如果是这样,那么你可以做以下两件事之一:
从您的时间戳中提取$year
,$month
,$dayOfMonth
,然后从中重新构建一个新日期(您已尝试这样做,但您正在使用在聚合框架中不起作用的语法。)
如果原始时间戳是ISODate()类型,那么您可以进行日期算术,从时间戳中减去小时,分钟,秒和毫秒,以获得“舍入”到当天的新日期。
您将如何做1.我假设您的所有日期都是今年,但您可以轻松调整数学以适应您最早的日期。
project1={$project:{_id:0,
y:{$subtract:[{$year:"$TimeStamp"}, 2013]},
d:{$subtract:[{$dayOfYear:"$TimeStamp"},1]},
TimeStamp:1,
jan1:{$literal:new ISODate("2013-01-01T00:00:00")}
} };
project2={$project:{tsDate:{$add:[
"$jan1",
{$multiply:["$y", 365*24*60*60*1000]},
{$multiply:["$d", 24*60*60*1000]}
] } } };
示例数据:
db.foos.find({},{_id:0,TimeStamp:1})
{ "TimeStamp" : ISODate("2013-11-13T19:15:05.600Z") }
{ "TimeStamp" : ISODate("2014-02-01T10:00:00Z") }
汇总结果:
> db.foos.aggregate(project1, project2)
{ "tsDate" : ISODate("2013-11-13T00:00:00Z") }
{ "tsDate" : ISODate("2014-02-01T00:00:00Z") }
答案 2 :(得分:0)
这是我在其中一个项目中使用的内容:
collection.aggregate(
// group results by date
{$group : {
_id : { date : "$date" }
// do whatever you want here, like $push, $sum...
}},
// _id is the date
{$sort : { _id : -1}},
{$orderby: { _id : -1 }})
.toArray()
其中$ date是mongo中的Date对象。我得到按日期索引的结果。