I'm bulding online shop (node.js [Express] & mongoDB [mongoose]). I want to create in a side panel 2 extra divs: one with recent added stuff and one with marked as bestseller.
in app.js I know how to render view only with a single .find() >>
Product.find({}).sort({'createdAt': -1}).limit(20).exec(function(err,products) {
res.render('/route', {
title: 'custom title',
products: products
});
});
..will display 20 last added products from my collection.
and then I can easily add it in a view (in jade) with sth like this:
ul
each product in products
li= product.name
but what if I want to make more than a single .find() ? lets say one will results in displaying last 20 products and another will display all those products that have field bestseller equals true..
query is easy:
Product.find({'isBestseller': true}).limit(20).exec(function(err,products) {
res.render('/route', {
title: 'custom title',
products: products
});
});
Or how to do it, when I want to have even more .find()s on a single res.render ?
All I need, is to assign .find() results to some variable and then call it after the 'title' comes:
sth like...
Product.find({'isBestseller': true}).limit(20).exec(function(err,products) {
bestsellerProducts: req.bestsellerProducts
});
and then
res.render('/route', {
title: 'custom title',
products: products, // 20 latest added
bestsellerProducts: bestsellerProducts // 20 bestsellers
});
Or there is any other method?
Thanks for looking at it! Regards, Mike
If you're trying to send back multiple query results in the same request, it's just a matter of making the multiple calls and coordinating that multiple async returns. There are a number of ways to do this depending on what you want to accomplish and the complexity of each one.
The straight-forward way
If you've only got a two or three calls you can just nest the callbacks and return the response from the inner-most callback. This can get unwieldy reall fast and creates the callback hell scenario. It would look something like this:
Product.find({}).sort({'createdAt': -1}).limit(20).exec(function(err,products) {
//handle error
var response = {};
response.title = 'custom title'
response.products = products;
Product.find({'isBestseller': true}).limit(20).exec(function(err,products) {
//handle error
response.bestSellers = req.bestsellerProducts
//now you can send your response
res.render('/route',response);
});
As you can see, if there more calls to make or there is more logic involved, it can get difficult to follow. That can be alleviated by using named callbacks instead of anonymous functions.
Using a control flow library
For more complicated scenarios, you can use a control flow library, like async. These really help especially when you've got multiple control flows you need to apply in your app. With async it would look something like this:
async.series([
function(callback){
Product.find({}).sort({'createdAt': -1}).limit(20).exec(callback);
},
function(callback){
Product.find({'isBestseller': true}).limit(20).exec(callback);
},
],function(err, results){
res.render('/route',{
title:'custom',
products: results[0],
bestSellers: results[1]
});
}
If you're learning node, it's worthwhile to learn how to manage the async control yourself to familiarize you with the patterns you're going to be using over and over.