单一参考
在单个引用结构中,例如student.classId、class.schoolId、school.id,操作 1 和 3 可以在单个 find 操作中完成。 2和4可以一分为二:
1 查询属于一个学校的所有班级。
db.classes.find({schoolId: <school-id>})
2 查询属于某个班级的学校。
const schoolId = db.classes.findOne({_id: <class-id>}).schoolId;
const school = db.schools.findOne({_id: schoolId});
3 查询属于某个班级的学生。
db.students.find({classId: <class-id>})
4 查询属于学校的学生。
const classesForSchool = db.classes.find({schoolId: <school-id>});
const classIds = classesForSchool.map(class => class._id);
const students = db.students.find({classId: {$in: classIds}});
另类
您可能会考虑拥有两个集合:一个包含学校(包含一个嵌套的班级对象数组),另一个包含学生。在这种情况下,所有 4 个都是单个查询。您可以通过添加唯一索引来保持数据完整性,如下所示:
db.schools.createIndex({'classes._id': 1}, {unique: true})`
所有查询将如下所示:
1 查询属于一个学校的所有班级。
db.schools.findOne({_id: <school-id>}).classes
2 查询属于某个班级的学校。
db.schools.findOne({'classes._id': <class-id>})
3 查询属于某个班级的学生。
db.students.find({classId: <class-id>})
4 查询属于学校的学生。
db.students.find({schoolId: <school-id>})