2016-03-24 14 views
1

これはMongoDBとそのNo-SQLモデルの設計に反していますが、私は1つのコレクションでドキュメントを検索しようとしています。別のコレクションの対応するレコード。効果的に結合をエミュレートしようとしています。MongoDB、Mongooseの検索結果別のコレクションを検索する

//query is irrelevant to question 
var results = collectionOne.find(query).limit(limit); 

var a = []; 

results.forEach(function(r) 
{ 
    var aquery = { id : {$eq : r.id}}; 
    collectionTwo.find(aquery).limit(limit).exec(function, b) 
    { 
     if (err) 
     { 
      res.render('error', 
      { 
       status : 500 
      }); 
     } 
     else 
     { 
      a.push(b); 
     } 
    }); 
}); 
res.jsonp(a); 
+0

このサーバー側を実行するために$ lookupで集約を使用することができます – profesor79

答えて

6

は「一種の参加」しMongoDBのような$lookup、の新機能がある一方で、あなたの特定の操作は、これを必要としません。ここでは、_idの値が前回の値とマッシュされた場所に基づいて、別のコレクションの結果を返します。

この場合、最良の選択肢は$inを使用して他のコレクションで個のクエリをさらに個発行することです。

// Mongoose turns a cursor to an array by default in the callback method 
collectionOne.find(query,{ "_id": 1}).limit(limit).exec(function(err,results) { 

    // Just get array of _id values 
    var ids = results.map(function(el) { return el._id }); 

    // Not sure if you really mean both collections have the same primary key 
    // I'm presuming two different fields being "id" as opposed to "_id" 
    collectionTwo.find({ "id": { "$in": ids } },function(err,items) { 
     // matching results are here 
    }) 

}) 

これだけです。

あなたがすべては、その後、ちょうどそのの「リスト」として_id値の最初のクエリ結果を返す「参加あなたが本当に望んでいた場合は、ターゲットコレクション

に関連する分野に$inにその引数を指定しています『結果に入社"とし、あなたが実際だ。この

collectionOne.aggregate([ 
    { "$match": query }, 
    { "$limit": limit }, 
    { "$lookup": { 
     "from": "collectionTwo", 
     "localField": "_id", 
     "foreignField": "id", 
     "as": "twoItems" 
    }} 
]) 

よう$lookupを使用することができ、MongoDBの3.2を用意して』、とあなたはおそらくだけcollectionTwoからマッチした結果を返すためにそれを使用することができますが、その後私はペルソナllyはそうしないでしょう。これはサーバ上でさえコストのかかる運動であり、実際にそのフォーマットを返すために必要な操作をさらにフィルタリングすると、さらにコストがかかることになります。

また、.populate()については、mongooseを参照してください。これは実際にはこのタイプのクエリの「逆」です。その代わりに、関連するコレクション内のオブジェクトの主キーを指すObjectIdの値の配列(または通常のフィールドですが、この場合は配列)を格納するのがプロセスです。したがって、collectionTwoの「多数」の値がある場合、これらはcollectionOne文書内の配列に格納されます。

これもまた、「結合エミュレーション」であり、実際の結合ではありません。結果は$lookupと似ていますが、実際にはcollectionTwoの結果ではなく、同様にフィルタリングする必要がある「結合」バージョンの「単なる」結果ではありません。

.populate()で実際に起こるのは、とにかく$inというクエリを実行するということです。したがって、親に子参照を格納するすべての作業(IMHO、ほとんどの場合、それを行うことができれば、代わりにデータを埋め込むこともできます)でも、データベースとの実際のやりとりは変更されません。 $inクエリ。

+0

@ user3424480あなたはあなたがそこに何を意味するか分からない。 「ソース」が「ObjectId」を使用しているときに「ターゲット」も同様に必要であるということを意味するならば、もちろんそうです。それはどんなタイプのBSONにも当てはまります。 –

関連する問題