我是MongoDB的新手。我在嵌套集合时遇到了一些问题。假设我在mongodb中有3个不同的集合。 (1)类(2)主题和(3)章。
课程包含各种课程名称,特定课程的主题包含不同的主题名称,而特定课程的章节包含不同的主题名称。
使用猫鼬,我可以获取/查找父母的章节集合,如下所示:
ChapterModel.find({})
.limit(1)
.populate([
{ path: "classId", model: ClassModel },
{ path: "subjectId", model: SubjectModel }
]);
给出以下结果:
[
{
"_id": "5de6a660a5f6a42060d532cd",
"name": "Physical Quantities and Their Measurements",
"subjectId": {
"_id": "5de6a660a5f6a42060d532c5",
"classId": "5de6a65fa5f6a42060d532c4",
"name": "Physics"
},
"classId": {
"_id": "5de6a65fa5f6a42060d532c4",
"name": "IX"
}
}
]
但是我找不到以以下方式获取类子级的任何方法:
[
{
"_id" : ObjectId("5de6a660a5f6a42060d532c5"),
"name": "IX",
"subjects": [
{
"_id" : ObjectId("5de6a660a5f6a42060d532c6"),
"name": "Physics",
"classId": ObjectId("5de6a660a5f6a42060d532c5"),
"chapters": [
{
"_id" : ObjectId('5c09fb04ff03a672a26fb23a'),
"name": Physical Quantities and Their Measurements",
"classId": ObjectId("5de6a660a5f6a42060d532c5"),
"subjectId": ObjectId("5de6a660a5f6a42060d532c6"),
},
{
"_id" : ObjectId("5de6a660a5f6a42060d532c6"),
"name": "Motion",
"classId": ObjectId("5de6a660a5f6a42060d532c5"),
"subjectId": ObjectId("5de6a660a5f6a42060d532c6"),
}
]
}
]
}
]
它们是否像填充所有嵌套子代或集合一样?
答案 0 :(得分:1)
您可以使用猫鼬的populate功能。
解决问题的一种方法是设计如下的架构和模型: (请注意,因为它是javascript中的保留关键字,所以我使用课程名称而不是课程)
course.js
const mongoose = require("mongoose");
const courseSchema = new mongoose.Schema(
{
name: String
},
{
toJSON: { virtuals: true }
}
);
courseSchema.virtual("subjects", {
ref: "Subject",
foreignField: "course",
localField: "_id"
});
module.exports = mongoose.model("Course", courseSchema);
subject.js
const mongoose = require("mongoose");
const subjectSchema = new mongoose.Schema(
{
name: String,
course: {
type: mongoose.Types.ObjectId,
ref: "Course"
}
},
{
toJSON: { virtuals: true }
}
);
subjectSchema.virtual("chapters", {
ref: "Chapter",
foreignField: "subject",
localField: "_id"
});
module.exports = mongoose.model("Subject", subjectSchema);
chapter.js:
const mongoose = require("mongoose");
const chapterSchema = new mongoose.Schema({
name: String,
subject: {
type: mongoose.Types.ObjectId,
ref: "Subject"
}
});
module.exports = mongoose.model("Chapter", chapterSchema);
请注意,虚拟关键字的意思是populate virtual。 我之所以选择这种解决方案,是因为否则我们应该在课程模式中保留一个称为主题的附加字段,我们需要在其中保留一组主题ID(以及主题模式中的Chapters字段)。
使用这些架构,您可以使用以下查询来获取所需的结果:
const Course = require("../models/course");
router.get("/courses", async (req, res) => {
const result = await Course.find({}).populate({
path: "subjects",
populate: { path: "chapters" }
});
res.send(result);
});
如果您很难测试,以下是创建课程,主题和章节的其他途径:
const Subject = require("../models/subject");
const Chapter = require("../models/chapter");
const Course = require("../models/course");
router.post("/courses", async (req, res) => {
const result = await Course.create(req.body);
res.send(result);
});
router.post("/subjects", async (req, res) => {
const result = await Subject.create(req.body);
res.send(result);
});
router.post("/chapters", async (req, res) => {
const result = await Chapter.create(req.body);
res.send(result);
});
router.get("/courses", async (req, res) => {
const result = await Course.find({}).populate({
path: "subjects",
populate: { path: "chapters" }
});
res.send(result);
});
首先,我用这个正文创建了一个帖子:(给出的课程ID为5de6c047856efe390cbf665d)
{
"name": "IX"
}
然后,我使用此主体为5de6c047856efe390cbf665d的课程ID创建了一个主题:(给出了主体ID为5de6c0d7856efe390cbf665e)
{
"name": "Physics",
"course": "5de6c047856efe390cbf665d"
}
然后使用该主题ID 5de6c0d7856efe390cbf665e,我使用以下内容创建了两章:
{
"name": "Physical Quantities and Their Measurements",
"subject": "5de6c0d7856efe390cbf665e"
}
{
"name": "Motion",
"subject": "5de6c0d7856efe390cbf665e"
}
结果是:
[
{
"_id": "5de6c047856efe390cbf665d",
"name": "IX",
"__v": 0,
"subjects": [
{
"_id": "5de6c0d7856efe390cbf665e",
"name": "Physics",
"course": "5de6c047856efe390cbf665d",
"__v": 0,
"chapters": [
{
"_id": "5de6c123856efe390cbf665f",
"name": "Physical Quantities and Their Measurements",
"subject": "5de6c0d7856efe390cbf665e",
"__v": 0
},
{
"_id": "5de6c136856efe390cbf6660",
"name": "Motion",
"subject": "5de6c0d7856efe390cbf665e",
"__v": 0
}
],
"id": "5de6c0d7856efe390cbf665e"
}
],
"id": "5de6c047856efe390cbf665d"
}
]