2017-06-05 19 views
0

下記のreqUrlという名前の着信リクエストURLを格納できる小さなアプリケーションをコーディングし、compareUrls関数を使用して既に存在するかどうかを確認します。MongoDBのクエリと可変スコープ内での関数の使用

両方のWebサイトが同じドメインにある場合はtrueを返し、そうでない場合はfalseを返します(compareUrls(stackoverflow.com, http://www.stackoverflow.com)など)。これは、重複するURLを追加しないように使用されます。

私はこのようなMongoDBのクエリ内でその機能を使用しようとしています:

app.get("/:reqUrl", function(req, res) 
{ 
    var reqUrl = req.params.reqUrl; 

    MongoClient.connect(Url, function(err, db) 
    { 
     if (err) throw err; 
     db.collection("mydb").find({$where: function() { 

     if (compareUrls(reqUrl, this.url) //if true, simply return the url 
     { 
      return this.url; 
     } else { //if not existing insert it into the database 
      db.collection("mydb").insert({"url":reqUrl}); 
     };   

    }}).toArray(); 

//Code continues below 

さて問題は、スコープの、reqUrl変数が認識されないということである、と私は任意の回避策を知りません。 compareUrlsでローカル変数を使用しても、要素のコレクション全体が返されます。私は単純に.findを呼び出し、各項目に対してreqUrlをチェックするだけで、すべての結果を配列に戻すことを考えましたが、これは効率的ではありません。

MongoDBの新機能です。

ご意見ありがとうございます。

+0

'reqUrl'はどこで初期化されていますか? – Cynigo

+0

'MongoClient.connect()'以外のものは、私の質問を編集します – Valilutzik

+0

'$ where'関数の中に' insert'のようなデータベース操作はできません。 – JohnnyHK

答えて

1

ここでは、$where節のロジック内で他のデータベース操作を実行することはできません。また、完全に不要で、実際の操作が実際の標準演算子やメソッドでサポートされているからです。

あなたは本当にがほしいですか?.findOneAndUpdate()です。あなたがしている一致条件の種類には、単に値をチェックするだけで、$whereは必要ありません。これは、実際には、照会部分を選択するための検索条件である$regexです。

「挿入」部分については、それは"upserts"が対象です。したがって、データが「見つからない」場合、「upsert」は新しい文書をコレクションに作成/挿入し、そうでない場合は「更新」します。もちろん

db.collection("mydb").findOneAndUpdate(
    { "url": new RegExp(reqUrl) }, 
    { "$setOnInsert": { "url": reqUrl } }, 
    { "upsert": true, "returnOriginal": false }, 
    function(err, doc) { 
    // deal with result here 
    } 
) 

がここ$regex使用量がちょうどです:あなたはチューン$setOnInsert修飾子と、この場合には「見つかった」文書が実際に変更されていないことができるようにということ、およびデータのみを「挿入」にタッチしますbasic "は、この文字列がプロパティ文字列"の状態にあります。 Regex to match simple domain

しかし、基本的なロジックは「正規表現」が一致条件を満たしているのと同じままであり、その後単純に「ドメインマッチング」に関連するより高度な正規表現があります。 "upsert"

つまり、実際に一致条件として$where句を使用することはできません。ただ、条件の下でそれを確認してください

db.collection("mydb").findOneAndUpdate(
    { "$where": function() { return compareUrls(reqUrl, this.url); } }, 
    { "$setOnInsert": { "url": reqUrl } }, 
    { "upsert": true, "returnOriginal": false }, 
    function(err, doc) { 
    // deal with result here 
    } 
) 

:それは、実際の操作はserver functionか含まれ、インラインを呼び出すことができますいずれかの供給機能「内」ではなく、データベースのメソッドを呼び出そうとの「アップサート」のままというだけです$whereのサーバ機能または結果は、が動作するので、実際にはブール値true/falseを返しています。

ここでも"returnOriginal": falseの使用方法に注意してください。.findOneAndUpdate()メソッドのデフォルトの動作は変更前に元のドキュメントを返すことです。場合によってはこれが望まれるかもしれませんが、最も一般的な用法はドキュメントを変更した状態で返すことです。

もちろん、文書を返信する必要がない場合は、.updateOne()で十分であり、文書コンテンツを「ワイヤーで」返すオーバーヘッドを減らすことができます。

+0

あなたの忌々しい答えに感謝しています。前に正規表現のルートに行くと思っていましたが、 compareUrls'関数を呼び出します。 MongoDBクエリ内でカスタム関数を使用するのは難しいです。 – Valilutzik

+1

@Valilutzikこれは設計上のものです。そして、「あまりにも悪い」ではありません。私はあなたの関数で、正規表現ではできないことが起こっているとは想像もできません。実際には「本当に最適」になるためには、「ドメイン」をプロパティとしてのみ格納する必要があります。それが一意性のテストであれば、これは単純な「等価」一致と最もパフォーマンスの高いオプションになります。しかしあなたが本当に必要としているのは、あなたの頭を包み込むために必要な** JavaScriptの評価===悪い**ということです。ネイティブ演算子を使用します。 –

+0

さて、それを得ました:) – Valilutzik

関連する問題