If rephrased, the question would be: How can I merge multiple collections in mongoDB?
Let's assume the collection names correspond to model names like dogs
, teams
, and people
(following the Mongoose convention of pluralization). Below is a method to achieve this:
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)
});
In this pipeline, we:
- Start with
Dog
and match the breed
- Use $lookup to combine with teams and retrieve those with "Poodle" members
- The result from step 2 is an array of teams. To separate the array, we employ another $unwind operation
- Perform another $lookup to join with people and populate the trainer array
- Unwind to separate the trainer array
- Filter the set for male trainers
- Select the desired fields with $project
The output will resemble:
{
"_id" : ObjectId("596e5500b5174986059958a8"),
"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"
}
}
This method allows us to search Dog
and connect with other collections. The final documents root _id is the dog's, not the team's. The structure can be optimized for better readability, akin to Mongoose's population feature.
Remember, this is distinct from Mongoose's population feature. Here, the database server handles document retrieval efficiently in one operation. For sharded collections, population or a different approach might be more suitable as explained here.