mongodbmongoosemongoose-schema

Can we use unique: [true, "this should be unique"] in this way in mongoose


import mongoose from "mongoose";

const userSchema = new mongoose.Schema(
    {
        name: {
            type: String,
            required: [true, "Please provide your name."],
            minLength: [3, "Name must be at least 3 characters long"],
            maxLength: [50, "Name cannot exceed 50 characters"],
            trim: true,
            index: true,
        },
        username: {
            type: String,
            required: [true, "Please provide a username."],
            minLength: [3, "Username must be at least 3 characters long"],
            maxLength: [30, "Username cannot exceed 30 characters"],
            unique: [
                true,
                "This username is already taken. Please choose another one.",
            ],
            lowercase: true,
            trim: true,
            index: true,
        },
        email: {
            type: String,
            required: [true, "Please provide your email address."],
            unique: [
                true,
                "This email address is already registered. Please login or use a different one.",
            ],
            lowercase: true,
            trim: true,
        },
        password: {
            type: String,
            required: [true, "Please provide a password."],
            minLength: [8, "Password must be at least 8 characters long"],
            maxLength: [50, "Password cannot exceed 50 characters"],
        },      
    },
    { timestamps: true }
);

export const User = mongoose.model("User", userSchema);

Can we use unique in this way?

I have seen mongoose docs, required, maxLength, minLength have been used there but unique is not there. Can you help me in this.

Is this correct or it is a good practice to use it in this way


Solution

  • Unfortunately, mongoose unique constraints are not the same a validators so you cannot pass custom error messages to them.

    Mongoose uses a MongoDB unique index when you define a property as unique: true so you can check for an E11000 error thrown by the native driver during document creation and respond with a custom message if you want.

    Something like this:

    app.post('/user',  async (req, res) => {
       try{
          const newUser = await User.create({
             name: req.body.name,
             username: req.body.username,
             email: req.body.email,
             password: req.body.password
          });
          return res.status(201).json({
             message: 'New User Created'
          })
       }catch(err){
          console.log(err);
          if(err.code === 11000){
             const errorMessages = new Map([
                ['username', 'This username is already taken. Please choose another one.'],
                ['email', 'This email address is already registered. Please login or use a different one.'],
             ]);
             return res.status(400).json({
                error: errorMessages.get(Object.keys(err.keyPattern)[0])
             })
          }else{
             return res.status(500).json({
                error: 'Error on Server'
             })
          }
       }
    })
    

    By creating const errorMessages = new Map() you can store all of your custom duplicate key error messages in a Map object. Then to access the right one you can use the err.keyPattern which will be an object of key: value pairs. By calling Object.keyson the err.keyPattern you can select the key at 0 index and it will return the name of the property violating the unique index.