【问题标题】:mapReduce using node.js and mongoosemapReduce 使用 node.js 和猫鼬
【发布时间】:2026-01-20 04:25:01
【问题描述】:

我正在尝试计算每个地区的学生人数。 我有一个看起来像

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

然后我有一些 Node.js 代码

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)
})
};

我得到的错误是。关于我可能做错的任何提示?

类型错误

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) 

【问题讨论】:

    标签: node.js mongodb mongoose mapreduce


    【解决方案1】:

    尝试直接在模型上调用 mapReduce() 方法,而不是在模型的集合属性上调用,因为它需要一个额外的对象作为带有 out 属性的参数:

    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)
        });
    };
    

    另一种选择是使用 aggregation framework,它具有更好的性能,因为聚合在服务器 (C++) 中本机运行,而 mapReduce 生成单独的 JavaScript 线程来运行 JavaScript 代码。因此,您可以运行以下 aggregation 管道来获得相同的结果:

    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)
        });
    };
    

    【讨论】: