【问题标题】:mongoose conditional required field validation猫鼬条件必填字段验证
【发布时间】:2019-03-15 05:07:59
【问题描述】:

根据猫鼬built-in validators documentations,我可以使用条件必填字段:

const schema = mongoose.Schema({
    a: {
        type: String,
        required: function () {
            return this.b === 1
        }
    },
    b: {
        type: Number,
        required: true
    }
});

在此架构中,仅当属性 b 等于 1 时才需要属性 a。

尝试创建新文档按预期工作:

Model.create({ b: 1 }); // throws ValidationError (property a is required)

和

Model.create({ b: 2 }); // creates document

我的问题是尝试更新现有文档并将属性b 设置为1,因此应该需要属性a。

运行以下代码:

Model.findByIdAndUpdate(model._id, { b: 1 }, { new: true, runValidators: true});

意外地更新了文档,但没有抛出需要属性a 的错误。

我的猜测是验证只针对更新后的属性(属性b)而不是整个文档运行。

我不确定这是预期的行为还是错误...

我错过了什么吗? 有什么方法可以运行整个文档的验证器,而不仅仅是更新的属性,而无需之前手动获取文档?

【问题讨论】:

    标签: node.js mongodb mongoose mongoose-schema


    【解决方案1】:

    您必须实现通常称为“钩子”的中间件,您可以阅读更多内容 并实现您的需求 https://mongoosejs.com/docs/middleware.html

    【讨论】:

    • 这是不正确的,如果我只更新属性b,则使用钩子我无法访问属性a,因此如果不获取之前的文档,仍然无法验证该字段。
    【解决方案2】:

    在尝试了中间件和验证器但没有成功后,我可以通过使用transactions 来实现这个要求(可从MongoDB 4.0 和Mongoose 5.2.0 获得)

    // Create a transaction session
    const session = await mongoose.startSession();
    session.startTransaction();
    
    // Fetch the model (pass the session)
    const model = await Model.findById(modelId).session(session);
    
    // ... update your model here
    
    // Validate the schema
    if (model.b === 1 && !model.a) {
        throw new mongoose.ValidationError('property a is required');
    }
    
    // Save the changes
    await model.save();
    await session.commitTransaction();
    

    请注意,我没有将session 附加到save 函数,因为它已经通过使用find 获取模型而附加:

    如果您使用会话从 findOne() 或 find() 获取 Mongoose 文档,该文档将保留对该会话的引用并将该会话用于 save()。

    我发现这种方法的一个问题是MongoDB 目前仅在副本集上支持transactions。 可以选择使用run-rs在本地运行它而无需复制集进行开发@

    要在 macOS、Linux 或 Windows 上运行本地副本集进行开发,请使用 npm 全局安装 run-rs 并运行 run-rs --version 4.0.0。 Run-rs 会为你下载 MongoDB 4.0.0。

    有关更多信息,您可以查看Mongoose documentations 的交易和MongoDB documentations

    【讨论】:

      猜你喜欢
      • 2021-08-27
      • 2021-05-06
      • 2014-02-23
      • 1970-01-01
      • 1970-01-01
      • 2016-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多