Javascript 我在这个 Mongoose 独特的预保存验证中做错了什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11872556/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What am I doing wrong in this Mongoose unique pre-save validation?
提问by Geo
I'm trying to create a User model, that has an unique username. Here's the code for it:
我正在尝试创建一个用户模型,它具有唯一的用户名。这是它的代码:
var mongoose = require("mongoose");
var Schema = mongoose.Schema;
var UserSchema = new Schema({
username: String,
password: String,
});
UserSchema.virtual("password_confirmation").get(function() {
return this.pw_conf;
}).set(function(value) {
this.pw_conf = value;
});
UserSchema.path("username").required(true);
UserSchema.path("password").required(true);
UserSchema.pre("save",function(next, done) {
var self = this;
mongoose.models["User"].findOne({username : self.username},function(err, user) {
if(user) {
self.invalidate("user","username must be unique");
}
done();
});
next();
});
UserSchema.pre("save",function(next) {
if(this.pw_conf !== this.password) {
next(new Error("Must specify the password confirmation"));
}
else {
next();
}
});
module.exports = mongoose.model("User",UserSchema);
I was also testing to see if the uniqueness works:
我也在测试唯一性是否有效:
var User = require("./users"),
mongoose = require("mongoose");
var u = new User();
mongoose.connect('mongodb://localhost/my_database');
u.username = "me";
u.password = "password";
u.password_confirmation = "password";
u.save(function(err) {
if(err) {
console.log(err);
}
mongoose.disconnect();
});
Problem is, it doesn't. Each time I run the code, I get a new object created. I am aware that there are probably other ways of ensuring uniqueness, but I'd like to do it in this way. Shouldn't I be calling done
after I handle the result of the findOne
method? Am I calling next
wrong?
问题是,它没有。每次运行代码时,都会创建一个新对象。我知道可能还有其他方法可以确保唯一性,但我想这样做。done
处理完findOne
方法的结果后,我不应该调用吗?我叫next
错了吗?
回答by rdrey
http://mongoosejs.com/docs/api.html#schematype_SchemaType-uniqueis the way to go. It uses actual MongoDb indexes to make sure that your field is unique. No need for .pre
middleware.
http://mongoosejs.com/docs/api.html#schematype_SchemaType-unique是要走的路。它使用实际的 MongoDb 索引来确保您的字段是唯一的。不需要.pre
中间件。
Enjoy!
享受!
回答by JohnnyHK
To use parallel middleware(with next
and done
parameters), you need to pass true
as the second parameter.
要使用并行中间件(带next
和done
参数),您需要true
作为第二个参数传递。
Beyond that, there are two possibilities:
除此之外,还有两种可能:
Your self.invalidate
call should be referencing "username"
instead of "user"
. If that doesn't fix it, you can fail things explicitly by passing an Error object to done
if you want to abort the save operation:
您的self.invalidate
电话应该是引用"username"
而不是"user"
. 如果这不能解决它,done
如果您想中止保存操作,您可以通过将 Error 对象传递给显式失败:
UserSchema.pre("save", true, function(next, done) {
var self = this;
mongoose.models["User"].findOne({username: self.username}, function(err, user) {
if(err) {
done(err);
} else if(user) {
self.invalidate("username", "username must be unique");
done(new Error("username must be unique"));
} else {
done();
}
});
next();
});
回答by thomas-peter
There's a really good plugin for mongoose that's really easy to install and use. The documentation is excellent and it worked for me first time.
有一个非常好的 mongoose 插件,非常易于安装和使用。文档非常好,第一次对我有用。
But there is an issue with re-saving.
但是重新保存存在问题。
回答by furf
Have you considered using an asynchronous validator to catch the error?
您是否考虑过使用异步验证器来捕获错误?
UserSchema.path('username').validate(function (value, done) {
User.count({ username: value }, function (error, count) {
// Return false if an error is thrown or count > 0
done(!(error || count));
});
}, 'unique');