Search code examples
mongoosenext.jsschema

How to use "match" in Schema while using mongoose


I am learning Next.js from this youtube video Next.js 13 Full Course 2023 and here he tells about "match" that he uses as a requirement for the data to match a few attributes he give by adding some code in there.

username: {
        type: String,
        required : [true, 'username is required'],
        match: [/^(?=.{8,20}$)(?![_.])(?!.*[_.]{2})[a-zA-Z0-9._]+(?<![_.])$/, "Username invalid, it should contain 8-20 alphanumeric letters and be unique!"], 
    },

I would like know more about this way of writing match and how to change or make your own but I can't find any documentation or explanation yet. Please help me learn how to use it. I am currently using Nextjs with MongoDB as database and Mongoose. Here is a copy of my pakage.json if needed.

{
  "name": "surveysnap",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "autoprefixer": "10.4.15",
    "express": "^4.18.2",
    "mongoose": "^7.5.2",
    "next": "13.4.19",
    "next-auth": "^4.23.1",
    "postcss": "8.4.28",
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "react-icons": "^4.10.1",
    "tailwindcss": "3.3.3"
  }
}

Full code of the Schema I use is this.

import { Schema, model, models } from "mongoose";
// models is the collection of all the model that is associated with the mongoose library
const UserSchema = new Schema({
    email: {
        type : String,
        unique : [true, 'email already in use'],
        required : [true, 'email already in use'],
    },
    username: {
        type: String,
        required : [true, 'username is required'],
        match: [/^(?=.{8,20}$)(?![_.])(?!.*[_.]{2})[a-zA-Z0-9._]+(?<![_.])$/, "Username invalid, it should contain 8-20 alphanumeric letters and be unique!"], 
    },
    password: {
        type: String,
        match: [/^(?=.{8,20}$)(?![_.])(?!.*[_.]{2})[a-zA-Z0-9._]+(?<![_.])$/, "Password invalid, it should contain 8-20 alphanumeric letters and be unique!"],
    },
    image: {
        type: String,
    },
    membership: {
        type: String,
        required : [true, 'membership is information is required'],
    },
    survey_created: {
        type: Number,
    },
    survey_answered: {
        type: Number,
    },
    snap_points: {
        type: Number,
    },

});

const User = models.User || model("User", UserSchema);
// if a "User" already exists, models assign the existing one to avoid redefining model and ensuring the existing one be used.
// Otherwise it will create a new one.
export default User;

An Explanation on how to use Match in Schema.


Solution

  • In Mongoose match is used to set a regexp validator for your schema value for the property it's used on.

    The first parameter is the Regular Expression and the second parameter is the message returned to your user on a failed match.

    In your case, this is the RegExp:

    /^(?=.{8,20}$)(?![_.])(?!.*[_.]{2})[a-zA-Z0-9._]+(?<![_.])$/
    

    This is the message:

    "Username invalid, it should contain 8-20 alphanumeric letters and be unique!"
    

    Whatever value is passed will be tested against the Regular Expression. You can manipulate the Regular Expression until your hearts content but it is not trival so read up on RegExp and do some testing to make sure it does what you think it does, for example:

    Empty strings, undefined, and null values always pass the match validator. If you require these values, enable the required validator also.