3

I am trying to get a count of number of students per locality. I have a model that looks like

var mongoose = require('mongoose');
var schema = mongoose.Schema;
var studentSchema = new mongoose.Schema(
{
 "name":String,
 "address" :{
     "locality":String
  }
});
module.exports = mongoose.model('Student', studentSchema);

I then have some Node.js Code

var Student = require('../../../models/Student');
module.exports.getStudentsBasedOnLocality = function(){
var o = {};
o.map = function () {
    emit(Student.address.locality, 1)
}
o.reduce = function (k, vals) {
    return vals.length
}

Student.collection.mapReduce(o, function (err, results) {
    if(err) throw err;
    console.log(results)
})
};

The error I get is. Any tips on what I might be doing wrong?

TypeError:

Cannot read property 'out' of undefined
at Collection.mapReduce (C:\***\node_modules\mongodb\lib\collection.js:2961:21)
at NativeCollection.(anonymous function) [as mapReduce] (C:\***\node_modules\mongoose\lib\drivers\node-mongodb-native\collection.js:136:28) 
CandleCoder
  • 1,387
  • 4
  • 21
  • 45
Rahul Ganguly
  • 1,908
  • 5
  • 24
  • 36

1 Answers1

5

Try calling the mapReduce() method directly on the model, not on the collection property of the model which requires an extra object as parameter with the out property:

var Student = require('../../../models/Student');
module.exports.getStudentsBasedOnLocality = function(){
    var o = {},
        self = this;
    o.map = function () {
        emit(this.address.locality, 1)
    };
    o.reduce = function (k, vals) {
        return vals.length
    };

    Student.mapReduce(o, function (err, results) {
        if(err) throw err;
        console.log(results)
    });
};

Another alternative is to use the aggregation framework, which has better performance since aggregation runs natively in the server (C++), whereas mapReduce spawns separate javascript thread(s) to run JavaScript code. You can thus run the following aggregation pipeline to achieve the same result:

var Student = require('../../../models/Student');
module.exports.getStudentsBasedOnLocality = function(){
    var pipeline = [
        {
            "$group": {
                "_id": "$address.locality",
                "count": { "$sum": 1 }
            }
        }
    ];

    Student.aggregate(pipeline, function (err, results) {
        if(err) throw err;
        console.log(results)
    });
};
chridam
  • 100,957
  • 23
  • 236
  • 235