Reputation: 127
With documents like:
{
_id: 123,
events: {
someEvent:{
created: ISODate("2015-06-27T16:51:03.000Z"),
metadata: {
some: "thing"
}
},
anotherEvent:{
created: ISODate("2015-06-27T16:51:01.000Z"),
metadata: {
some: "thing"
}
}
}
}
This is a simplified example of the data. The events object can have between 200 and 3,000 fields. There are thousands of documents like this.
I'm looking to use mapreduce on the collection so I only return one of the events (the one with the latest 'created' date) for each document in the collection.
Is this possible?
Upvotes: 1
Views: 844
Reputation: 50426
Yes it's possible. MapReduce is a bit of a "blunt edged sword" for this, but your element structure is "not great" and a possible 3000 elements needs something like this:
db.collection.mapReduce(
function() {
var doc = this;
var plucked = Object.keys(doc.events)
.map(function(key) {
var myObj = doc.events[key];
myObj.key = key;
return myObj;
})
.sort(function(a,b) {
return ( a.created > b.created )
? -1 : ( a.created < b.created )
? 1 : 0;
})[0];
emit(this._id, plucked);
},
function() {},
{ "out": { "inline": 1 } }
);
So basically that cylces though "events" and reshapes the data somewhat. Then you .sort()
on the "created" key of the results in "descencing order" and just pull the first array element.
The "reducer" does nothing here. But this is just a way for the server to do the filtering.
Upvotes: 2