Mongoose: Method is not a function

Created on 16 May 2017  路  15Comments  路  Source: Automattic/mongoose

Hi,

I have this method in my model:

// Compare password
UserSchema.methods.comparePassword = function(candidatePassword){
    return bcrypt.compareSync(candidatePassword, this.password);
};

let User = mongoose.model('User', UserSchema);
export default User;

When i try call this method, i receive this error:

events.js:160
      throw er; // Unhandled 'error' event
      ^

TypeError: users_1.default.comparePassword is not a function

Where is the error here ?

Please mention your node.js, mongoose and MongoDB version.
Node: v6.3.10
MongoDB: v3.2.13
Mongoose: v4.9.9

Thanks,

help

Most helpful comment

solved it using await on fetching user. let user = await UserModel.findOne({ email });
Its design flaw on my part

All 15 comments

how are you calling comparePassword()

@varunjayaraman ,

Thanks for quickly response;

        User.findOne(query, function(err, user) {
            if(err || !user) return done(null, err);
            if(!User.comparePassword(password)) return done(null, err);

            return done(null, user);

        });

comparePassword is a method, not a static. You're calling it off the User model but you need to call it off the user instance:

if (!user.comparePassword(password)) return done(null, err);

My bad...
It's working now!
Thanks.

Also, just a word of caution: bcrypt.compareSync is a bad idea. compareSync is a CPU intensive op and youre gonna block the event loop.

What you suggest ?

you should use the asynchronous option with promises or callbacks:

With promises:

// Load hash from your password DB. 
bcrypt.compare(myPlaintextPassword, hash).then(function(res) {
    // res == true 
});

with callbacks:

// Load hash from your password DB. 
bcrypt.compare(myPlaintextPassword, hash, function(err, res) {
    // res == true 
});

Thanks

Hi guys I get the same issue despite following directions correctly
mongoose v4.13.6

let UserSchema = new Schema({ ... });
UserSchema.methods.checkPassword = function () {...}
const UserModel = mongoose.model(
  'user',
  UserSchema
);
let user = UserModel.findOne({ email });
user.checkPassword(password);

But i get the below error

TypeError: user.checkPassword is not a function

I have confirmed user object as well

user.exec(
  function(err, user) {
    console.log(user);
  }
);

gets my user object

{ _id: 5a3011ca4f353941bbb0cbed,
  email: '[email protected]',
  password: '$2a$10$jGpddddddfiSyAql9uFjBEsJTnjdcpau9D0v32PoBDs6N8P9m',
  createdAt: 2017-12-12T10:28:42.895Z,
  __v: 0 }

*More info. If i Log the user object. user = UserModel.findOne({ email }); console.log(user)

{
schema: 
   Schema {
     ...
     methods: { checkPassword: [Function] },
}

solved it using await on fetching user. let user = await UserModel.findOne({ email });
Its design flaw on my part

Hi Guys Could you please help me?
I think i have the same problem. I get an Error saying "getOrders" is not a Function.
I'm using by the way "Mongoose 5.2.15"

customerSchema.methods.getOrders = function(){
return Orders.find({customerId: this._id});
};

@stephanekechi can you please provide a more complete code sample?

@vkarpov15 thank you for your Reply.
Of course I can.
==> That's the Code for the model:

var mongoose = require('mongoose');
var Orders = require('../models/order.js');

var customerSchema = mongoose.Schema({
    firstName: String,
    lastName: String,
    email: String,
    address1: String,
    address2: String,
    city: String,
    state: String,
    zip: String,
    phone: String,
    salesNotes: [{
        date: Date,
        salespersonId: Number,
        notes: String,
    }],
});

customerSchema.methods.getOrders= function(){
    return Orders.find({customerId: this._id});
};


var Customer = mongoose.model('Customer', customerSchema);
module.exports = Customer;

==> That's where I call the function getOrders()

exports.getCustomerViewModel = (customerId)=>{

    var customer = Customer.findById(customerId, (err,cust)=>{
        if(err) return null;
        return cust;
    });
    if(!customer) return {error: 'Unknown customer ID: ' + req.params.customerId};

    **var orders = customer.getOrders().map(function(order)**{
        return {
            orderNumber: order.orderNumber,
            date: order.date,
            status: order.status,
            url: '/orders/' + order.orderNumber,
            customerId: order.customerId,
        }
    });

@stephanekechi this is an issue with your code, customer.findById() returns a thenable, not a doc. You should use async/await to get an actual doc:

exports.getCustomerViewModel = async (customerId)=>{

    const customer = await Customer.findById(customerId);
    if(!customer) return {error: 'Unknown customer ID: ' + req.params.customerId};

        const orders = await customer.getOrders();
        for (const order of orders) { /* transform orders here */ }
}

thank a lot for your help @vkarpov15 . It's working now.

Was this page helpful?
0 / 5 - 0 ratings