使用 Express/MongoDB 创建永久链接
Creating permalinks with Express/MongoDB
假设我有以下 LMS 应用程序架构:
const CourseSchema = new mongoose.Schema({
name: { type: String, required: true },
code: { type: String, required: true, unique: 1, uppercase: 1 }, // ex. CSCA48
quizzes: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Quiz' }]
});
const QuizSchema = new mongoose.Schema({
name: { type: String, required: true }, // ex. 1a
questions: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Question' }]
});
const QuestionSchema = new mongoose.Schema({
number: { type: String, required: true }, // ex. 4
question: { type: String, required: true },
type: { type: String },
choices: [String],
answers: [String]
});
我按照 RESTful API 准则构建(或尝试构建)该应用程序。例如,
GET /courses/[ObjectID]
GET /courses/[ObjectID]/quizzes
GET /courses/[ObjectID]/quizzes/[ObjectID]
GET /courses/[ObjectID]/quizzes/[ObjectID]/questions
我使用 ObjectID 的原因是因为它们是唯一的并且可以轻松检索对象 -- 特别是 app.param()。例如,
router.param('courseID', controllers.Course.getCourseByParam);
router.param('quizID', controllers.Quiz.getQuizByParam);
router.param('questionID', controllers.Question.getQuestionByParam);
router.get('/courses', controllers.Course.getCourses);
router.get('/courses/:courseID', controllers.Course.getCourse);
router.get('/courses/:courseID/quizzes', controllers.Quiz.getQuizzes);
router.get('/courses/:courseID/quizzes/:quizID/questions', controllers.Question.getQuestions);
但是现在,我想知道是否有一种方法可以不使用 ObjectID 来使 URL 更多 friendly/readable?
GET /courses/[code]/quizzes/[name]/questions/[number]
ex. /courses/CSCA48/quizzes/1a/questions/4
我对此最担心的是,虽然课程 code
是独一无二的,但测验 name
和问题 number
不是。例如,/courses/CSCA48/quizzes/1b/questions/4
将是不同测验的不同问题。所以,除非我弄错了,否则真的不可能使用 app.param()
。因此,我需要以某种方式确保测验属于匹配的课程,然后问题属于匹配的测验。
我并不是真的在寻找代码,只是关于如何处理(或不处理)的大致思路。
由于组合 [code]-[name]-[number]
是唯一的([code]
也是唯一的,这很重要),您应该能够 运行 提出正确问题的查询:
Course.findOne({ code : req.params.code })
.populate({
path : 'quizzes',
match : { name : req.params.name },
populate : {
path : 'questions',
match : { number : req.params.number }
}
})
或者,您可以向 QuestionSchema
添加两个字段以反映问题所属的课程和测验,在这种情况下,您只需 运行 一个查询即可找到正确的问题文档(人口需要 3 个查询)。
假设我有以下 LMS 应用程序架构:
const CourseSchema = new mongoose.Schema({
name: { type: String, required: true },
code: { type: String, required: true, unique: 1, uppercase: 1 }, // ex. CSCA48
quizzes: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Quiz' }]
});
const QuizSchema = new mongoose.Schema({
name: { type: String, required: true }, // ex. 1a
questions: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Question' }]
});
const QuestionSchema = new mongoose.Schema({
number: { type: String, required: true }, // ex. 4
question: { type: String, required: true },
type: { type: String },
choices: [String],
answers: [String]
});
我按照 RESTful API 准则构建(或尝试构建)该应用程序。例如,
GET /courses/[ObjectID]
GET /courses/[ObjectID]/quizzes
GET /courses/[ObjectID]/quizzes/[ObjectID]
GET /courses/[ObjectID]/quizzes/[ObjectID]/questions
我使用 ObjectID 的原因是因为它们是唯一的并且可以轻松检索对象 -- 特别是 app.param()。例如,
router.param('courseID', controllers.Course.getCourseByParam);
router.param('quizID', controllers.Quiz.getQuizByParam);
router.param('questionID', controllers.Question.getQuestionByParam);
router.get('/courses', controllers.Course.getCourses);
router.get('/courses/:courseID', controllers.Course.getCourse);
router.get('/courses/:courseID/quizzes', controllers.Quiz.getQuizzes);
router.get('/courses/:courseID/quizzes/:quizID/questions', controllers.Question.getQuestions);
但是现在,我想知道是否有一种方法可以不使用 ObjectID 来使 URL 更多 friendly/readable?
GET /courses/[code]/quizzes/[name]/questions/[number]
ex. /courses/CSCA48/quizzes/1a/questions/4
我对此最担心的是,虽然课程 code
是独一无二的,但测验 name
和问题 number
不是。例如,/courses/CSCA48/quizzes/1b/questions/4
将是不同测验的不同问题。所以,除非我弄错了,否则真的不可能使用 app.param()
。因此,我需要以某种方式确保测验属于匹配的课程,然后问题属于匹配的测验。
我并不是真的在寻找代码,只是关于如何处理(或不处理)的大致思路。
由于组合 [code]-[name]-[number]
是唯一的([code]
也是唯一的,这很重要),您应该能够 运行 提出正确问题的查询:
Course.findOne({ code : req.params.code })
.populate({
path : 'quizzes',
match : { name : req.params.name },
populate : {
path : 'questions',
match : { number : req.params.number }
}
})
或者,您可以向 QuestionSchema
添加两个字段以反映问题所属的课程和测验,在这种情况下,您只需 运行 一个查询即可找到正确的问题文档(人口需要 3 个查询)。