いいえ、 .populate()
を呼び出すことはできません .aggregate()
の前 、そしてあなたができない非常に正当な理由があります。しかし、あなたが取ることができるさまざまなアプローチがあります。
.populate()
メソッドは「クライアント側」で機能し、基になるコードが実際に追加のクエリ(より正確には $ in
)を実行します。 クエリ)を参照して、参照されたコレクションから指定された要素を「検索」します。
対照的に、 .aggregate()
は「サーバー側」の操作であるため、基本的にコンテンツの「クライアント側」を操作して、後でそのデータを集約パイプラインステージで使用できるようにすることはできません。操作しているコレクションにすべて存在する必要があります。
ここでのより良いアプローチは、 $ lookup
集約パイプライン操作。また、おそらく User
から処理するのが最適です この場合、選択を絞り込むためのコレクション:
User.aggregate(
[
// Filter first
{ "$match": {
"age": { "$gt": 20 }
}},
// Then join
{ "$lookup": {
"from": "scores",
"localField": "userID",
"foriegnField": "userID",
"as": "score"
}},
// More stages
],
function(err,results) {
}
)
これには基本的に、 User
内に新しいフィールド「score」が含まれます。 他のコレクションの「ルックアップ」で一致したアイテムの「配列」としてのオブジェクト:
{
"userID": "abc",
"age": 21,
"score": [{
"userID": "abc",
"score": 42,
// other fields
}]
}
一般的に予想される使用法は、可能な「1対多」関係の「左結合」であるため、結果は常に配列になります。一致する結果がない場合、それは単なる空の配列です。
コンテンツを使用するには、なんらかの方法で配列を操作するだけです。たとえば、 $ arrayElemAt
を使用できます。
将来の操作で配列の最初の要素を1つだけ取得するための演算子。そして、通常の埋め込みフィールドと同じようにコンテンツを使用できます:
{ "$project": {
"userID": 1,
"age": 1,
"score": { "$arrayElemAt": [ "$score", 0 ] }
}}
MongoDB 3.2を使用できない場合、別のコレクションの関係によって制限されるクエリを処理する他のオプションは、最初にそのコレクションから結果を取得してから、 $ in
2番目にフィルタリングするには:
// Match the user collection
User.find({ "age": { "$gt": 20 } },function(err,users) {
// Get id list
userList = users.map(function(user) {
return user.userID;
});
Score.aggregate(
[
// use the id list to select items
{ "$match": {
"userId": { "$in": userList }
}},
// more stages
],
function(err,results) {
}
);
});
したがって、有効なユーザーのリストを他のコレクションからクライアントに取得し、それをクエリで他のコレクションにフィードすることは、以前のリリースでこれを実現するための唯一の方法です。