我的参考馆藏很少:员工,角色,学校......
我需要查询数据库,列出某所学校雇用的所有员工。这意味着必须在列表或结果数组中返回在相应角色文档中具有特定学校ID的所有员工。
到目前为止,我试图找到它:
const employees = mongoose.schema("Employees");
employees.find({})
.populate({
"path": "roles"
})
.then(function(docs){
docs.filter(function(){
// write my filters here....
})
});
但这仍然效率低下,我无法使其发挥作用。 它必须是一种更聪明的方式......
这是我的员工文档,它引用了角色集合中的文档:
{
"_id" : { "$oid" : "57027f1b9522d363243abr42" },
"assignedRoles": [
{
"type": "teacher",
"schools": [
{
"schoolId": "57027f1b9522d3632423rf32",
"classes" : ["math", "science"],
"active": true
},
{
"schoolId": "57027f1b9522d36324252fs2",
"classes" : ["science"],
"active": true
},
{
"schoolId": "57027f1b9522d36324242f35",
"classes" : ["math"],
"active": true
},
]
},
{
"type": "manager",
"schools": [
{
"schoolId": "57027f1b9522d3632423rf32",
"active": true
},
{
"schoolId": "57027f1b9522d36324252fs2",
"active": true
}
]
}
{
"type": "principal",
"schools": [
{
"schoolId": "57027f1b9522d3632423rf32",
"active": true
}
]
}
],
"rolesMeta": "Meta Info for the Roles"
}
以下是学校列表 - 与任务无关,我只是为了完成而添加:
{
"_id": { "$oid" : "57027f1b9522d3632423rf32" },
"name": "G.Washington HS",
"district": "six",
"state": "New Mexico"
},
{
"_id": { "$oid" : "57027f1b9522d36324252fs2" },
"name": "A. Lincoln HS",
"district": "six",
"state": "New Mexico"
},
{
"_id": { "$oid" : "57027f1b9522d36324242f35" },
"name": "T. Roosvelt HS",
"district": "four",
"state": "New Mexico"
}
答案 0 :(得分:0)
解决问题的方法是使用MongoDB Aggregate framework向下钻取并“展平”阵列结构。
以下是我如何解决它:
db.employees.aggregate([
// I use $project to specify which field I want selected from the collection
{
$project: {_id: 1, "roles": 1}
},
// $lookup helps me get results and populate the 'role' field from the Roles collection. This returns an array
{
$lookup: {
"from": "roles",
"localField": "roles",
"foreignField": "_id",
"as": "roles"
}
},
// $unwind is self explanatory - it flattens the array and creates multiple objects, instances of the parent object for each array element.
{
$unwind: "$roles"
},
// now repeat for each array in this document
{
$unwind: "$roles.assignedRoles"
},
// repeat again, since I need to look in the schools array.
{
$unwind: "$roles.assignedRoles.schools"
},
// The following line will return all records that the school ID checks out.
{
$match: {"roles.assignedRoles.schools.schoolId": school}
},
// $group is a necessary cleanup task so we avoid repeating employee records... Nicely Done! :)
{
$group: {
"_id": "$_id",
"roles": {"$push": "$roles"},
}
}
])
.exec()
.then(function (docs) {
// here you process the resulted docs.
});