Mongoose {strict:throw}不会抛出错误

kyvafyod  于 2023-03-30  发布在  Go
关注(0)|答案(3)|浏览(108)

我到处找这个问题的答案,但似乎我运气不好。
我有一个非常简单的 Mongoose 模型

var userObject = {
    profile: {
        username: {
            type: String,
            required: true,
            lowercase: true
        },
        firstname: {
            type: String,
            required: true
        },
        lastname: {
            type: String,
            required: true
        },
        img: {
            type: String,
            required: true,
            match: /^(https?:\/\/)/i
        },
        email: {
            type: String,
            match: /^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/,
            required: true
        },
        singupdate: {
            type: Date,
            default: Date.now
        }
    }
};

而且,当我创建模式时,我选择了在添加不在模型中的属性时抛出错误的选项。

new mongoose.Schema(userObject, { strict: "throw" });

这就是我试图捕获错误的方式。当我添加有效属性时,进程运行,我收到创建的文档,但当我添加无效属性时,进程永远不会退出,并且日志永远不会出现在控制台上。

try {
    User.create(users, function(err, docs) {
        console.log("err: " + err);
        console.log("docs: " + docs);
    });
} catch (e) {
    console.log(e.message);
}

我哪里做错了?

qzwqbdag

qzwqbdag1#

医生说:
https://mongoosejs.com/docs/guide.html#strict
strict选项(默认情况下启用)确保传递给模型构造函数的、在模式中未指定的值不会保存到数据库中
strict选项也可以被设置为“throw”,这将导致产生错误而不是丢弃坏数据。
但这并不意味着你认为它的意思。
注意:无论schema选项是什么,在示例上设置的任何键/瓦尔,如果在schema中不存在,都将被忽略。
因此,“坏数据”只包含模式中但格式错误的数据。模式中任何多余的数据NOT将被默默删除,导致最大的毛发损失并违反POLA。

34gzjxbg

34gzjxbg2#

如果您添加的属性不是模型的一部分,请从mongoose文档:
strict选项(默认情况下启用)确保传递给模型构造函数的、在模式中未指定的值不会保存到数据库中
即使在strict:throw中也是这样工作的,所以您不必担心模型中没有引用的其他字段。
关于未触发的异常,Aaron Heckmann在this post中谈到了在save上未触发的异常,其中strict : throw
这更像是对mongoose工作原理的误解。“strict”选项启用了对试图存储在数据库中的键/值的验证。schemas在延迟到已验证的doc.{g,s}et()方法的文档示例上创建getter/setter。将 adhoc 数据附加到mongoose文档示例不会触发get/set(),因此不需要进行验证,因为“strict”选项会在doc.{g,s}et()方法中执行。It“那天不可能保存到数据库中。
由于附加字段不是模型的一部分,它们不会触发这些验证,因此不会触发异常(当然,这些字段不会保存在数据库中)
只有当属于模型的字段未通过此验证时,才会引发异常

kh212irz

kh212irz3#

正如其他答案所提到的,设置strict只会影响实际存在于模型模式中的键。因此,如果你想让它在尝试设置无效字段时抛出错误,你需要检查键是否存在于模型的模式中。下面是一个如何做到这一点的例子:

const obj = await MyModel.findOne(...)
for (const key in req.body) {
  if (typeof Property.schema.obj[key] === 'undefined') {
    throw new Error(`Invalid property: ${key}`)
  }
  obj[key] = req.body[key]
}
obj.save()

这里有一个使用Document中间件的方法(只要属性名不以$_开头)。然而,我不知道如何在 Query 中间件中截断更新的值之前获得它们。如果有人能解决这个问题,请随时更新这个答案。

mySchema.pre('validate', async function () {
  for (const key of Object.keys(this)) {
    if (!/^\$|_/.test(key) && typeof MyModel.schema.obj[key] === 'undefined') {
      throw new Error(`Invalid property: ${key}`)
    }
  }
})

相关问题