我有一个如下文档,现在我想按频道,年份和月份以及日期分组,然后我想选择当前日期的记录。这是我的文件:
{
"_id" : ObjectId("56de5eab29f9463baf6eb7d2"),
"created_at" : ISODate("2016-03-08T05:10:03.854Z"),
"updated_at" : ISODate("2016-03-08T05:10:03.854Z"),
"channel" : "040403",
"countrycode" : "IN",
"distinctid" : "abc123456",
"os" : "Android"
}
我写了这样的聚合:
db.collection.aggregate([
{$project: {
"channel":"$channel",
"year": {$year: "$created_at" },
"month: {$month: "$created_at" },
"day": {$dayOfMonth: "$created_at" }
},
{$match: {
"year": new Date().getFullYear(),
"month": new Date().getMonth() + 1,
"day": new Date().getDate()
},
{$group:
{{"_id":{"channel":"$channel",
year: {$year: "$created_at" },
month: {$month: "$created_at" },
day: {$dayOfMonth: "$created_at" }},
"count":{"$sum":1}
}
}
]
)
然而,它说
缺失:属性id @(shell)之后:1:108
这是我的想法是正确的,为什么语法错了? 感谢
答案 0 :(得分:1)
取消初始$project
并使用$match
上的“范围”代替:
// Get current start of day and start of tomorrow
var now = Date.now(),
oneDay = ( 1000 * 60 * 60 * 24 ),
today = new Date( now - ( now % oneDay ) ),
tomorrow = new Date( today.valueOf() + oneDay );
db.collection.aggregate([
// Match on range
{ "$match": {
"$created_at": {
"$gte": today, "$lt": tomorrow
}
}},
// Then group on just the rolled up date
{ "$group": {
"_id":{
"channel":"$channel",
"year": { "$year": "$created_at" },
"month": { "$month": "$created_at" },
"day": { "$dayOfMonth": "$created_at" }
},
"count":{"$sum":1}
}}
])
使用$gte
和$lt
的“范围”是最有效的选择。如果您尝试首先使用$project
提取组件,那么这实际上是通过所有数据“完全通过”来计算这些值。只有在完成所有工作后才能实际选择所需的文件。
当$match
是第一阶段时,所有过滤都已完成,留下的文档更少,结果更快。更重要的是,作为一个“查询”,在初始阶段,这是唯一的机会你的处理必须使用“索引”来加快速度。所以最好抓住这个机会。
并不是说每天只有一天选择时,每天的分组确实为你做了什么,但是当你需要一系列日期时,它总是技术。是的,“单一”日仍然一个“范围”。
至于你试过的是什么问题?很多事情,但最明显的是在第一阶段没有使用$match
。
您真正需要记住的其他事情是$project
和$group
等“输出”来自源的文档的更改表示。因此,“out”出现的是后续“管道”阶段可用的所有内容,依此类推。认为“unix pipe”|
带有命令,并且最好类比了解每个管道阶段与另一个管道阶段的关系。即:
ps -ef | grep mongo | tee output.txt
答案 1 :(得分:0)
您的查询存在两个问题:
}
。Integer
类型(year
类型(month
,day
,$year
)的字段进行分组,但您应用了聚合运算符($month
,{期待$day
字段的{1}},Date
}。请尝试此查询:
db.collection.aggregate([{
$project: {
"channel": "$channel",
"year": { $year: "$created_at" },
"month": { $month: "$created_at" },
"day": { $dayOfMonth: "$created_at" }
}
}, {
$match: {
"year": new Date().getFullYear(),
"month": new Date().getMonth() + 1,
"day": new Date().getDate()
}
}, {
$group: {
"_id": { "channel": "$channel", year: "$year", month: "$month", day: "$day" },
"count": { "$sum": 1 }
}
}]);