1

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?

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Replace those two 'obj' references with 'doc' and it's a winner!
@Drew So bad of me. That will teach me to cut/paste from a reference scipt I am working on. Fixed now. Good catch

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.