实现思路
- 首先,从
Department
集合开始查询,因为我们最终要获取每个部门及其相关信息。
- 使用
$lookup
将Task
集合连接到Department
集合,通过department_id
关联,这一步可以在同一分片内完成,如果department_id
是分片键的一部分或者有合适的索引,性能会较好。
- 然后通过
$lookup
将Employee
集合连接到上一步的结果,通过employee_id
关联,这一步同样可以优化,如果employee_id
是分片键或有索引。
- 再通过
$lookup
将Project
集合连接到结果,通过project_id
关联,同样要利用好索引或分片键。
- 最后对结果进行整理,通过
$unwind
、$group
等操作获取所需的格式。
具体代码示例
db.Department.aggregate([
// 左外连接Task集合
{
$lookup: {
from: "Task",
localField: "_id",
foreignField: "department_id",
as: "tasks"
}
},
// 展开tasks数组
{ $unwind: { path: "$tasks", preserveNullAndEmptyArrays: true } },
// 左外连接Employee集合
{
$lookup: {
from: "Employee",
localField: "tasks.employee_id",
foreignField: "_id",
as: "employee"
}
},
// 展开employee数组
{ $unwind: { path: "$employee", preserveNullAndEmptyArrays: true } },
// 左外连接Project集合
{
$lookup: {
from: "Project",
localField: "tasks.project_id",
foreignField: "_id",
as: "project"
}
},
// 展开project数组
{ $unwind: { path: "$project", preserveNullAndEmptyArrays: true } },
// 分组整理结果
{
$group: {
_id: "$_id",
department_name: { $first: "$department_name" },
employees: {
$push: {
name: "$employee.name",
project_name_list: { $push: "$project.project_name" },
task_id_list: { $push: "$tasks._id" }
}
}
}
}
]);