2013-07-01 36 views
2

我有点困惑于如何在mongodb shell中使用闭包。如何在mongodb shell中使用闭包?

我想创建一个函数,我可以在开发期间专门使用以快速查找文档的一部分_id

该函数应该返回一个$where选择器来进行必要的匹配。
我想把它写的是这样的:

var id = function(pattern, selector) { 
    return Object.extend({ 
     $where: function() {return (this._id + "").indexOf(pattern) != -1;} 
    }, selector); 
}; 

但是当我尝试它,我得到以下错误:

db.mycollection.find(id("ab1")); 
error: { 
     "$err" : "JavaScript execution failed: ReferenceError: pattern is not defined near ').indexOf(pattern) ' ", 
     "code" : 16722 
} 

调用$where手动似乎工作也奇怪:

id("ell").$where.call({_id: "hello"}); // true 

我只能认为这是一个解决方案,使其工作,但这显然是可怕的。
澄清:这种方法new Function工作正常,但我不喜欢它,因为上述方法也应该工作。

var id = function(pattern, selector){ 
    return Object.extend({ 
     $where: new Function("return (this._id + '').indexOf('" + pattern + "') != -1;") 
    }, selector); 
}; 
  • 为什么不工作我封,封做MongoDB中的壳工作?
  • 奖励问题:我可以在用户配置文件某处注册此功能以自动加载吗?
+0

嗯我不确定你为什么认为'find()'期望闭包?为了运行闭包,find()函数必须要输入一个。至于另一个问题,你定义了什么作为用户配置文件?另外为什么要在全局中保存'$ where'子句? – Sammaye

+0

问题不在于'find()',而是'$ where'。我希望来自'id'函数的'pattern'参数能够关闭返回的'$ where'函数。但是当调用'$ where'时,'pattern'不再被定义。我想自动提供这个'id'函数,所以我不必每次启动一个新shell就定义它。我希望这能够澄清这个问题。 –

+0

好吧我想我现在知道为什么了,我相信这是由于JS的工作原理。如果你要将$ where的值定义为一个字符串而不是'Function',我有一种有趣的感觉,它会起作用。基本上我相信它是由于'Function'的工作原理而在您的客户端函数范围之外评估您的'pattern' var。至于如何在没有定义它的情况下运行它,如果你在Linux上,你可以将它添加到'.mongorc.js'中,并且它将完成 – Sammaye

回答

1

看来,MongoDB外壳序列化(在这种情况下,字符串ifies)$where功能对象,以便将它们发送到服务器。

在JavaScript的函数是比其功能码得多 - 这是一个closure的一部分,其包括两个功能代码本身和用于访问非局部变量的函数的变量引用环境。在函数被序列化后,它将被反序列化并在不同的引用环境下执行。当函数试图引用pattern时,它要求pattern在完全不同的参考环境中,该环境没有pattern变量。

这就是为什么你的字符串函数的作品。该函数包含pattern的实际值,而不是变量标识符pattern

this MongoDB bug,这也解释了:

That would work if the function was being evaluated locally, but the closure isn't sent over automatically.

In babble it used to be, but not in the shell.

这表明你的代码可将罩外工作,但我不知道有足够的了解蒙戈内部肯定地说。

+0

这似乎是问题,然后我只是使用我的'新的函数'方法,似乎工作正常。谢谢 ! –