Validate object against Mongoose schema without saving as a new document Validate object against Mongoose schema without saving as a new document mongodb mongodb

Validate object against Mongoose schema without saving as a new document


There is one way to do that through Custom validators. When the validation failed, failed to save document into DB.

var peopleSchema = new mongoose.Schema({        name: String,        age: Number    });var People = mongoose.model('People', peopleSchema);peopleSchema.path('name').validate(function(n) {    return !!n && n.length >= 3 && n.length < 25;}, 'Invalid Name');function savePeople() {    var p = new People({        name: 'you',        age: 3    });    p.save(function(err){        if (err) {             console.log(err);                    }        else            console.log('save people successfully.');    });}

Or another way to do that through validate() with same schema as you defined.

var p = new People({    name: 'you',    age: 3});p.validate(function(err) {    if (err)        console.log(err);    else        console.log('pass validate');});


As explained here in the mongoose documents https://mongoosejs.com/docs/validation.html , you can use doc.validate(callback) or doc.validateSync() to check for validation.

The difference is that you do not have to use await for validateSync() as its name suggests. it returns an error if validation fails, otherwise, it returns undefined.for example:

const model = new Model({somedata:somedata})const validatedModel = model.validateSync()if(!!validatedModel) throw validatedModel


I wrote the following function which doesn't need the model at all, you just pass an object and the Mongoose schema, no matter if it is as a document or a subdocument. Subdocuments are also checked recursively:

const validateObjectAgainstMongooseSchema = ({checkObject, mongooseSchema, currentPath = "object"} = {}) => {    const errors = [];    for (const key of Object.keys(checkObject)) {        const checkObjectType = Array.isArray(checkObject[key]) ? "array" : typeof checkObject[key];        const mongooseType = mongooseSchema.path(key).instance.toLowerCase();        const valid = mongooseType === checkObjectType;        if (checkObjectType === "object") {            errors.push(                ...validateObjectAgainstMongooseSchema({                    checkObject: checkObject[key],                    mongooseSchema: mongooseSchema.path(key).schema,                    currentPath: `${currentPath}.${key}`                })            );        } else if (!valid) {            errors.push(`${currentPath}.${key} should be of type ${mongooseType} but got ${checkObjectType}`);        }    }    return errors;};

when using the following schema:

const schema = new mongoose.Schema({        stringType: {            type: String        },        numberType: {            type: Number        },        dateType: {            type: Date        },        boolType: {            type: Boolean        },        arrayType: {            type: Array        },        schemaType: {            type: new mongoose.Schema({                embeddedDate: {                    type: Date                },                embeddedBool: {                    type: Boolean                }            })        }    });

the following yields an empty array

const errors = schemaUtils.helpers.validateObjectAgainstMongooseSchema({            checkObject: {                stringType: "test",                numberType: 2,                dateType: new Date("2020-01-01"),                boolType: true,                arrayType: ["test", "it"],                schemaType: {embeddedDate: new Date("2020-01-02"), embeddedBool: true}            },            mongooseSchema: schema        });

and this

const errors = schemaUtils.helpers.validateObjectAgainstMongooseSchema({            checkObject: {                stringType: 1,                numberType: "1",                dateType: 1,                boolType: 1,                arrayType: 1,                schemaType: {embeddedDate: 1, embeddedBool: 1}            },            mongooseSchema: schema        });

yields:

[      'object.stringType should be of type string but got number',      'object.numberType should be of type number but got string',      'object.dateType should be of type date but got number',      'object.boolType should be of type boolean but got number',      'object.arrayType should be of type array but got number',      'object.schemaType.embeddedDate should be of type date but got number',      'object.schemaType.embeddedBool should be of type boolean but got number'    ]