4

mongodb シェルでクロージャーを使用する方法について、私はちょっと混乱しています。

開発中にのみ使用できる関数を作成して、その一部でドキュメントをすばやく検索したいと考えています_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 shell で機能しますか?
  • おまけの質問:この関数をユーザー プロファイルのどこかに登録して、自動的にロードすることはできますか?
4

1 に答える 1

2

$whereMongoDB シェルは、サーバーに送信するために関数オブジェクトをシリアル化 (この場合は文字列化)しているようです。

JavaScript の関数は、その関数コードをはるかに超えたものです。これは、関数コード自体と、非ローカル変数にアクセスするための関数の変数参照環境の両方を含むクロージャの一部です。関数がシリアル化された後、シリアル化が解除され、異なる参照環境で実行されます。関数が を参照しようとすると、変数を持たないまったく異なる参照環境で を求めています。patternpatternpattern

そのため、リテラル文字列関数が機能します。その関数にはpattern、変数識別子ではなく、の実際の値が含まれますpattern

この MongoDB バグを参照してください。

関数がローカルで評価されている場合は機能しますが、クロージャーは自動的に送信されません。

せせらぎでは以前はそうでしたが、シェルではそうではありませんでした。

これは、あなたのコードがシェルの外部で動作する可能性があることを示唆していますが、Mongo の内部については確かなことを言うには十分ではありません。

于 2013-07-01T14:15:36.820 に答える