Javascript范围规则和mongo映射/减少函数
我想在mongo中创建一些javascript函数来执行参数映射/减少作业,但我对javascript的作用域感到困惑。例如,下面的代码给出了Javascript范围规则和mongo映射/减少函数,javascript,node.js,mongodb,closures,mongoose,Javascript,Node.js,Mongodb,Closures,Mongoose,我想在mongo中创建一些javascript函数来执行参数映射/减少作业,但我对javascript的作用域感到困惑。例如,下面的代码给出了“gender”变量的计数;i、 e.它会告诉我我有多少“男性”和“女性”记录: // count categories db.responses.mapReduce( function(){ emit(this["gender"], {count: 1}) }, function(state, values){
“gender”
变量的计数;i、 e.它会告诉我我有多少“男性”
和“女性”
记录:
// 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
函数的作用域,但我不太清楚为什么它没有被调用,也没有抛出错误。从我所读到的内容来看,在数据库命令中使用的函数的作用域不是默认的javascript作用域,而是可以(并且必须,如果需要)手动设置的。因此,它认为这应该有效:
var mapper = function(){
if(item in this){
emit(this[item], {count: 1});
}
};
...
db.responses.mapReduce(
mapper,
reducer,
{
out: {"inline": 1},
scope: {"item": item}
}
);
我认为你在mapper的声明中有一个问题: 您的代码:
function mapper(it){
fn = function(){
if(this[it]){
emit(this[it], {count: 1});
}
};
return fn;
}(item);
由于JavaScript语法/提升/分号插入的内容,等价于:
function mapper(it){
fn = function(){
if(this[it]){
emit(this[it], {count: 1});
}
};
return fn;
}
item;
您的function语句声明了一个要立即执行的函数,但您没有这样做
和项代码>就其自身而言,像这样完全可以使用JavaScript。它没有任何作用,但它是有效的。(如“使用严格”;
)
您需要的是函数表达式:
这里最重要的部分是在行的开头没有功能
。函数表达式周围的()
不是必需的,但它表示您立即执行函数。如果您没有为变量赋值,则需要它们;为了避免以函数
开始一行,您根本不需要闭包,项
已在countCategories
的范围内定义。为什么不直接将fn
分配给映射器
?因为这不起作用。。。顺便说一句,我把问题改了一点。当然,这不是一个解决方案……相关:他不工作。@Bergi好吧,至少这解释了为什么你没有得到任何错误。很多内部函数fn都是在没有调用的情况下被创建和丢弃的。我认为这里的根本问题是mongo正在破坏函数的环境,以某种方式将emit()
函数注入到它的作用域中。
var mapper = (function (it){
fn = function(){
if(this[it]){
emit(this[it], {count: 1});
}
};
return fn;
})(item);