Reputation: 27
I have a MongoDB database called Critterpedia that contains 3 collections: fish, bugs, sea creatures. I am trying to query those collections to render the critters that will be leaving this month. Below is my fish collection query that works and renders. How do I conduct the same query for the other two collections but send all the data at once with a single res.render() call?
app.get('/critters', (req, res) => {
let query = {$and: [{fishMonthsNorth: thisMonth}, {fishMonthsNorth: {$ne: nextMonth}}]}
//Find all fish that leave this month
Fish.find(query, (err, thisMonthFish) => {
if (err) {
console.log(err);
} else {
res.render('index', {thisMonthFish : thisMonthFish});
}
});
});
Ideally I would like to:
//Query fish collection
//Query Bugs collection
//Query Sea collection
//res.render('index', {fish : fish, bugs : bugs, sea : sea});
Thank you in advance!
Upvotes: 1
Views: 154
Reputation: 4352
Well, pretty easy, you wouldn't even believe.
Instead of writing a huge Model.aggregation
query with $merge
and $lookups
, you could make 3 .find
at once (in parallel), via Promise.all
, Promise.allSettled
or for await of
const express = require('express');
const router = express.Router();
/**
* Model importing / Collections
*/
const fish_db = require("../../db/fish_db");
const bug_db = require("../../db/bug_db");
const sea_db = require("../../db/sea_db");
router.get('/critters', async function(req, res) {
try {
let response = {};
/**
* You could form / pre-determine more queries, for each of your collection
*/
let query = {$and: [{fishMonthsNorth: thisMonth}, {fishMonthsNorth: {$ne: nextMonth}}]};
/**
* Promise.allSettled is ES2020 feature, you could use Promise.all instead
* or for await of arrayOfPromises
*/
await Promise.allSettled([
fish_db.find(query).then(docs => { Object.assign(response, {fish: docs}) } )
bug_db.find(query).then(docs => { Object.assign(response, {bug: docs}) } )
sea_db.find(query).then(docs => { Object.assign(response, {sea: docs}) } )
])
/** You could add almost anything to response if you want it to */
await res.status(200).json(response);
} catch (e) {
await res.status(404).json(e);
}
});
module.exports = router;
You could also form your array of promises before, like:
let futureFinds = [];
if (need to search for fish) {
futureFinds.push(await fish_db.find(query))
}
if (need to search for bugs) {
futureFinds.push(await bugs_db.find(query))
}
const [result_one, result_two] = await Promise.all(futureFinds)
and then handle them at-once as you see in code above.
Upvotes: 1