【问题标题】:How to use methods on schema in mongoose + express如何在 mongoose + express 中使用模式上的方法
【发布时间】:2016-02-23 21:00:07
【问题描述】:

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

这是我得到的错误。

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

    });


};

【问题讨论】:

  • 看起来方法不能从 .find() 获得,只能从 .findOne() 获得。

标签: node.js mongodb express mongoose


【解决方案1】:

user.find 查询 0 个或多个文档,因此其回调的第二个参数是文档数组,而不是单个文档。 user.findOne 查询 0 或 1 个文档,因此其回调的第二个参数为 null 或该单个文档。因此,您尝试在 JavaScript Array 上调用架构的方法,这当然是行不通的。将 find 调用更改为 findOne,它应该可以工作。

【讨论】:

  • 你知道是否可以从 user.comparePassword() 调用中获取用户对象吗?
  • @chovy 在像comparePassword 这样的实例方法中,this 是调用它的用户文档。
  • 在定义中,this 是一个用户对象,但是当我以异步行为调用它时,this 给了我架构,而不是回调中的用户对象。 user.comparePassword(req.body.password, function(err, isMatch) { //can't get user here });
  • @chovy 你已经有了user,因为你刚刚用它来调用comparePassword。回调可以直接访问。
  • 好的,我不知道为什么之前我失败了,它就像你说的那样工作。
猜你喜欢
  • 2020-09-29
  • 1970-01-01
  • 2016-01-02
  • 2018-10-22
  • 1970-01-01
  • 2018-09-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多