我在这个Mongoose独特的保存前validation中做错了什么?

我正在尝试创build一个用户模型,它有一个唯一的用户名。 这是它的代码:

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); 

我也在testing,看看是否唯一性的作品:

 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(); }); 

问题是,它没有。 每次运行代码,我都会得到一个新的对象。 我知道,确保唯一性可能还有其他的方法,但我想这样做。 在处理findOne方法的结果之后,我不应该调用done吗? 我打电话错了吗?

要使用并行中间件 (使用nextdone参数),需要传递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(); }); 

http://mongoosejs.com/docs/api.html#schematype_SchemaType-unique是要走的路。 它使用实际的MongoDb索引来确保您的字段是唯一的。 不需要.pre中间件。

请享用!

有一个非常好的mongoose插件,很容易安装和使用。 文档非常好,第一次为我工作。

但是,重新保存有一个问题。

https://npmjs.org/package/mongoose-unique-validator

你有没有考虑过使用asynchronousvalidation器来捕获错误?

 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');