Dan*_*yle 5 mongodb pymongo aggregation-framework
如何通过ObjectId日期汇总我的MongoDB结果.例:
默认光标结果:
cursor = [
{'_id': ObjectId('5220b974a61ad0000746c0d0'),'content': 'Foo'},
{'_id': ObjectId('521f541d4ce02a000752763a'),'content': 'Bar'},
{'_id': ObjectId('521ef350d24a9b00077090a5'),'content': 'Baz'},
]
Run Code Online (Sandbox Code Playgroud)
预计结果:
projected_cursor = [
{'2013-09-08':
{'_id': ObjectId('5220b974a61ad0000746c0d0'),'content': 'Foo'},
{'_id': ObjectId('521f541d4ce02a000752763a'),'content': 'Bar'}
},
{'2013-09-07':
{'_id': ObjectId('521ef350d24a9b00077090a5'),'content': 'Baz'}
}
]
Run Code Online (Sandbox Code Playgroud)
这就是我目前在PyMongo中用来实现这些结果的方法,但它很混乱,我想看看如何使用MongoDB的聚合框架(甚至MapReduce)来实现它:
cursor = db.find({}, limit=10).sort("_id", pymongo.DESCENDING)
messages = [x for x in cursor]
this_date = lambda x: x['_id'].generation_time.date()
dates = set([this_date(message) for message in messages])
dates_dict = {date: [m for m in messages if this_date(m) == date] for date in dates}
Run Code Online (Sandbox Code Playgroud)
是的,我知道最简单的方法是简单地为每条记录添加一个新的日期字段,然后再按此汇总,但这不是我现在想要做的.
谢谢!
没有办法用mongodb的聚合框架来完成你所要求的,因为没有聚合运算符可以将ObjectId变成类似日期的东西(尽管有JIRA票证).您应该能够使用map-reduce完成您想要的任务,但是:
// map function
function domap() {
// turn ObjectId --> ISODate
var date = this._id.getTimestamp();
// format the date however you want
var year = date.getFullYear();
var month = date.getMonth();
var day = date.getDate();
// yields date string as key, entire document as value
emit(year+"-"+month+"-"+day, this);
}
// reduce function
function doreduce(datestring, docs) {
return {"date":datestring, "docs":docs};
}
Run Code Online (Sandbox Code Playgroud)
llovett指出的Jira Ticket已得到解决,因此现在您可以使用和等日期运算符从$isoWeek$yearObjectId.
您的聚合看起来像这样:
{
"$project":
{
"_id": {
"$dateFromParts" : {
"year": { "$year": "$_id"},
"month": { "$month": "$_id"},
"day": { "$dayOfMonth": "$_id"}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)