把您的問題以不同的方式:如何加入兩個以上的藏品在MongoDB中?
假設對模型的名字您的集合名稱是dogs
,teams
和people
(複數化的貓鼬約定),下面是實現預期結果的方式之一:
Dog.aggregate([{
$match: {
breed: "Poodle"
}
},
{
$lookup: {
from: "teams",
localField: "_id",
foreignField: "members",
as: "team"
}
},
{
$unwind: "$team"
},
{
$lookup: {
from: "people",
localField: "team.trainer",
foreignField: "_id",
as: "trainer"
}
},
{
$unwind: "$trainer"
},
{
$match: {
"trainer.gender": "male"
}
},
{
$project: {
breed: 1,
trainer: 1,
team: {
_id: 1
}
}
}
], function(err, teams) {
console.log(teams)
});
在聚合管道我們做的以下:
- 以
Dog
爲出發點和匹配的品種
- 然後用$lookup參加與球隊的成績,並獲取那些包含以「貴賓」
- 2的結果集包含團隊陣列(你可以刪除下面的$查找所有步驟才能看到效果的狀態)成員引用隊。要分割該陣列到另一個文檔中,我們使用$unwind運算符(團隊三個要素的發言權將成爲三個文件在所有複製父域)
- 在新的結果集,再次申請$查找,這次加盟的人。這將人們放在培訓師陣列中。
- 再次放鬆身心分裂的教練
- 比賽結果集爲
trainer.gender
「男性」
- $project(選擇),你需要
最終的結果將是這個樣子領域:
{
"_id" : ObjectId("596e5500b5174986059958a8"),
"breed" : "Poodle",
"team" : {
"_id" : ObjectId("596e564fb5174986059958de")
},
"trainer" : {
"_id" : ObjectId("596e54bfb51749860599589c"),
"gender" : "male"
}
}
{
"_id" : ObjectId("596e5500b5174986059958a8"),
"breed" : "Poodle",
"team" : {
"_id" : ObjectId("596e564fb5174986059958e6")
},
"trainer" : {
"_id" : ObjectId("596e54bfb51749860599589c"),
"gender" : "male"
}
}
{
"_id" : ObjectId("596e5500b5174986059958b2"),
"breed" : "Poodle",
"team" : {
"_id" : ObjectId("596e564fb5174986059958de")
},
"trainer" : {
"_id" : ObjectId("596e54bfb51749860599589c"),
"gender" : "male"
}
}
{
"_id" : ObjectId("596e5500b5174986059958b2"),
"breed" : "Poodle",
"team" : {
"_id" : ObjectId("596e564fb5174986059958e6")
},
"trainer" : {
"_id" : ObjectId("596e54bfb51749860599589c"),
"gender" : "male"
}
}
從本質上講,我們已搜查Dog
並加入和匹配沿途多個集合。最終文檔中的根目錄_id
是狗不是團隊的_id,因此技術上結果集包含包含團隊和培訓者的狗,但您可以將它們視爲「團隊」文檔。你可以走相反的路,從Person
開始,到達Dog
。
而且,結果的結構是不完美的。您可能需要一個結構良好的格式,因爲人口確實像teams
包含嵌入式trainer
和members
。通過聚合管道的一些調整,我確信可以實現一個良好的結構。
最後,這是不同於貓鼬的人口,這是在另一個答案建議。主要區別在於,在這種情況下,您已經將查找所需文檔的任務委派給了mongo服務器,並且顯然一次性完成。在人口中,同樣需要太多的客戶端處理和許多對db的請求。但$lookup作品在unsharded集合,在這種情況下,你可能更喜歡人口或考慮this答案。
比我建議的要好得多:) – robertklep