我正在尝试创建一个具有唯一用户名的用户模型。这是代码:
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);
我还在测试是否有独特性:
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();
});
问题是,它没有。每次运行代码时,我都会创建一个新对象。我知道可能有其他方法可以确保唯一性,但我想以这种方式做到这一点。在处理done
方法的结果后,我不应该调用findOne
吗?我打电话给next
错了吗?
答案 0 :(得分:33)
http://mongoosejs.com/docs/api.html#schematype_SchemaType-unique是要走的路。它使用实际的MongoDb索引来确保您的字段是唯一的。不需要.pre
中间件。
享受!
答案 1 :(得分:29)
要使用parallel middleware(包含next
和done
参数),您需要将true
作为第二个参数传递。
除此之外,有两种可能性:
您的self.invalidate
来电应该引用"username"
而不是"user"
。如果这不能解决问题,如果要中止保存操作,则可以通过将Error对象传递给done
来显式失败:
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();
});
答案 2 :(得分:5)
答案 3 :(得分:3)
您是否考虑过使用异步验证程序来捕获错误?
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');