18

我正在尝试验证将插入到新文档中的一些数据,但不是在许多其他事情需要发生之前。因此,我将向静态方法添加一个函数,该函数有望根据模型模式验证数组中的对象。

到目前为止的代码如下:

module.exports = Mongoose => {
    const Schema = Mongoose.Schema

    const peopleSchema = new Schema({
        name: {
            type: Schema.Types.String,
            required: true,
            minlength: 3,
            maxlength: 25
        },
        age: Schema.Types.Number
    })

    /**
     * Validate the settings of an array of people
     *
     * @param   {array}     people  Array of people (objects)
     * @return  {boolean}
     */
    peopleSchema.statics.validatePeople = function( people ) {
        return _.every(people, p => {
            /**
             * How can I validate the object `p` against the peopleSchema
             */
        })
    }

    return Mongoose.model( 'People', peopleSchema )
}

所以这peopleSchema.statics.validatePeople就是我试图进行验证的地方。我已经阅读了猫鼬验证文档,但它没有说明如何在不保存数据的情况下验证模型。

这可能吗?

更新

这里的一个答案向我指出了正确的验证方法,这似乎有效,但现在它抛出了一个Unhandled rejection ValidationError.

这是用于验证数据的静态方法(插入)

peopleSchema.statics.testValidate = function( person ) {
    return new Promise( ( res, rej ) => {
        const personObj = new this( person )

        // FYI - Wrapping the personObj.validate() in a try/catch does NOT suppress the error
        personObj.validate( err => {
            if ( err ) return rej( err )

            res( 'SUCCESS' )
        } )
    })
}

然后我测试一下:

People.testValidate( { /* Data */ } )
    .then(data => {
        console.log('OK!', data)
    })
    .catch( err => {
        console.error('FAILED:',err)
    })
    .finally(() => Mongoose.connection.close())

使用不遵循架构规则的数据对其进行测试会引发错误,如您所见,我试图捕捉它,但它似乎不起作用。

PS我用 Bluebird 来兑现我的承诺

4

3 回答 3

5

有一种方法可以通过Custom validators. 验证失败时,无法将文档保存到数据库中。

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.');
    });
}

或者通过validate()与您定义的相同模式来实现此目的的另一种方法。

var p = new People({
    name: 'you',
    age: 3
});

p.validate(function(err) {
    if (err)
        console.log(err);
    else
        console.log('pass validate');
});
于 2016-01-31T03:44:34.050 回答
2

如 mongoose 文档https://mongoosejs.com/docs/validation.html中所述,您可以使用doc.validate(callback)doc.validateSync()检查验证。

不同之处在于你不必像它的名字所暗示的那样使用awaitfor 。validateSync()如果验证失败,则返回错误,否则返回undefined. 例如:

const model = new Model({somedata:somedata})

const validatedModel = model.validateSync()
if(!!validatedModel) throw validatedModel
于 2020-10-29T16:32:47.687 回答
0

我编写了以下根本不需要模型的函数,您只需传递一个对象和 Mongoose 模式,无论它是作为文档还是子文档。子文档也被递归检查:

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;
};

使用以下架构时:


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
                }
            })
        }
    });

以下产生一个空数组

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
        });

和这个

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

产量:

[
      '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'
    ]
于 2021-09-15T15:53:20.097 回答