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?

Original source