Javascript作用域规则和mongo map / reduce函数

我想制作一些在mongo中执行参数化map / reduce作业的javascript函数,但我对JavaScript的范围设置感到困惑.例如,以下代码给出了“性别”变量的计数;即它会告诉我有多少“男性”和“女性”记录:

// count categories
db.responses.mapReduce(
    function(){
        emit(this["gender"], {count: 1})
    }, function(state, values){
        var result = {count: 0};
        values.forEach(function(value) {
            result.count += value.count;
        });
        return result;
    }, {out: { inline : 1}}
);

这完全没问题.在下一步中,我想创建一个为任意属性执行此操作的函数

function countCategories(item) { 
    function mapper(it){
        fn = function(){
            if(this[it]){
                emit(this[it], {count: 1});
            }
        };
        return fn;
    }(item); 
    var reducer = function(state, values){
        var result = {count: 0};
        values.forEach(function(value) {
            result.count += value.count;
        });
        return result;
    };
    var out = {out: { inline : 1}};
    var results = db.responses.mapReduce(
        mapper, 
        reducer, 
        out
    );
    return results;
}   

countCategories("gender")

但是,当我尝试:

countCategories("gender")
{
    "results" : [ ],
    "timeMillis" : 48,
    "counts" : {
        "input" : 2462,
        "emit" : 0,
        "reduce" : 0,
        "output" : 0
    },
    "ok" : 1,
}

从未调用emit函数.这里出了什么问题?我的猜测是mongo提供的emit函数的范围,但我不确定为什么它没有被调用,也没有抛出错误.

解决方法:

从我在the docs中读到的内容,数据库命令中使用的函数范围不是它们的默认javascript范围,但可以(并且必须,如果需要)手动设置.所以,它认为这应该工作:

var mapper = function(){
    if(item in this){
        emit(this[item], {count: 1});
    }
};
...
db.responses.mapReduce(
    mapper, 
    reducer, 
    {
       out: {"inline": 1},
       scope: {"item": item}
    }
);
上一篇:javascript – Mongoose为同一个集合组合了两个查询


下一篇:javascript – Mongoose 4.x“model.update()”回调已更改