Mongoose: 模型更新方法不尊重验证器

创建于 2012-04-24  ·  59评论  ·  资料来源: Automattic/mongoose

无论模式约束如何,我都可以使用 model.Update 方法更新到任何值

例如,如果我有一个带有 enum 属性的 Schema,使用 update 我可以更改为 enum 约束之外的任何值,从而使集合无效。

如果更新的值未验证,则预期行为将引发错误。

我建议更新方法的一个额外选项,以便在出现第一个错误时退出。

new feature

最有用的评论

+1

更新不使用:默认值、设置器、验证和枚举是完全不直观的。 如果核心操作不遵守它,那么架构有什么用。

所有59条评论

您可能希望启用strict模式设置,它将忽略任何无效的模式路径并更新其余路径。 没有错误被抛出。

新架构({..},{严格:真})

有一个类似的拉取请求等待合并,在设置模式中不存在的路径时抛出,但在model.update期间不会抛出。 也许我们应该将其添加到上面的 PR 并将错误传递给回调。

您好,再次感谢您的快速回复。

我不是指无效路径,而是指特定路径内的约束。

拿这个例子

var 用户 = 新架构({
用户名: {
类型:字符串,
小写:真,
修剪:真实,
独特:真实
},
姓名: {
类型:字符串,
修剪:真实,
要求:真实,
独特的:假的,
指数:真
},
密码: {
类型:字符串,
要求:真实,
选择:假,
设置:加密
},
角色: {
类型:字符串,
“默认”:“用户”,
"enum": ['user', 'admin', 'root']
},
创建:{
类型:日期,
“默认”:Date.now
}
}, { 严格:真});

users.update({"username" : "test"}, {"role" : "thisShowldFail"}, function (err, val){
...
});

请注意,即使启用了严格模式选项,现在“test”用户也具有角色“thisShowldFail”。
更新不应该尊重枚举和其他类似的选项吗?

你是对的,它应该验证枚举。 我以为在某个地方有一张票。

+1,由于此问题,无法使用 #update。

是否可以让 .update 制作新文档 + .save 可以做的所有事情?

  • 默认值
  • 二传手
  • 自定义验证
  • 枚举

如果使用 upsert 选项,也

  • 必需的

不是现在

我的意思是有可能/计划实施......? :)

它可能很好。 相关 #472

+1

更新不使用:默认值、设置器、验证和枚举是完全不直观的。 如果核心操作不遵守它,那么架构有什么用。

+1

我喜欢猫鼬,但如果它不验证更新,它对我的​​帮助就会小得多。 我有大文件,我不想下载它们只是为了进行验证。

这是我跳进去的。我正在尝试一下,试图实现这一点。
目标是获得:

  • 默认值
  • 二传手
  • 验证
  • 枚举
  • 必需的

甚至不确定我会成功,但我会试一试。 我将从验证器开始。

祝我好运!

梅尔。

+1

+1

如果.update支持验证,那就太好了。

撞击 +1

凹凸不平+1

请在更新时添加验证!

+1

编辑:-2 因为我认为 mongoose 不应该负责验证。

@thalesfsp是的。 过去曾尝试过,但规则变得非常不稳定,因为内存中不存在文档并且在多种情况下会崩溃,从而导致行为不一致和混乱。

开源的美妙之处:如果你想要一个特性,你可以编写它并提交一个拉取请求,并通过测试和证明它正常工作的文档。

一个相当严重的限制。 在寻求补丁时,直接抓取 Schema 对象以确定是否应该运行验证器是否可行? 我主要关心应用于更新的自定义验证器和枚举规则。 我认为,在保存文档时应该已经应用了其他模式约束。 将问题简化为枚举和验证器是否有意义,并且在更新期间不需要任何文档?

+1 Bump,这将是一个非常有用的功能 - 在进行更新时,我希望从架构中看到最小/最大等 - 否则我正在为猫鼬可以做的事情做很多样板逻辑

很高兴看到这种情况发生。 目前我的解决方法是找到对象,更改字段然后保存它,这会触发验证中间件。 根据文档

Tank.findById(id, function (err, tank) {
  tank.size = 'large';
  tank.save(function (err) {
   // Document updated, do something with it
  });
});

我知道这很棘手,因为update命令直接委托给 Mongo,并且整个文档不在内存中进行验证。 因此, @BrianHoldsworth建议的方法似乎是一个不错的起点,仅针对要更新的字段解析模式运行验证。

@aheckmann您能否向我们提供有关先前(失败的)实施工作的更多详细信息,以便尝试此补丁的人不会再次犯同样的错误?

我主要关心应用于更新的自定义验证器和枚举规则。 我认为,在保存文档时应该已经应用了其他模式约束。 将问题简化为枚举和验证器是否有意义,并且在更新期间不需要任何文档?

@BrianHoldsworth我认为这可能过于简单化了。 如果带有required: true验证约束的字段更新为空字符串,会发生什么情况? 我们需要它来触发验证错误。

我也对这个感兴趣。 也许可以编写一个插件来覆盖 .update() 方法并运行验证? 这样,即使是部分解决方案也可以实现。 另一方面,如果它在核心中,则有望处理各种验证并 100% 稳健。

我也遇到过这个问题,有自定义验证器和枚举。 虽然可以先查找然后更新,但当文档具有不同的子文档结构时,编写通用案例代码确实非常困难。

+1撞这个。

布赖恩的解决方案看起来很优雅。 希望在补丁达到测试版时收到通知。

+1

需要这个+1

+1

+1

+1

+1

在 3.9.3 update()将有 2 个特殊选项, setDefaultsOnInsertrunValidators ,它们将设置默认值并在您的查询上运行验证器。 例如,请参阅测试,还没有真正的文档:(

非常感谢 - 这是一个很好的修复!

@vkarpov15我使用您的代码也将验证应用于 findOneAndUpdate。 参见 PR #2393。

嗨,您知道什么时候会发布稳定版 3.9 以便在更新时使用验证吗?

谢谢

@AlexandreAWE好问题。 我目前正在对 4.0 和 3.9.x 分支进行 beta 测试,但现在它是“完成后就会完成”的事情。 我希望在圣诞节前有一个 RC。

@vkarpov15 3.9.x 稳定版

@andrewholsted正在等待mongodb 驱动程序 2.0和 mongodb 服务器 2.8 稳定下来——这有望在本月发生,但如果不支持最新版本的 mongodb 和最新驱动程序,就无法真正发布 4.0。 有关更多详细信息,请参阅我的博客

我可能提出了一个愚蠢的问题,但为什么不在传递给 mongodb 之前获取正在更新的数据并根据模式验证该数据?

另外,+1

标记并等待

等不及 3.9 稳定了:)

这个功能还在吗? 热切等待3.9..文会上市吗?

您可以npm install mongoose@unstable获取不稳定版本。 当前 4.0 的预计到达时间是 3 月 25 日 - 一个查看里程碑页面的好地方

昨晚刚遇到这个问题。 很高兴我不是唯一一个! 我很高兴能够发布此更改,感谢您所做的一切!

+1

不知道为什么这个问题被标记为关闭。 我还在面对。

我实际上不确定这是否适用于 findOneAndUpdate() 的枚举验证,即使 runValidators 设置为 true。

@m1cah请提供示例来说明您正在尝试做什么。 我们确实有这方面的测试,他们通过了……

@vkarpov15我相信这是一个演示它的简短示例: http : //code.runnable.com/VYhGbVhereIYdbst/update-validation-enum-for-mongoose-and-databases

一个问题是上面的例子使用的是史前版本的猫鼬:

root<strong i="6">@runnable</strong>:~# head node_modules/mongoose/package.json                                                                                                                 
{                                                                                                                                                                         
  "name": "mongoose",                                                                                                                                                     
  "description": "Elegant MongoDB object modeling for Node.js",                                                                                                           
  "version": "3.6.14",                                                                                                                                                    
  "author": {                                                                                                                                                             
    "name": "Guillermo Rauch",                                                                                                                                            
    "email": "[email protected]"                                                                                                                                   
  },                                                                                                                                                                      
  "keywords": [                                                                                                                                                           
    "mongodb",  

尝试升级到 4.x,它应该可以工作。

您确定它适用于枚举和 findOneAndUpdate 方法吗?
在 mongoose 4.2.6 上它似乎失败了,我可以设置一个错误的值。

架构:

var UserSchema = new Schema({
    first_name: {
        type: String,
        required: true,
    },
    last_name: {
        type: String,
        required: true,
    },
    email: {
        type: String,
        unique: true,
        required: true,
    },
    embededData: [{
        type: {
            type: String,
            enum: ['value1', 'value2', 'value3']
            required: true
        }
    }]
}, { strict: true });

FindOneAndUpdate 方法:

UserModel.findOneAndUpdate(
    {_id: uid}, 
    {$push: {embededData: data}}, 
    { runValidators: true }, function(err) {
});

然后我可以推embededData.type = 'Panda';

请参阅更新验证器文档和 #2933 - 更新验证器不在$push ,仅在$set$unset

+1

据我所知,这仍然不适用于您在数组字段上使用自定义验证器的情况。

例如,这个代码片段:

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/myTestDB');

var db = mongoose.connection;

db.on('error', function (err) {
console.log('connection error', err);
});
db.once('open', function () {
console.log('connected.');
});

var Schema = mongoose.Schema;
var userSchema = new Schema({
  _id : String,
  name : {
    type: [String],
    validate: {
        validator: function (str) {
            return str.length > 1
        }
    },
  }
});


var User = mongoose.model('User', userSchema);

User.findOneAndUpdate({"name": ["John", "Doe"]}, { 
  $setOnInsert: {
    name: ["John"],
  },
}, { runValidators: true, upsert: true, new: true }, function (err, data) {
  if (err) {
    return console.log(err);
  } else {
    // console.log(data.validateSync())
    return console.log('Updated', data);
  }
});

将允许您将用户更新为具有 ["John"] 的name字段而不会引发任何错误,即使我包含的自定义验证器明确禁止任何长度小于或等于 1 的名称数组。验证器本身工作得很好,从以下事实可以看出,如果您取消注释console.log(data.validateSync()) ,从而强制进行验证,它实际上会返回适当的错误消息。 问题是这个验证没有在findOneAndUpdate()调用中进行,尽管我包含了runValidators=true选项。

看起来像一个错误,你能为此打开一个单独的问题吗?

谢谢

是否有针对上述问题的修复程序? @vkarpov15

@Saravanan90请不要在没有任何有意义信息的情况下评论长期关闭的问题。 用代码示例打开一个单独的问题。

此页面是否有帮助?
0 / 5 - 0 等级