tipiwiny tipiwiny - 3 months ago 10
Node.js Question

Mongoose - How to handle the result after using the populate method?

I´m starting a work with mongoose. I have created 2 schemas . The second schema with reference to the first. The schemas are :

User.js

const Schema = mongoose.Schema;
const userSchema = new Schema({
username: {type: String, unique: true},
first_name: String,
middle_name: String,
first_surname: String,
second_surname: String,
email: String,
password: String
});
const UserModel = mongoose.model('user', userSchema);


Resource.js

const Schema = mongoose.Schema;
const User = require('models/user');
const resourceSchema = new Schema({
resourceType: String,
creator: {type: Schema.Types.ObjectId, ref: 'user'},
creationTime: String
});

const ResourceModel = mongoose.model('resource', resourceSchema);


Now I want to make a query to know the user who has created a resource. Here , I use the Populate Method,according to the documentation of mongoose Documentacion about Populate. I have tried several options:

Resources.js

ResourceModel.findOne({'_id': options.resourceId}).populate('creator').exec().then(resource => {
log.info(resource.creator.username);
});


The log.info return a undefined. If I change the code :

ResourceModel.findOne({'_id': options.resourceId}).populate('creator').exec().then(resource => {
log.info(resource.creator);
});


The log.info return this:

$__: {
"strictMode": true,
"getters": {},
"wasPopulated": true,
"activePaths": {
"paths": {
"username": "init",
"second_surname": "init",
"password": "init",
"middle_name": "init",
"first_surname": "init",
"first_name": "init",
"email": "init",
"_id": "init"
},
"states": {
"ignore": {},
"default": {},
"init": {
"username": true,
"second_surname": true,
"password": true,
"middle_name": true,
"first_surname": true,
"first_name": true,
"email": true,
"_id": true
},
"modify": {},
"require": {}
},
"stateNames": [
"require",
"modify",
"init",
"default",
"ignore"
]
},
"emitter": {
"domain": {
"domain": null,
"_events": {},
"_eventsCount": 1,
"members": [
{
"_readableState": {
"objectMode": false,
"highWaterMark": 16384,
"buffer": [],
"length": 0,
"pipes": null,
"pipesCount": 0,
"flowing": true,
"ended": true,
"endEmitted": true,
"reading": false,
"sync": true,
"needReadable": false,
"emittedReadable": false,
"readableListening": false,
"resumeScheduled": false,
"defaultEncoding": "utf8",
"ranOut": false,
"awaitDrain": 0,
"readingMore": false,
"decoder": null,
"encoding": null
},
"readable": false,
"domain": "[Circular]",
"_events": {},
"_eventsCount": 2,
"socket": {
"_connecting": false,
"_hadError": false,
"_handle": {
"bytesRead": 746,
"_externalStream": {},
"fd": 16,
"reading": true,
"owner": "[Circular]",
"onconnection": null,
"writeQueueSize": 0
},
"_parent": null,
"_host": null,
"_readableState": {
"objectMode": false,
"highWaterMark": 16384,
"buffer": [],
"length": 0,
"pipes": null,
"pipesCount": 0,
"flowing": true,
"ended": false,
"endEmitted": false,
"reading": true,
"sync": false,
"needReadable": true,
"emittedReadable": false,
"readableListening": false,
"resumeScheduled": false,
"defaultEncoding": "utf8",
"ranOut": false,
"awaitDrain": 0,
"readingMore": false,
"decoder": null,
"encoding": null
},
"readable": true,
"domain": null,
"_events": {
"end": [
null,
null
],
"drain": [
null,
null
],
"close": [
null,
null
]
},
"_eventsCount": 10,
"_writableState": {
"objectMode": false,
"highWaterMark": 16384,
"needDrain": false,
"ending": false,
"ended": false,
"finished": false,
"decodeStrings": false,
"defaultEncoding": "utf8",
"length": 0,
"writing": false,
"corked": 0,
"sync": true,
"bufferProcessing": false,
"writecb": null,
"writelen": 0,
"bufferedRequest": null,
"lastBufferedRequest": null,
"pendingcb": 0,
"prefinished": false,
"errorEmitted": false,
"bufferedRequestCount": 0,
"corkedRequestsFree": {
"next": null,
"entry": null
}
},
"writable": true,
"allowHalfOpen": true,
"destroyed": false,
"_bytesDispatched": 0,
"_sockname": null,
"_pendingData": null,
"_pendingEncoding": "",
"server": {
"domain": null,
"_events": {
"connection": [
null,
null
],
"clientError": [
null,
null
]
},
"_eventsCount": 9,
"_connections": 1,
"_handle": {
"bytesRead": 0,
"_externalStream": {},
"fd": 15,
"reading": false,
"owner": "[Circular]",
"onread": null,
"writeQueueSize": 0
},
"_usingSlaves": false,
"_slaves": [],
"_unref": false,
"allowHalfOpen": true,
"pauseOnConnect": false,
"httpAllowHalfOpen": false,
"timeout": 120000,
"_pendingResponseData": 0,
"_connectionKey": "6::::3000"
},
"_server": "[Circular]",
"_idleTimeout": 120000,
"_idleNext": {
"_idleNext": "[Circular]",
"_idlePrev": "[Circular]"
},
"_idlePrev": "[Circular]",
"_idleStart": 21855,
"parser": {
"_headers": [],
"_url": "",
"_consumed": true,
"socket": "[Circular]",
"incoming": "[Circular]",
"outgoing": null,
"maxHeaderPairs": 2000
},
"_paused": false,
"_consuming": true,
"_httpMessage": {
"domain": "[Circular]",
"_events": {},
"_eventsCount": 1,
"output": [],
"outputEncodings": [],
"outputCallbacks": [],
"outputSize": 0,
"writable": true,
"_last": false,
"chunkedEncoding": false,
"shouldKeepAlive": true,
"useChunkedEncodingByDefault": true,
"sendDate": true,
"_removedHeader": {},
"_contentLength": null,
"_hasBody": true,
"_trailer": "",
"finished": false,
"_headerSent": false,
"socket": "[Circular]",
"connection": "[Circular]",
"_header": null,
"_headers": null,
"_headerNames": {},
"log": {
"domain": null,
"_events": {},
"_eventsCount": 0,
"_level": 30,
"streams": [
{
"type": "stream",
"stream": {
"_connecting": false,
"_hadError": false,
"_handle": {
"bytesRead": 0,
"_externalStream": {},
"fd": 1,
"writeQueueSize": 0,
"owner": "[Circular]"
},
"_parent": null,
"_host": null,
"_readableState": {
"objectMode": false,
"highWaterMark": 16384,
"buffer": [],
"length": 0,
"pipes": null,
"pipesCount": 0,
"flowing": null,
"ended": false,
"endEmitted": false,
"reading": false,
"sync": true,
"needReadable": false,
"emittedReadable": false,
"readableListening": false,
"resumeScheduled": false,
"defaultEncoding": "utf8",
"ranOut": false,
"awaitDrain": 0,
"readingMore": false,
"decoder": null,
"encoding": null
},
"readable": false,
"domain": null,
"_events": {},
"_eventsCount": 3,
"_writableState": {
"objectMode": false,
"highWaterMark": 16384,
"needDrain": false,
"ending": false,
"ended": false,
"finished": false,
"decodeStrings": false,
"defaultEncoding": "utf8",
"length": 0,
"writing": false,
"corked": 0,
"sync": false,
"bufferProcessing": false,
"writecb": null,
"writelen": 0,
"bufferedRequest": null,
"lastBufferedRequest": null,
"pendingcb": 0,
"prefinished": false,
"errorEmitted": false,
"bufferedRequestCount": 0,
"corkedRequestsFree": {
"next": null,
"entry": null
}
},
"writable": true,
"allowHalfOpen": false,
"destroyed": false,
"_bytesDispatched": 766,
"_sockname": null,
"_writev": null,
"_pendingData": null,
"_pendingEncoding": "",
"server": null,
"_server": null,
"_type": "pipe",
"fd": 1,
"_isStdio": true
},
"raw": false,
"level": 30,
"closeOnExit": false
}
],
"serializers": null,
"src": false,
"fields": {
"name": "hommer-ml",
"module": "log",
"hostname": "sd-dev",
"pid": 14028
}
},
"_time": 1471589378213,
"acceptable": [
"application/json",
"text/plain",
"application/octet-stream",
"application/javascript"
],
"formatters": {},
"req": "[Circular]",
"serverName": "hommer-ml",
"methods": [
"GET"
]
}
},
"connection": "[Circular]",
"httpVersionMajor": 1,
"httpVersionMinor": 1,
"httpVersion": "1.1",
"complete": true,
"headers": {
"host": "localhost:3000",
"authorization": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmaXJzdF9uYW1lIjoiamVzdXMiLCJtaWRkbGVfbmFtZSI6Implc3VzIiwiZmlyc3Rfc3VybmFtZSI6ImNhcm1vbmEiLCJpZCI6IjU3OTcyNzQ4NjkxZmZhNmY0MWFlYWQ4YyIsImhvc3QiOiIxMC4wLjIuMiIsImlhdCI6MTQ3MDEyNjIyMH0._qU7nBVrWb0m5Q__dA8FCgjaKp47Nnv1zB9rzjn4CNY",
"user-agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36",
"content-type": "application/json",
"accept": "*/*",
"accept-encoding": "gzip, deflate, sdch",
"accept-language": "en-US,en;q=0.8,es;q=0.6",
"x-forwarded-for": "10.0.2.2",
"x-forwarded-host": "localhost:8080",
"x-forwarded-server": "127.0.1.1",
"connection": "Keep-Alive"
},
"rawHeaders": [
"Host",
"localhost:3000",
"Authorization",
"Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmaXJzdF9uYW1lIjoiamVzdXMiLCJtaWRkbGVfbmFtZSI6Implc3VzIiwiZmlyc3Rfc3VybmFtZSI6ImNhcm1vbmEiLCJpZCI6IjU3OTcyNzQ4NjkxZmZhNmY0MWFlYWQ4YyIsImhvc3QiOiIxMC4wLjIuMiIsImlhdCI6MTQ3MDEyNjIyMH0._qU7nBVrWb0m5Q__dA8FCgjaKp47Nnv1zB9rzjn4CNY",
"User-Agent",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36",
"Content-Type",
"application/json",
"Accept",
"*/*",
"Accept-Encoding",
"gzip, deflate, sdch",
"Accept-Language",
"en-US,en;q=0.8,es;q=0.6",
"X-Forwarded-For",
"10.0.2.2",
"X-Forwarded-Host",
"localhost:8080",
"X-Forwarded-Server",
"127.0.1.1",
"Connection",
"Keep-Alive"
],
"trailers": {},
"rawTrailers": [],
"upgrade": false,
"url": "/api/authorizations/57b566ee593e745b25008983/permission",
"method": "GET",
"statusCode": null,
"statusMessage": null,
"client": "[Circular]",
"_consuming": true,
"_dumped": false,
"log": {
"domain": "[Circular]",
"_events": {},
"_eventsCount": 0,
"_level": 30,
"streams": [
{
"type": "stream",
"stream": "[Circular]",
"raw": false,
"level": 30,
"closeOnExit": false
}
],
"serializers": null,
"src": false,
"fields": {
"name": "hommer-ml",
"module": "log",
"hostname": "sd-dev",
"pid": 14028,
"req_id": "cb1702ef-2c55-49bb-9cbd-ad5e65eee8f8",
"action": "GET",
"ip": "10.0.2.2"
}
},
"_time": 1471589378213,
"serverName": "hommer-ml",
"_version": "*",
"_url": {
"protocol": null,
"slashes": null,
"auth": null,
"host": null,
"port": null,
"hostname": null,
"hash": null,
"search": null,
"query": null,
"pathname": "/api/authorizations/57b566ee593e745b25008983/permission",
"path": "/api/authorizations/57b566ee593e745b25008983/permission",
"href": "/api/authorizations/57b566ee593e745b25008983/permission"
},
"_cacheURL": "/api/authorizations/57b566ee593e745b25008983/permission",
"params": {
"resource_id": "57b566ee593e745b25008983"
},
"context": "[Circular]",
"route": {
"path": "api/authorizations/:resource_id/permission",
"method": "GET",
"versions": [],
"name": "getapiauthorizationsresource_idpermission"
},
"_dtraceId": 1,
"_anonFuncCount": 2,
"_currentRoute": "getapiauthorizationsresource_idpermission",
"_currentHandler": "handler-1",
"_timerMap": {
"bunyan": [
0,
297414
],
"parseQueryString": [
0,
115094
],
"readBody": [
0,
1285054
],
"parseBody": [
0,
684934
],
"logContext": [
0,
1316491
],
"handler-0": [
0,
2723801
],
"handler-1": [
970057,
332862660
]
},
"_id": "cb1702ef-2c55-49bb-9cbd-ad5e65eee8f8",
"timers": [
{
"name": "bunyan",
"time": "[Circular]"
},
{
"name": "parseQueryString",
"time": "[Circular]"
},
{
"name": "readBody",
"time": "[Circular]"
},
{
"name": "parseBody",
"time": "[Circular]"
},
{
"name": "logContext",
"time": "[Circular]"
},
{
"name": "handler-0",
"time": "[Circular]"
}
],
"query": {},
"_clen": false,
"_contentType": "application/json",
"body": "",
"user": {
"first_name": "jesus",
"middle_name": "jesus",
"first_surname": "carmona",
"id": "57972748691ffa6f41aead8c",
"host": "10.0.2.2",
"iat": 1470126220
}
},
"[Circular]"
]
},
"_events": {},
"_eventsCount": 0,
"_maxListeners": 0
}
}
--
_doc: {
"username": "jecargar",
"second_surname": "garcia",
"password": "test",
"middle_name": "jesus",
"first_surname": "gonzalez",
"first_name": "juan",
"email": "email@email.com",
"_id": "57972748691ffa6f41aead8c"
}
--
_pres: {
"$__original_save": [
null,
null
]
}
--
_posts: {
"$__original_save": []
}


According to the above result, acceding to ._doc.creator, we can find the attributes of the creator of the resource. Finally, I use this:

ResourceModel.findOne({'_id': options.resourceId}).populate('creator').exec().then(resource => {
log.info(resource.creator._doc.username);
});


The log.info show the creator´s username but I do not know if it's the right way to use Populate method.

Thanks for your help.

Answer

Is there an error thrown if you use:

ResourceModel.findOne({_id : options.resourceId})
             .populate('creator')
             .exec((error, resource) => {
                   if (error) throw error;
                   console.log(resource._id);
                   console.log(resource.creator._id);
                   console.log(resource.creator.username);
              });

Is there an export in your models? I'm not sure if you need it, but I use something like:

var mongoose = require('mongoose');
var OtherModel = require('./OtherModel.js');
var Schema = mongoose.Schema;

module.exports = mongoose.model('User', new Schema({
    linkedField: {type: Schema.Types.ObjectId, ref: 'other'}
});

and then I use User.findOne({_id : ... in my routes