Answer a question

Background

I am defining a Mongoose schema for countries, where I store the country name, and its ISO alpha2 and ISO alpha3 codes.

These ISO codes, are just abbreviations for the country names. For example, Spain is ES, United Sates is US, and so on.

Objective

My objective is to do schema validation so that the codes have the right amount of letters when inserting a country in the collection.

An ISO alpha2 code can only have 2 characters, and an ISO alpha3 code can have 3.

Problem

To achieve this I have a validation function that checks if the given code has the correct size:

const hasValidFormat = (val, size) => val.length === size;  

And I am trying to use this function as my validator:

"use strict";

const mongoose = require("mongoose");

const hasValidFormat = (val, size) => val.length === size; 

const countrySchema = {
    name: { type: String, required: true },
    isoCodes:{
        alpha2: { 
            type: String, 
            required:true,
            validate: {
                validator: hasValidFormat(val, 2),
                message: "Incorrect format for alpha-2 type ISO code."
            }
        },
        alpha3: { 
            type: String,
             validate: {
                validator: hasValidFormat(val, 3),
                message: "Incorrect format for alpha-3 type ISO code."
            }           
        }
    }
};


module.exports = new mongoose.Schema(countrySchema);
module.exports.countrySchema = countrySchema;

The problem is that I have the error val is not defined and the code wont run. This is confusing, because according to the Mongoose docs for custom validators, the validator field is a function!

However

If I change the previous code to:

"use strict";

const mongoose = require("mongoose");

const hasValidFormat = (val, size) => val.length === size; 

const countrySchema = {
    name: { type: String, required: true },
    isoCodes:{
        alpha2: { 
            type: String, 
            required:true,
            validate: {
                validator: val => hasValidFormat(val, 2),
                message: "Incorrect format for alpha-2 type ISO code."
            }
        },
        alpha3: { 
            type: String,
             validate: {
                validator: val => hasValidFormat(val, 3),
                message: "Incorrect format for alpha-3 type ISO code."
            }           
        }
    }
};


module.exports = new mongoose.Schema(countrySchema);
module.exports.countrySchema = countrySchema;

It will work!

Question

Can someone explain me why the first example doesn't work, and the second does?

Answers

This is because the validator function will take only one parameter.

According to the documentation, if the validator function takes two parameters, mongoose will assume the 2nd argument is a callback.

"Custom validators can also be asynchronous. If your validator function takes 2 arguments, mongoose will assume the 2nd argument is a callback."

Source: http://mongoosejs.com/docs/validation.html

You first code fails mainly because Mongoose is seeing it as an async validation, which is not the case. As a golden rule, validation functions should be inline.

You can achieve the behavior you are looking for bu using a closer function, like in the second code sample.

Thanks,

Logo

MongoDB社区为您提供最前沿的新闻资讯和知识内容

更多推荐