Javascript 范围规则和 mongo map/reduce 函数
Posted
技术标签:
【中文标题】Javascript 范围规则和 mongo map/reduce 函数【英文标题】:Javascript scoping rules and mongo map/reduce functions 【发布时间】:2012-07-26 01:16:04 【问题描述】:我想制作一些在 mongo 中执行参数化映射/减少作业的 javascript 函数,但我对 JavaScript 的作用域感到困惑。例如,下面的代码给了我"gender"
变量的计数;即它会告诉我有多少 "male"
和 "female"
记录:
// 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
函数的作用域,但我不太确定为什么它没有被调用,也没有抛出错误。
【问题讨论】:
你根本不需要闭包,item
已经在countCategories
的范围内定义了。为什么不直接将fn
分配给mapper
?
因为没用...顺便把问题改了一下。
当然,这不是一个解决方案...
相关:How to use variables in MongoDB Map-reduce map function
【参考方案1】:
根据我在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
);
【讨论】:
【参考方案2】:我觉得你的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;
你的函数语句声明了一个你想立即执行的函数,但你没有。
而 item;
本身就是完全可以的 JavaScript。它没有做任何事情,但它是有效的。 (喜欢"use strict";
)
你想要的是一个函数表达式:
var mapper = (function (it)
fn = function()
if(this[it])
emit(this[it], count: 1);
;
return fn;
)(item);
这里的重要部分是function
本身不在行首。函数表达式周围的()
不是必需的,但它表示您立即执行该函数。如果您没有分配给变量,则它们将是必需的;避免以function
开头。
【讨论】:
他had this before - 不起作用。 @Bergi 好吧,至少这解释了为什么您没有收到任何错误。许多内部函数 fn 被创建并被丢弃,却从未被调用过。 我认为这里的根本问题是 mongo 弄乱了函数的环境,以某种方式将emit()
函数注入它的范围。以上是关于Javascript 范围规则和 mongo map/reduce 函数的主要内容,如果未能解决你的问题,请参考以下文章