hhs
hhs

Reputation: 714

how to populate map-reduced result

TestSessionSchema.statics.getTopTesters = function(callback){
    var o = {};
    o.map = function(){
        emit(this._customer, this.points);
    };

    o.reduce = function(_customer, values){
        var result = {_customer: _customer, sum_points: 0, };
        values.forEach(function(point){
            result.sum_points += point;
        });
        return result;
    };

    o.out = { replace: 'createdCollectionNameForResults' };
    o.verbose = true;

    this.mapReduce(o,function(err, model, stats){
        model.find().sort({'value.sum_points': "desc"}).limit(5).populate("_customer").exec(function(error, results){

            log(results);

        })
    });

}

In map-reduce part I am geting _customers' points.

Now i want to populate _customer to get customers' info model.find().sort({'value.sum_points': "desc"}).limit(5).populate("_customer") does not work

how can I do it?

Upvotes: 1

Views: 715

Answers (1)

Asya Kamsky
Asya Kamsky

Reputation: 42352

When you do mapReduce in MongoDB, you must make sure that your emit value has the same format as your reduce return value.

That means in your case that if map calls emit(customer, points) then reduce must return simply the value for points.

To change your specific example, your map function is okay, but your reduce function should be:

reduce = function(_customer, values) {
        var result =  0;
        values.forEach(function(point){
            result += point;
        });
        return result;
    };

Your reduce function would then sum up all of the values (points) for each _customer, which is what you want. The output would be _customer, point as key-value pairs with field names _id and value where value would be the sum of all the point values for that _id (_customer).

To query the result you would run:

db.createdCollectionNameForResults.find().sort({value:-1}).limit(5)

Upvotes: 1

Related Questions