如何执行一个Mongoosevalidationfunction只用于创build用户页面,而不是编辑用户页面?

背景
我目前正在用Node.js,Express和MongoDB构build一个网站。 我正在使用mongoose与我的MongoDB服务器一起工作。 现在我在Mongoose模式中有一个函数,用来检查用户input的电子邮件地址是否已经存在于数据库中。 我希望这个函数只能在创build账户页面上调用。 任何帮助将不胜感激! 谢谢!

问题
该function很好用,但是在编辑用户个人资料页面以及创build用户页面时会被调用。 这意味着,如果用户在编辑个人资料页面上没有更改他们的电子邮件,他们不能更新他们的个人资料。 我只想要这个validation独特的电子邮件function被称为创build用户页面,所以我可以避免这个问题。 我如何根据用户所在的页面来运行一个函数?

代码
函数在我的用户架构来检查电子邮件是否已经存在

UserSchema.path('email').validate(function(value, done) { this.model('User').count({ email: value }, function(err, count) { if (err) { return done(err); } // If `count` is greater than zero, "invalidate" done(!count); }); }, 'Email already exists'); 

整个用户架构(文件名是user.server.model.js)

 'use strict'; /** * Module dependencies. */ var mongoose = require('mongoose'), Schema = mongoose.Schema, crypto = require('crypto'); /** * A Validation function for local strategy properties */ var validateLocalStrategyProperty = function(property) { return ((this.provider !== 'local' && !this.updated) || property.length); }; /** * A Validation function for local strategy password */ var validateLocalStrategyPassword = function(password) { return (this.provider !== 'local' || (password && password.length > 6)); }; /** * User Schema */ var UserSchema = new Schema({ firstName: { type: String, trim: true, default: '', validate: [validateLocalStrategyProperty, 'Please fill in your first name'] }, lastName: { type: String, trim: true, default: '', validate: [validateLocalStrategyProperty, 'Please fill in your last name'] }, displayName: { type: String, trim: true }, companyName: { type: String, trim: true, default: '' }, companyWebsite: { type: String, trim: true, default: '' }, companyAddress1: { type: String, trim: true, default: '' }, companyAddress2: { type: String, trim: true, default: '' }, companyCity: { type: String, trim: true, default: '' }, companyState: { type: String, trim: true, default: '' }, companyZip: { type: String, trim: true, default: '' }, phone: { type: String, trim: true, default: '' }, email: { type: String, trim: true, default: '', unique: true, validate: [validateLocalStrategyProperty, 'Please fill in your email'], match: [/.+\@.+\..+/, 'Please fill a valid email address'] }, username: { type: String, unique: 'testing error message', required: 'Please fill in a username', trim: true }, password: { type: String, default: '', validate: [validateLocalStrategyPassword, 'Password should be longer'] }, salt: { type: String }, provider: { type: String, required: 'Provider is required' }, providerData: {}, additionalProvidersData: {}, roles: { type: [{ type: String, enum: ['user', 'admin'] }], default: ['user'] }, updated: { type: Date }, created: { type: Date, default: Date.now }, /* For reset password */ resetPasswordToken: { type: String }, resetPasswordExpires: { type: Date } }); /** * Hook a pre save method to hash the password */ UserSchema.pre('save', function(next) { if (this.password && this.password.length > 6) { this.salt = new Buffer(crypto.randomBytes(16).toString('base64'), 'base64'); this.password = this.hashPassword(this.password); } next(); }); /** * Check if email already exists in database */ UserSchema.path('email').validate(function(value, done) { this.model('User').count({ email: value }, function(err, count) { if (err) { return done(err); } // If `count` is greater than zero, "invalidate" done(!count); }); }, 'Email already exists'); /** * Create instance method for hashing a password */ UserSchema.methods.hashPassword = function(password) { if (this.salt && password) { return crypto.pbkdf2Sync(password, this.salt, 10000, 64).toString('base64'); } else { return password; } }; /** * Create instance method for authenticating user */ UserSchema.methods.authenticate = function(password) { return this.password === this.hashPassword(password); }; /** * Find possible not used username */ UserSchema.statics.findUniqueUsername = function(username, suffix, callback) { var _this = this; var possibleUsername = username + (suffix || ''); _this.findOne({ username: possibleUsername }, function(err, user) { if (!err) { if (!user) { callback(possibleUsername); } else { return _this.findUniqueUsername(username, (suffix || 0) + 1, callback); } } else { callback(null); } }); }; mongoose.model('User', UserSchema); 

users.server.routes.js文件

 'use strict'; /** * Module dependencies. */ var passport = require('passport'); module.exports = function(app) { // User Routes var users = require('../../app/controllers/users.server.controller'); // Setting up the users profile api app.route('/users/me').get(users.me); app.route('/users').put(users.update); app.route('/users/accounts').delete(users.removeOAuthProvider); // Setting up the users password api app.route('/users/password').post(users.changePassword); app.route('/auth/forgot').post(users.forgot); app.route('/auth/reset/:token').get(users.validateResetToken); app.route('/auth/reset/:token').post(users.reset); // Setting up the users authentication api app.route('/auth/signup').post(users.signup); app.route('/auth/signin').post(users.signin); app.route('/auth/signout').get(users.signout); // Finish by binding the user middleware app.param('userId', users.userByID); }; 

您可以使用Document.isNew标志仅运行创build检查。 喜欢这个:

 UserSchema.pre('save', function(next) { if (this.isNew) { // Enforce constraints here } if (this.password && this.password.length > 6) { this.salt = new Buffer(crypto.randomBytes(16).toString('base64'), 'base64'); this.password = this.hashPassword(this.password); } next(); }); 

您也可以使用Document.isModified ,所以在保存钩子时,您也可以检查this.isModified('email')

比你安德鲁Lavers。 我认为他的答案将工作得很好,但我最终做的只是在模式中使用我的电子邮件的唯一索引validation。

 email: { type: String, trim: true, validate: [validateLocalStrategyProperty, 'Please fill in your email'], match: [/.+\@.+\..+/, 'Please fill a valid email address'], unique: 'testing error message' }, 

mean.js锅炉板代码在服务器中有一个名为errors.server.controller.js的控制器,用于处理在唯一索引validation失败(它们给出错误代码11000和11001)时出现的错误。

 exports.getErrorMessage = function(err) { var message = ''; if (err.code) { switch (err.code) { case 11000: case 11001: message = getUniqueErrorMessage(err); break; default: message = 'Something went wrong'; } } else { for (var errName in err.errors) { if (err.errors[errName].message) message = err.errors[errName].message; } } return message; }; 

当我使用唯一的索引validation,而不是在编辑configuration文件页面上有任何问题。
我以前试过这个独特的属性,它不工作,我发现这是因为如果您的数据库中已经有重复的值,你必须删除数据库中的所有信息。 我听说有解决这个问题的其他方法,但对我来说,删除数据库是最容易的。 Mongoose的创造者Aaron Heckmannbuild议采用独特的validation指数方法,以避免在使用其他方法时遇到与预期的竞争条件相关的错误。
http://nraj.tumblr.com/post/38706353543/handling-uniqueness-validation-in-mongo-mongoose