What am I doing wrong in this Mongoose unique pre-save validation?
javascript, mongoose, node.js
Solution
To use parallel middleware (with `next` and `done` parameters), you need to pass `true` as the second parameter.
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:
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();
});
Problem
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?