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) 

1 Answer 1

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)
    });
};
Sign up to request clarification or add additional context in comments.

Comments

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.