Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to return Mongoose results from the find method?

Everything I can find for rending a page with mongoose results says to do it like this:

users.find({}, function(err, docs){     res.render('profile/profile', {         users:     docs     }); }); 

How could I return the results from the query, more like this?

var a_users = users.find({}); //non-working example 

So that I could get multiple results to publish on the page?

like:

/* non working example */ var a_users    = users.find({}); var a_articles = articles.find({});  res.render('profile/profile', {       users:    a_users     , articles: a_articles }); 

Can this be done?

like image 595
MrBojangles Avatar asked May 30 '11 21:05

MrBojangles


People also ask

What does find () return in Mongoose?

The find() function is used to find particular data from the MongoDB database.

Does find return an array Mongoose?

Return valueThe returned value could be an array of documents, a single document if it matches only one, or an empty array if no document is matched.

What is findOne in Mongoose?

Mongoose | findOne() Function The findOne() function is used to find one document according to the condition. If multiple documents match the condition, then it returns the first document satisfying the condition.

Is Mongoose back end?

Mongoose acts as a front end to MongoDB, an open source NoSQL database that uses a document-oriented data model.


2 Answers

You're trying to force a synchronous paradigm. Just does't work. node.js is single threaded, for the most part -- when io is done, the execution context is yielded. Signaling is managed with a callback. What this means is that you either have nested callbacks, named functions, or a flow control library to make things nicer looking.

https://github.com/caolan/async#parallel

async.parallel([    function(cb){       users.find({}, cb);    },    function(cb){       articles.find({}, cb);    } ], function(results){    // results contains both users and articles }); 
like image 141
Josh Avatar answered Sep 21 '22 01:09

Josh


I'll play the necromancer here, as I still see another, better way to do it.

Using wonderful promise library Bluebird and its promisifyAll() method:

var Promise = require('bluebird'); var mongoose = require('mongoose');  Promise.promisifyAll(mongoose); // key part - promisification  var users, articles; // load mongoose models "users" and "articles" here  Promise.props({     users: users.find().execAsync(),     articles: articles.find().execAsync()   })   .then(function(results) {     res.render('profile/profile', results);   })   .catch(function(err) {     res.send(500); // oops - we're even handling errors!   }); 

Key parts are as follows:

Promise.promisifyAll(mongoose); 

Makes all mongoose (and its models) methods available as functions returning promises, with Async suffix (.exec() becomes .execAsync(), and so on). .promisifyAll() method is nearly-universal in Node.JS world - you can use it on anything providing asynchronous functions taking in callback as their last argument.

Promise.props({     users: users.find().execAsync(),     articles: articles.find().execAsync()   }) 

.props() bluebird method takes in object with promises as its properties, and returns collective promise that gets resolved when both database queries (here - promises) return their results. Resolved value is our results object in the final function:

  • results.users - users found in the database by mongoose
  • results.articles - articles found in the database by mongoose (d'uh)

As you can see, we are not even getting near to the indentation callback hell. Both database queries are executed in parallel - no need for one of them to wait for the other. Code is short and readable - practically corresponding in length and complexity (or rather lack of it) to wishful "non-working example" posted in the question itself.

Promises are cool. Use them.

like image 26
bardzusny Avatar answered Sep 23 '22 01:09

bardzusny