ga-wdi-boston / team-project

Other
2 stars 39 forks source link

Testing mongoose populate #6

Closed raq929 closed 8 years ago

raq929 commented 8 years ago

We're trying to test the mongoose populate function for our schema. Currently we're getting the error Cannot read property 'populate' of undefined We are running a script in Node which creates a page (sucessfully), and then attempts to call the populate function on that page.

raq929 commented 8 years ago

Ok we tried it using Find(page we created before).populate('user_id) And we now get: Query { _mongooseOptions: { populate: { user_id: [Object] } }, mongooseCollection: NativeCollection { collection: { s: [Object] }, opts: { bufferCommands: true, capped: false }, name: 'pages', collectionName: 'pages', conn: NativeConnection { base: [Object], collections: [Object], models: [Object], config: [Object], replica: false, hosts: null, host: 'localhost', port: 27017, user: undefined, pass: undefined, name: 'mongo-crud', options: [Object], otherDbs: [], _readyState: 1, _closeCalled: false, _hasOpened: true, _listening: true, db: [Object], _events: {}, _eventsCount: 0 }, queue: [], buffer: false, emitter: EventEmitter { domain: null, _events: {}, _eventsCount: 0, _maxListeners: undefined } }, model: { [Function: model] hooks: Kareem { _pres: {}, _posts: {} }, base: Mongoose { connections: [Object], plugins: [], models: [Object], modelSchemas: [Object], options: [Object] }, modelName: 'Page', model: [Function: model], db: NativeConnection { base: [Object], collections: [Object], models: [Object], config: [Object], replica: false, hosts: null, host: 'localhost', port: 27017, user: undefined, pass: undefined, name: 'mongo-crud', options: [Object], otherDbs: [], _readyState: 1, _closeCalled: false, _hasOpened: true, _listening: true, db: [Object], _events: {}, _eventsCount: 0 }, discriminators: undefined, schema: Schema { paths: [Object], subpaths: {}, virtuals: [Object], nested: {}, inherits: {}, callQueue: [Object], _indexes: [], methods: {}, statics: {}, tree: [Object], _requiredpaths: undefined, discriminatorMapping: undefined, _indexedpaths: undefined, s: [Object], options: [Object] }, collection: NativeCollection { collection: [Object], opts: [Object], name: 'pages', collectionName: 'pages', conn: [Object], queue: [], buffer: false, emitter: [Object] } }, schema: Schema { paths: { title: [Object], content: [Object], url: [Object], user_id: [Object], _id: [Object], __v: [Object] }, subpaths: {}, virtuals: { id: [Object] }, nested: {}, inherits: {}, callQueue: [ [Object], [Object] ], _indexes: [], methods: {}, statics: {}, tree: { title: [Object], content: [Object], url: [Object], user_id: [Object], _id: [Object], id: [Object], __v: [Function: Number] }, _requiredpaths: undefined, discriminatorMapping: undefined, _indexedpaths: undefined, s: { hooks: [Object], queryHooks: [Object] }, options: { typeKey: 'type', id: true, noVirtualId: false, _id: true, noId: false, validateBeforeSave: true, read: null, shardKey: null, autoIndex: null, minimize: true, discriminatorKey: '__t', versionKey: '__v', capped: false, bufferCommands: true, strict: true, pluralization: true } }, op: 'find', options: {}, _conditions: { title: 'hello' }, _fields: undefined, _update: undefined, _path: undefined, _distinct: undefined, _collection: NodeCollection { collection: NativeCollection { collection: [Object], opts: [Object], name: 'pages', collectionName: 'pages', conn: [Object], queue: [], buffer: false, emitter: [Object] }, collectionName: 'pages' }, _traceFunction: undefined, _castError: null, _count: [Function], _execUpdate: [Function], _find: [Function], _findOne: [Function], _findOneAndRemove: [Function], _findOneAndUpdate: [Function] }

srhoulam commented 8 years ago

Looks like it's working. If you're still getting "cannot read property X of undefined", then look at where you're trying to access that property. Whatever is before the dot is undefined for some reason. A common cause is an object property that gets assigned to only conditionally, but gets accessed unconditionally.

raq929 commented 8 years ago

So... I'm confused about what populate is supposed to do, then? My understanding is that calling populate in the way we called it would give me a user object that corresponds to the id, and this seems like... not that.

srhoulam commented 8 years ago

It creates a nested document where attributes that refer to documents in other collections by their IDs instead contain the actual document from the other collection. E.g., if I have a document like so:

{
    userId: <someUserId>,
    bookId: <someBookId>,
    favFood: <someFoodId>
}

that is set up with Mongoose such that each attribute refers to documents from the User, Book, and Food collections, respectively, populating it will yield the following:

{
    userId: <someUserDocument>,
    bookId: <someBookDocument>,
    favFood: <someFoodDocument>
}

Because the attribute will later contain a document, you may prefer to call it something more descriptive like "owner" rather than "userId", or "favFood" rather than "foodId".

raq929 commented 8 years ago

Right. But what I'm getting back doesn't look like a user document, so I'm confused.

srhoulam commented 8 years ago

You don't get the user document. You get the document you populated with the attribute that contained the user id containing the user document instead.

gaand commented 8 years ago

What you pasted starts with Query so I think it's a mongoose Query object. You may need to call exec() and then handle the data in the then of the returned promise.

raq929 commented 8 years ago

Oh. Yes, that makes sense. Will try it after lunch.

raq929 commented 8 years ago

OK, so we're trying to map what the documentation does to what we're doing. And the promise stuff is working, and we're not getting an error, but we're being told that the username is undefined, instead of the username of the user we specified. And since there's no error, we don't know where to look. our code: var owner2 = Page.findOne({'title': "hello4"}).populate('owner', 'username').exec(function (err, page) { if (err) return handleError(err); console.log('The username is %s', page.owner.username);

The username is undefined

srhoulam commented 8 years ago

Attribute names are case-sensitive. Try 'userName'.

raq929 commented 8 years ago

Same problem.

srhoulam commented 8 years ago

The problem was a bit from many columns, most important of which was working in the wrong database. Also the test object was created manually in mongo shell and did not match the collection's schema in mongoose, making it anomalous. You seem to be on track now.

raq929 commented 8 years ago

We are now getting [{"_id":"565ca31be5eb510668a56153","userName":"user1","__v":0,"passwordDigest":"$2a$16$aZNqK2TBR1m4t1W7DD6xQOifR9KpR4Iu6dwjwdafAXOtPvNU8owBu","pages":[]}] The username is undefined