Search code examples
mongodbexpressmongoosemongoose-schema

How to apply validation of a Model which is having a ref?


I want to apply validation on the current schema.What is the way I can validate using validator and show error message when the projectMembers is not entered?

projectMembers: [{
        user: {
            type: Schema.Types.ObjectId,
            ref: 'User',
            required: true,
        },
        userRole: {
            type: Schema.Types.ObjectId,
            ref: 'UserRole',
            required: true,
        },
    }],

User Model

const userSchema = new Schema({
    username: {
        type: String,
        required: true,
        minlength: 3,
        validate: {
            validator: (username) => {
                return username.length >= 3
            },
            msg: () => {
                return 'UserName length less than 3 characters'
            }
        }
    },
    email: {
        type: String,
        required: true,
        unique: true,
        minlength: 7,
        validate: {
            validator: (email) => {
                return validator.isEmail(email)
            },
            msg: () => {
                return 'Enter a valid email'
            }
        }
    },
    password: {
        type: String,
        required: true,
        minlength: 8,
        validate: {
            validator: (password) => {
                return password.length >= 8
            }
        },
        msg: function () {
            return 'Enter atleast 8 charcters'
        }
    })

UserRole Model

const UserRoleSchema = new Schema({
    userRole: {
        type: String,
        required: true,
        validate: {
            validator: (userRole) => {
                return userRole.length >= 0
            },
            msg: () => {
                return 'User Role should be selected'
            }
        }
    }
})

const UserRole = mongoose.model('UserRole', UserRoleSchema)
module.exports = UserRole       

Solution

  • Let' say your projectMembers is inside a model called Project.

    You can set required error message in schema like this:

    const mongoose = require("mongoose");
    const Schema = mongoose.Schema;
    
    const projectSchema = new Schema({
      name: {
        type: String,
        required: true
      },
      projectMembers: [
        {
          user: {
            type: Schema.Types.ObjectId,
            ref: "User",
            required: [true, "User is required"]
          },
          userRole: {
            type: Schema.Types.ObjectId,
            ref: "UserRole",
            required: [true, "User Role is required"]
          }
        }
      ]
    });
    
    const Project = mongoose.model("Project", projectSchema);
    
    module.exports = Project;
    

    And in post project route, you can use mongoose's doc.validateSync() method to validate.

    Here is a sample:

    router.post("/project", async (req, res) => {
      const { name, projectMembers } = req.body;
    
      const project = new Project({ name, projectMembers });
    
      const { errors } = project.validateSync();
    
      if (errors) {
        let convertedErrors = [];
        for (field in errors) {
          convertedErrors.push(errors[field].message);
        }
    
        return res.send({ errors: convertedErrors });
      }
    
      //todo: do whatever you want
    
      res.send();
    });
    

    If you send a request without user role to this route with this body:

    {
     "name": "project name",
     "projectMembers": [{
        "user": "5dc12a0aa875cd0ca8b871ea"
     }] 
    }
    

    You will get this response:

    {
        "errors": [
            "User Role is required"
        ]
    }
    

    And if you send a request without user role and user to this route with this body:

    {
     "name": "project name",
     "projectMembers": [{}] 
    }
    

    You will get this response:

    {
        "errors": [
            "User Role is required",
            "User is required"
        ]
    }