Mongoose: How can I access a select:false property in a schema method?
Asked Answered
R

5

24

Quick code:

var userSchema = new mongoose.Schema({
    username: String,
    password: {type: String, select: false}
});

userSchema.methods.checkPassword = function(password, done) {
    console.log(password);      // Password to check
    console.log(this.password); // stored password
    ...
};

I don't want the password to be accessible by default, but I need a method to check against a user inputted password before authenticating the user. I know I can do a query to the DB to include these values, but I'm a bit lost on how I could access the hidden property on the schema method itself. this in the method itself is just the returned query, so it seems like it is inaccessible? Should I be doing the checkPassword() function elsewhere?

Railey answered 3/3, 2015 at 17:57 Comment(0)
C
29

You can use select to select password in query. This is an example query.

User.findOne().select('password').exec(callback);

And this must be what you want to check password.

userSchema.methods.checkPassword = function(password, done) {
    User.findOne({username: this.username}).select('password').exec(function (err, user) {
        if (user.password == password)
            return true;
        else 
            return false;
    });
}

I hope this might help you.

Campobello answered 4/3, 2015 at 4:52 Comment(5)
So it seems it's not possible to access the select:false properties from within a schema.methods itself, you have to pass it to a callback. Got it! Thank you.Railey
@Khay, I am getting an error that find().select is not a functionGotham
@PulkitAggarwal please check your schema name which you are using for find(). There may be typo error in it.Campobello
Is it possible to select multiple fields. For example const user = await User.findOne({ email }).select( 'emailVerified', 'password' );Rena
@Rena See answer below: https://mcmap.net/q/547276/-mongoose-how-can-i-access-a-select-false-property-in-a-schema-methodSlavin
A
16

You can explicitly allow the password field (with {select:"false"}) to be returned in your find call with "+" operator before field e.g.:

User.findOne({}).select("+password") // "+" = allow select hidden field
Annular answered 14/9, 2021 at 13:24 Comment(1)
"+" operator is useful if you need property in addition to the rest of the properties. otherwise, it just returns that property excluding all others.Seismoscope
S
0

A right way is writing the fields on method findOne. You can ask the fields that you want to return. In your case, it should be:

await User.findOne({ username: this.username }, 'password').exec();

Documentation: mongoose.findOne

Sherburne answered 2/6, 2021 at 0:42 Comment(0)
S
0

Above answers only show selection for a single property.

For multiple properties, syntax is this one:

await this.userModel
      .findOne({ email }, { status: 1, firstName: 1, religion: 1 })
      .exec();

This will return:

{
  _id: new ObjectId("62de5a5158b809468b812345"),
  status: 'Active',
  firstName: 'John',
  religion: 'Christian Orthodox'
}
Slavin answered 26/7, 2022 at 10:37 Comment(0)
S
0

In order to select hidden fields such as those fields which are set to

select: false

in the mongoose schema. Try this.

const data = User.find().select("+password");
Stirring answered 18/4 at 14:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.