Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

mongoose model for multi-types of users

I am building a kind of social network for students and teachers with MEAN stack.

Students has their own account page different from the one of the teachers.

I have one single registration page for both teachers and students.

When registering, the user has to choose the "type" of the account with a select html tag (student or teacher),

I want to have one single model representating two different type of user (teacher and student) that contains common fields like email and password etc, and some specific fields depending on the select tag ; because I am using email-verification-node npm and it only permits to use a single model in the PersistentUserModel function.

like image 523
user3711521 Avatar asked Jul 28 '16 14:07

user3711521


People also ask

What is the difference between Mongoose schema and model?

Mongoose Schema vs. Model. A Mongoose model is a wrapper on the Mongoose schema. A Mongoose schema defines the structure of the document, default values, validators, etc., whereas a Mongoose model provides an interface to the database for creating, querying, updating, deleting records, etc.

Is Mongoose an ORM or ODM?

Mongoose is an ODM that provides a straightforward and schema-based solution to model your application data on top of MongoDB's native drivers.

What is Mongoose schema types ObjectId?

ObjectId . A SchemaType is just a configuration object for Mongoose. An instance of the mongoose. ObjectId SchemaType doesn't actually create MongoDB ObjectIds, it is just a configuration for a path in a schema.

Is Mongoose model a collection?

The mongoose. model() function of the mongoose module is used to create a collection of a particular database of MongoDB.


Video Answer


2 Answers

I suggest use this approach.

You should have a separate Schemas for Account, Teacher and Student so the different info between the teachers and students should not be mixed in one place.

Account

var Account = new Schema({
    email:String,
    password:String,
    _teacher:{type:Schema.Types.ObjectId, ref:'Teacher'},
    _student:{type:Schema.Types.ObjectId, ref:'Student'}
})

Under account, you should reference the Teacher model if teacher account otherwise reference Students model.

To check if Account is Teacher or Student you could just check _teacher, if it has a value then it's a Teacher account else it's a student. But to make the condition more unique you, check both _teacher and _student.

This approach will save you a lot of refactoring in the future if you will decided to allow the teacher to be a student as well (which is not impossible to happen), he/she can just use the same account and register as a student. Just like what google is doing, on account/email multiple types of app to use.

Teacher

var Teacher = new Schema({
    name:{type:Schema.Types.ObjectId, ref:'Name'}
    // Other teachers info
})

Student

var Student = new Schema({
    name:{type:Schema.Types.ObjectId, ref:'Name'}
    // Other students info
})

Name

On this part maybe you are wondering why you need a separate model for name. Well that is because in this approach you can just use one route or endpoint or query to search users across your app. When you search for a name, all students and teachers with matching result will be queried without looking into 2 different collections (Teacher collection and Student collection).

On good use case for this is, for sure you will have an admin dashboard where you can manage all students and teachers. In that dashboard you can just one search field for both teacher and student.

var Name = new Schema({
    firstName:String,
    middleName:String,
    lastName:String
})

Good reads

  • Referencing a document
  • Embedded documents
  • Schema Types
  • Schema Options

Other tips

You could also separate the Address like I did with the name here. Reason? Same purpose as with the Name, you might want to add search by location feature or something like that.

I hope this helps.

like image 114
CENT1PEDE Avatar answered Oct 17 '22 07:10

CENT1PEDE


Set up a Boolean field inside your data model that has the key teacher (or student if you prefer) and set that when the user signs up.

Edit:

You can have two different schemas, one for each user type. Declaring them would look something like this.

const usersSchema = new Schema({/* base schema */});

const teachersSchema = new Schema({ /* teachers schema */});
const studentsSchema = new Schema({ /* students schema */});

And

const User = mongoose.model('User', usersSchema, 'users');
User.Teacher = mongoose.model('Teacher', teachersSchema, 'users');
User.Student = mongoose.model('Student', studentsSchema, 'users');

Have a look at the docs here

Edit 2:

I found a better way of doing this is using discriminators...thanks!

const options = {discriminatorKey: 'kind'};

const userSchema = new mongoose.Schema({/* user schema */}, options);
const User = mongoose.model('User', userSchema);

// Schema that inherits from User
const teacherSchema = User.discriminator('Teacher',
  new mongoose.Schema({/* Schema specific to teacher */}, options));
const studentSchema = User.discriminator('Student',
  new mongoose.Schema({/* Schema specific to student */}, options));

const teacher = new Teacher({/* you can add everything here! */});
const student = new Student({/* you can add everything here! */});

Look up by calling either Teacher or Student

Now you have one model with two Schema! More info in the docs here.

Edit with more info:

You would create two types of data structure, a teacher and student which would both be held in the User collection. When you are calling the database you call using Teacher or Student.

Any data that is going to be common to both is put in the User schema, while anything that is specific you put in the relevant schema.

When you receive a call to the api you direct to the relevant look up. You could use a boolean or a string in the request params, and then separate out the logic with an if statement or a switch statement. I would use a string and a switch.

In your client set two constants TEACHER = 'teacher', STUDENT = 'student', and call with the relevant constant to the api in the body of your request. That way when it hits the api the request will be parsed to the correct lookup and send back the relevant data.

like image 45
alex Avatar answered Oct 17 '22 07:10

alex