2017-07-04 1 views
0

Angenommen, ich habe die folgenden Schemata für eine LMS App:Erstellen Permalinks mit Express/MongoDB

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] 
}); 

ich gebaut (oder versucht zu bauen) die App folgende RESTful API-Richtlinien. Zum Beispiel

GET /courses/[ObjectID] 
GET /courses/[ObjectID]/quizzes 
GET /courses/[ObjectID]/quizzes/[ObjectID] 
GET /courses/[ObjectID]/quizzes/[ObjectID]/questions 

Der Grund, warum ich verwendet ObjectID war, weil sie einzigartig sind und macht es einfach, Objekte abzurufen - vor allem mit app.param(). Zum Beispiel

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); 

Aber jetzt frage ich mich, ob es einen Weg gibt ist, um nicht zu verwenden ObjectID machen die URLs freundlicher/lesbar?

GET /courses/[code]/quizzes/[name]/questions/[number] 

ex. /courses/CSCA48/quizzes/1a/questions/4 

Meine größte Sorge dabei ist, dass, obwohl natürlich code eindeutig zuzuordnen sind, Quiz name und Frage number nicht. Zum Beispiel wäre /courses/CSCA48/quizzes/1b/questions/4 eine andere Frage für ein anderes Quiz. Also, wenn ich mich nicht irre, ist es nicht wirklich möglich, app.param() zu verwenden. Daher müsste ich irgendwie sicherstellen, dass das Quiz zu dem passenden Kurs gehört und dann die Frage zu dem passenden Quiz gehört.

Ich bin nicht wirklich auf der Suche nach Code, nur eine allgemeine Vorstellung davon, wie ich das angehen kann (oder nicht).

+0

Ist die Kombination '[Code] - [Name] - [Nummer]' eindeutig? – robertklep

+0

@robertklep Ja, wäre es. – Mikey

+0

Sie können eine eindeutige Kombination sein, aber wenn das Ergebnis auf die Verwendung von "bestückten Pfaden" angewiesen ist (was im Wesentlichen mindestens zwei weitere Anfragen an MongoDB zusätzlich zu jeder Basisanforderung ist), dann ist es einfach eine wirklich schlechte Idee und Sie sollten das Design überdenken. –

Antwort

1

Da die Kombination [code]-[name]-[number] einzigartig ist (und [code] auch, was wichtig ist), sollten Sie in der Lage sein, eine Abfrage auszuführen, die die richtige Frage stellen würde:

Course.findOne({ code : req.params.code }) 
     .populate({ 
     path  : 'quizzes', 
     match : { name : req.params.name }, 
     populate : { 
      path : 'questions', 
      match : { number : req.params.number } 
     } 
     }) 

Alternativ können Sie auch zwei Felder hinzufügen könnte an QuestionSchema, um sowohl den Kurs als auch das Quiz widerzuspiegeln, zu dem die Frage gehört. In diesem Fall müssten Sie nur eine einzige Abfrage ausführen, um das richtige Fragedokument zu finden (Population erfordert 3 Abfragen).

+0

Interessante erste Lösung. Ich nehme an, das funktioniert nur bis zu 2 verschachtelte Ebenen?Zum Beispiel würde '[code] - [name] - [Nummer] - [anothervar]' Ihre zweite Lösung erfordern? – Mikey

+0

@Mikey Wenn Sie ein befülltes Feld zu 'QuestionSchema' hinzufügen (was Sie dann mit' req.params.anothervar' abfragen würden), sollten Sie in der Lage sein, eine Ebene tiefer zu gehen. – robertklep

+0

Ich mag das. Ich werde es später ausprobieren und Sie wissen lassen. – Mikey

Verwandte Themen