1

I have begun diving into the server side of things lately, and am working on an app where I need to think about how I plan my models.

My users are teachers, and in the dashboard will have the ability to create a list of students. My schema's will contain more directives to prevent duplicates being created, but I have simplified them here. Here's what I have attempted so far:

// Teacher Model
const Teacher = new Schema({
   fname: String,
   lname: String,
   email: String,
})

// Student Model
const Student = new Schema({
   fname: String,
   lname: String,
   full: String,
   uuid: String
   grades: {
    classwork: Array,
    quizzes: Array,
    tests: Array
   }
})

Here's where my inexperience with backend work comes into play. This setup doesn't really make sense to me. Say when I go and save a student, it will create a new student under the student collection in the database. This is not ideal, as the student should be stored in a way that is strictly accessible to the teacher who created it.

I was thinking about creating a new key in my Teachers Schema called "students"(which would be an array) that would push a student into it each time one was created.

It's definitely important that I plan this properly, as the teacher is going to have much more ability in the future, like creating assignments, grading students etc. I'd like to design this with best practices in mind, to ensure the teachers data is safe from other users.

Mikey
  • 6,728
  • 4
  • 22
  • 45
Dan Zuzevich
  • 3,651
  • 3
  • 26
  • 39
  • Wouldn't you have a `CourseSchema`? – Mikey Jul 12 '17 at 13:53
  • That's another thing I am struggling with. I was hoping if I could get this original question answered, I'd be able to figure that part out on my own. However, I am still not really sure how I am going to do that. – Dan Zuzevich Jul 12 '17 at 14:39
  • IMO I think the `ClassSchema` is important to this design. A teacher has many classes where each class has many students. The class is the bridge that connects them and a lot of other things. I personally would keep them as separate entities and connect them by references. For example, you may have `ClassSchema` with two arrays of references: `teachers` and `students`. This will allow you to find the teachers and students for a particular class. You might find it useful to have `classes` (array of references) in your `TeacherSchema`. This will allow to easily find the classes for a teacher. – Mikey Jul 12 '17 at 15:23
  • You might find these two questions useful: [MongoDB relationships: embed or reference?](https://stackoverflow.com/questions/5373198/mongodb-relationships-embed-or-reference) and [Many-to-many relationship with nosql](https://stackoverflow.com/questions/25101386/many-to-many-relationship-with-nosql-mongodb-and-mongoose) – Mikey Jul 12 '17 at 15:30

2 Answers2

2

Using nested array in mongo model is not so smooth. I can suggest to think about size of this array.

If there is a chance that your array can grow - don't use it.

My suggestion for your database design is simple. Add teacherId to the student model. This way, when you need to fetch students list according to the certain teacher - you can easily query by teacherId.

So your student schema modified would look this way:

const Student = new Schema({
   teacherId: {
     type: mongoose.Schema.Types.ObjectId,
     index: true,
     required: true
   },
   fname: String,
   lname: String,
   full: String,
   uuid: String
   grades: {
    classwork: Array,
    quizzes: Array,
    tests: Array
   }
});
Lazyexpert
  • 3,106
  • 1
  • 19
  • 33
  • Wouldn't a student have many teachers though? More importantly, I don't see why there needs to be a direct relationship between teacher and student. – Mikey Jul 12 '17 at 13:47
  • This is in response to Mikey's question. This is more so for a very specific niche of teachers, mainly elementary/middle school where they have one class of students all year, and teach them several subjects. The students have no interaction with this app, its just for classroom management type things. – Dan Zuzevich Jul 12 '17 at 14:31
  • It seems that going with @lazyexpert solution might be the best idea here? – Dan Zuzevich Jul 12 '17 at 14:40
  • @DanielZuzevich Both answers have their merits. It all depends on what you want to do -- and how much work you want to do (as indicated in LazyExpert's link). – Mikey Jul 12 '17 at 15:25
  • Went with this one for the moment. I will post back here when I start building out my other models, and if I change anything. – Dan Zuzevich Jul 13 '17 at 14:17
2

I don't agree with @Lazyexpert. MongoDB is a non-relational database and you can store until 16Mb of data per document. It is really enough for what you need

The maximum BSON document size is 16 megabytes. The maximum document size helps ensure that a single document cannot use excessive amount of RAM or, during transmission, excessive amount of bandwidth. To store documents larger than the maximum size, MongoDB provides the GridFS API.

i.e: https://docs.mongodb.com/manual/reference/limits/

So I suggest you just add the datas of each student directly in your teacher.

You can find some tips here : https://www.safaribooksonline.com/library/view/50-tips-and/9781449306779/ch01.html

So your model would looks something like that :

const Teacher = new Schema({
   fname: String,
   lname: String,
   email: String,
   students : [
      {
         fname: String,
         lname: String,
         full: String,
         uuid: String
         grades: {
             classwork: Array,
             quizzes: Array,
             tests: Array
         },
      },
   ],
})

And if you absolutely want a collection Student as well, then use a "post" middleware on the "save" action on your student schema. Something like this :

StudentSchema.post('save', function(doc) {
  Teacher.findOneAndUpdate({_id: <your teacher id>}, <your student object>, callback);
});

i.e: mongoosejs.com/docs/api.html#schema_Schema-post

Good luck :)

  • 1
    I wouldn't be so straightforward. Read this article: https://dzone.com/articles/dont-worry-about-embedding-0 . Arrays have their pros and cons. – Lazyexpert Jul 12 '17 at 13:29
  • I definitely wouldn't keep all those information together in one collection. Updating a student's information, for example, will become a nightmare. – Mikey Jul 12 '17 at 13:45
  • That's what I was thinking. I originally tried storing it all in one collection, and could immediately see that it would become a hassle. – Dan Zuzevich Jul 12 '17 at 14:33
  • Not necessarily, with the $ operator it is not that complicate. But that's true, it depends what exactly you wanna do. And if you have an array in an array in an array ... yes it will be a nightmare to update. but for a single level of data, I feel it is ok. – Robin Thiry Jul 12 '17 at 15:53