如何在mongoose + express中使用模式方法

当我尝试从exports.index.post运行user.comparePassword(见下面)时,出现以下错误 – 我粘贴了所有代码以帮助缩小问题的范围。 UserSchema.pre('save')方法工作正常,但不是在./routes/account.js(我使用mongoose3)

这是我得到的错误。

Caught exception: [TypeError: Object { username: 'test4', email: 'test4@test.com', password: '$2a$10$Ix5vCuVYGIU7AmXglmfIxOyYnF6CiPJfw9HLSAGcRDxMJEttud/F6', _id: 505fee7ce28f10711e000002, __v: 0 } has no method 'comparePassword'] ## ./app.js app.post('/account', routes.account.index.post); ## ./models/user.js var mongoose = require('mongoose') , bcrypt = require('bcrypt') , Schema = mongoose.Schema , db = mongoose.createConnection('localhost', 'mydb'); var UserSchema = new Schema({ username : { type: String, required: true, index: { unique: true }, trim: true } , email : { type: String, required: true, index: { unique: true }, trim: true, lowercase: true } , password : { type: String, required: true, trim: true } }); UserSchema.pre('save', function(next) { var user = this; // only hash the password if it has been modified (or is new) if (!user.isModified('password')) return next(); // generate a salt bcrypt.genSalt(function(err, salt) { if (err) return next(err); // hash the password along with our new salt bcrypt.hash(user.password, salt, function(err, hash) { if (err) return next(err); // override the cleartext password with the hashed one user.password = hash; next(); }); }); }); //compare supplied password UserSchema.methods.comparePassword = function(candidatePassword, cb) { bcrypt.compare(candidatePassword, this.password, function(err, isMatch) { if (err) return cb(err); cb(null, isMatch); }); }; module.exports = db.model('User', UserSchema); ##./routes/account.js /* * GET account home page. */ exports.index = {}; exports.index.get = function(req, res){ var d = { title: 'Edit account' }; res.render('account', { d: d } ); }; exports.index.post = function(req, res){ req.assert('email', 'Enter email').notEmpty().isEmail(); req.assert('password', 'Enter password').notEmpty().isAlphanumeric().len(5,20); //user must confirm password if ( req.body.password_new ) { req.assert('password_new', 'Enter password').notEmpty().isAlphanumeric().len(5,20); req.assert('password_new_confirm', 'Passwords must match').equals(req.body.password); } res.locals.err = req.validationErrors(true); if ( res.locals.err ) { var d = { title: 'Edit account' }; res.render('account', { d: d } ); return; } var User = require('../models/user') , mongoose = require('mongoose') , db = mongoose.createConnection('localhost', 'mydb'); var user = db.model('User', User.UserSchema); user.find({username: req.session.user.username }, function(err, user){ if ( err ) return next(err); /*********** THIS IS WHERE THE ERROR OCCURS **************/ user.comparePassword(req.body.password, function(err, isMatch) { console.log("isMatch", isMatch); if (err) next(err); if (!isMatch) { req.flash('error', 'Woops, looks like you mistyped your password.'); req.session.user = user; res.locals.user = user; res.redirect('/account'); return; } //user is authenticated //session length console.log(req.body); }); }); }; 

user.find查询0个或多个文档,所以其callback的第二个参数是一个文档数组,而不是一个文档。 user.findOne查询0或1个文档,所以其callback的第二个参数是null或单个文档。 所以你试图在一个JavaScript Array上调用你的模式的方法,这当然是行不通的。 改变find调用findOne它应该工作。