Aggregate MongoDB Results by ObjectId Date

How can I aggregate my MongoDB results by ObjectId date. Example:

Default cursor results:

cursor = [ {'_id': ObjectId('5220b974a61ad0000746c0d0'),'content': 'Foo'}, {'_id': ObjectId('521f541d4ce02a000752763a'),'content': 'Bar'}, {'_id': ObjectId('521ef350d24a9b00077090a5'),'content': 'Baz'}, ] 

Projected Results:

 projected_cursor = [ {'2013-09-08': {'_id': ObjectId('5220b974a61ad0000746c0d0'),'content': 'Foo'}, {'_id': ObjectId('521f541d4ce02a000752763a'),'content': 'Bar'} }, {'2013-09-07': {'_id': ObjectId('521ef350d24a9b00077090a5'),'content': 'Baz'} } ] 

This is what I use in PyMongo to achieve these results, but it is messy, and I would like to see how I can do this using the MongoDB (or even MapReduce) aggregation structure:

 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} 

And yes, I know that the easiest way would be to simply add a new date field to each record and then fill it out, but that’s not what I want to do right now.

Thanks!

+4
source share
2 answers

So, this does not answer my question directly, but I found a better way to replace all this lambda nonsense above using Python setdefault :

 d = {} for message in messages: key = message['_id'].generation_time.date() d.setdefault(key,[]).append(message) 

Thanks @raymondh for the tip in PyCon:

Convert code to beautiful, idiomatic Python

+1
source

It is not possible to fulfill what you are asking for with mongodb's aggregation structure, since there is no aggregation operator that can turn ObjectId into something dated (there is a JIRA ticket ). You should be able to accomplish what you want using map-reduce, however:

 // 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}; } 
+7
source

Source: https://habr.com/ru/post/1501239/


All Articles