无论模式约束如何,我都可以使用 model.Update 方法更新到任何值
例如,如果我有一个带有 enum 属性的 Schema,使用 update 我可以更改为 enum 约束之外的任何值,从而使集合无效。
如果更新的值未验证,则预期行为将引发错误。
我建议更新方法的一个额外选项,以便在出现第一个错误时退出。
您可能希望启用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 个特殊选项, setDefaultsOnInsert
和runValidators
,它们将设置默认值并在您的查询上运行验证器。 例如,请参阅测试,还没有真正的文档:(
非常感谢 - 这是一个很好的修复!
@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请不要在没有任何有意义信息的情况下评论长期关闭的问题。 用代码示例打开一个单独的问题。
最有用的评论
+1
更新不使用:默认值、设置器、验证和枚举是完全不直观的。 如果核心操作不遵守它,那么架构有什么用。