12

I have defined a Model with mongoose like this:

var mongoose = require("mongoose")
var Schema = mongoose.Schema

var userObject = Object.create({
    alias: String,
    email: String,
    password: String,
    updated: { 
        type: Date,
        default: Date.now
    }
})

var userSchema = new Schema(userObject, {strict: false})
var User = mongoose.model('User', userSchema)

module.exports = User

Then I created a user that I can perfectly find through mongo console like this:

db.users.findOne({ email: "[email protected]" });
{
    "_id" : ObjectId("55e97420d82ebdea3497afc7"),
    "password" : "caff3a46ebe640e5b4175a26f11105bf7e18be76",
    "gravatar" : "a4bfba4352aeadf620acb1468337fa49",
    "email" : "[email protected]",
    "alias" : "coco",
    "updated" : ISODate("2015-09-04T10:36:16.059Z"),
    "apps" : [ ],
    "__v" : 0
}

However, when I try to access this object through a node.js with mongoose, the object a retrieve is not such doc, but a wrapper:

This piece of code...

// Find the user for which the login queries
  var User = require('../models/User')
  User.findOne({ email: mail }, function(err, doc) {
    if (err) throw err
      if (doc) {
        console.dir(doc)
        if(doc.password == pass) // Passwords won't match

Produces this output from console.dir(doc)...

{ '$__': 
   { strictMode: false,
     selected: undefined,
     shardval: undefined,
     saveError: undefined,
     validationError: undefined,
     adhocPaths: undefined,
     removing: undefined,
     inserting: undefined,
     version: undefined,
     getters: {},
     _id: undefined,
     populate: undefined,
     populated: undefined,
     wasPopulated: false,
     scope: undefined,
     activePaths: { paths: [Object], states: [Object], stateNames: [Object] },
     ownerDocument: undefined,
     fullPath: undefined,
     emitter: { domain: null, _events: {}, _maxListeners: 0 } },
  isNew: false,
  errors: undefined,
  _doc: 
   { __v: 0,
     apps: [],
     updated: Fri Sep 04 2015 12:36:16 GMT+0200 (CEST),
     alias: 'coco',
     email: '[email protected]',
     gravatar: 'a4bfba4352aeadf620acb1468337fa49',
     password: 'caff3a46ebe640e5b4175a26f11105bf7e18be76',
     _id: { _bsontype: 'ObjectID', id: 'Uét Ø.½ê4¯Ç' } },
  '$__original_validate': { [Function] numAsyncPres: 0 },
  validate: [Function: wrappedPointCut],
  _pres: { '$__original_validate': [ [Object] ] },
  _posts: { '$__original_validate': [] } }

Therefore, passwords won't match because doc.password is undefined.

Why is this caused?

2
  • 1
    Use console.log, not console.dir to sanely log Mongoose model instances. Commented Sep 4, 2015 at 13:04
  • Yeah, as a fact console.log(doc) only printed the wrapped document, but the password validation still did not work and doc.password still returned undefined without console.dir(doc). Commented Sep 4, 2015 at 13:49

1 Answer 1

15

That's exactly the purpose of mongoose, wrapping mongo objects. It's what provides the ability to call mongoose methods on your documents. If you'd like the simple object, you can call .toObject() or use a lean query if you don't plan on using any mongoose magic on it at all. That being said, the equality check should still hold as doc.password returns doc._doc.password.

Sign up to request clarification or add additional context in comments.

5 Comments

Great. It worked! Thank you really. Do you know why in several tutorials and snippets –like this one in mongoose docs– the method .toObject() is not used?
It's not a necessity. If you're using mongoose, chances are, you want the mongoose document.
Sorry to be so insisting I want to fully understand; In the linked example mongoose object is used to access directly to document params (like person.occupation). In my case that did not work, since doc.password always returns undefined unless I apply .toObject() first.
Try this: doc.password === doc._doc.password. That should evaluate to true. In the example you linked, when you access person.occupation it returns person._doc.occupation. This is why I don't understand your error. If doc.toObject().password makes your code work, doc.password should work as well.
Thank you soo much!! This bit just helped me fix an issue that had me stuck for hours. I was trying to modify my server side rendered React app config thinking that this was a react context issue but turns out it was MongoDB.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.