【问题标题】:How can I provide default validation for all instances of a custom mongoose SchemaType?如何为自定义 mongoose SchemaType 的所有实例提供默认验证?
【发布时间】:2021-09-17 21:47:35
【问题描述】:

我已按照 mongoose 文档创建 Custom Schema Types。我的实现是功能性的,但没有产生我想要的结果。

我的目标是拥有一个自定义 schemaType,它在转换失败(或转换成功但验证失败时)提供自定义错误消息,而不必在每次在我的 api 模式中使用数据类型时声明验证方法。

这里是一个例子(我会尝试在 cmets 中解释):

const mongoose = require('mongoose')

// Create Custom Schema Type
class UUIDv4 extends mongoose.SchemaType {
    constructor(key, options) {
        super(key, options, 'UUIDv4');
    }

    cast(val) {
        if (/*Do UUIDv4 validation check here*/) {

            /* Because of the way mongoose works, this error message is difficult
               to present to a user because the built-in casting error message is 
               always used at the top level.
             */
            throw new Error(`${val} is not a valid version 4 UUID`);
        }
        return val;
    }
}

// Add `UUIDv4` to the type registry
mongoose.Schema.Types.UUIDv4 = UUIDv4;

const entitySchema = new mongoose.Schema({
    entityKey: {
        type: UUIDv4,
        required: true
    }
})

const Entity = mongoose.model('Entity', entitySchema)

const testEntity = new Entity({
    entityKey: "123456789"
})

testEntity.save().then(() => {
    console.log('done')
}).catch((e) => {
    console.log(e.errors.entityKey.reason.message) // This is where the custom message can be found
})

显然,我可以跳过创建自定义 SchemaType,但我希望避免每次在我的模式中使用 entityKey 时都必须指定自定义验证器(它们被大量使用)。

const UUIDv4Validator = {
    validator: function(v) {
        // If is valid. . . return true
        // else return false
    },
    message: 'Invalid UUIDv4'
}

const entitySchema = new mongoose.Schema({
    entityKey: {
        type: String,
        required: true,
        validate: UUIDv4Validator // I don't want to have to do this every time
    }
})

我知道我可以保留自定义模式类型并使用可选的链接运算符在我的 try/catch 语句中检查是否存在此错误,但我宁愿避免这种需要,因为它会重复:

try {
    // do stuff . . .
    await testEntity.save()
} catch (e) {
    const message = e?.errors?.entityKey?.reason?.message ?? e.message. // No thank you!
    // do stuff . . .
}

我尝试阅读文档以了解如何为自定义模式类型创建自定义验证方法,但我未能成功尝试任何工作,并且到目前为止我还没有在网上找到任何示例。

如何将自定义验证器永久链接到我的 UUIDv4 自定义架构类型,以评估尝试保存的数据,并在适当时返回我的自定义错误消息?

【问题讨论】:

    标签: javascript node.js mongodb mongoose mongoose-schema


    【解决方案1】:

    我通过点击 mongoose SchemaTypes documentation 中的链接并挖掘了一些 mongoose 插件的源代码找到了答案。

    本质上,要制作一个普遍应用于 mongoose SchemaType 的所有实例的自定义验证器,应该将验证器直接传递给 SchemaType 的 validate() 方法。

    在自定义的 SchemaType 类定义中,可以通过在类构造函数中调用 super 的验证器方法来完成。这是一个例子:

    class UUIDv4 extends mongoose.SchemaType {
        constructor(key, options) {
            super(key, options, 'UUIDv4');
            
            // Call the validate method of super and pass in a validator
            // function and a message to return when validation fails
            this.validate(function(val){
                return isUUIDv4(val) // Example UUIDv4 validation check
            }, '{PATH}: "{VALUE}" is not a valid version 4 UUID')
        }
        
        // Other class methods such as cast(), etc. . .
    }
    

    如文档所示(以及我的原始问题)猫鼬validators 接受一个对象{},其中包含validatormessage。尽管它们经常被添加到模式中以提供对特定字段/路径的自定义验证,但可以通过调用 SchemaType.validate()(其中 SchemaType 替换为实际的 SchemaType 名称,即 String)并传入,将它们添加到 schemaType 的整体验证中验证器函数和消息作为两个单独的参数。

    对于那些使用自定义 SchemaTypes 的人,例如在我的用例中,可以通过让 cast() 方法始终返回 true 并仅处理 save() 上的验证来从验证器获取所需的错误消息。

    【讨论】:

      猜你喜欢
      • 2020-03-29
      • 1970-01-01
      • 2019-05-21
      • 1970-01-01
      • 2023-03-15
      • 2012-12-11
      • 1970-01-01
      • 1970-01-01
      • 2015-03-11
      相关资源
      最近更新 更多