2012-08-08 1 views
22

私はユニークなユーザー名を持つユーザーモデルを作成しようとしています。ここではそのためのコードは次のとおりです。このMongooseのユニークな保存前検証で何が間違っていますか?

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

問題は、それがない、です。コードを実行するたびに、新しいオブジェクトが作成されます。一意性を保証する他の方法があるかもしれないことは承知していますが、私はこのようにしたいと思います。 findOneメソッドの結果を処理した後、私はdoneに電話してはいけませんか?私はnextと間違っていますか?

答えて

28

、あなたは2番目のパラメータとしてtrue渡す必要があります。その向こう

、2つの可能性があります

あなたself.invalidateコールは"username"代わりの"user"を参照する必要があります。それはそれを修正しない場合は、保存操作を中止したい場合は、あなたが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(); 
}); 
+1

これはうまくいきましたが、エラー形式は同じではありません。したがって、APIを構築してエラーオブジェクト形式を数えれば、おそらくその方法に問題が生じます。私はhttps://npmjs.org/package/mongoose-unique-validatorをテストしました。それは私の魅力のように働いていました。エラーオブジェクトはほとんど同じです。 –

+0

私の場合、これはうまくいきませんでした。関数のシグネチャを変更して(次の)引数を1つだけ変更し、次にパラメータを指定せずに次のエラーを呼び出す必要がありました。 – Matus

+0

@Matus 'pre' [ミドルウェア](http://mongoosejs.com/docs/middleware.html):パラレル( 'next'と' done'パラメータ付き)、シリアル( 'next'だけ)。 – JohnnyHK

33

http://mongoosejs.com/docs/api.html#schematype_SchemaType-uniqueです。実際のMongoDbインデックスを使用して、フィールドが一意であることを確認します。 .preミドルウェアは不要です。

お楽しみください! (nextdoneパラメータで)parallel middlewareを使用するには

+7

うんしかし、誰カスタムエラーメッセージ...そして、同じドキュメント上の2つの異なるユニークなエラーとの違いを確認する方法はありません。 @YvesMについてはhttps://groups.google.com/d/msg/mongoose-orm/BX7kz0BwLjk/JWuvD_p4hYcJ –

+2

+1をご覧ください。 Mongooseのドキュメントによると: "注:制約違反**はMongoDBからのE11000エラーを返します**保存時に** Mongoose検証エラー**ではありません" – kuzyn

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

本当にインストールして使いやすいmongooseのプラグインが本当にあります。ドキュメントは素晴らしく、初めての仕事でした。

ただし、再保存に関する問題があります。

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

+0

通常、プロジェクトにもっと多くのモジュールを持ち込むことについては反対ですが、多くの検証を行い、リファクタを統合する必要がなければ、これは必須であると思います – kuzyn

関連する問題