How To Use Async Parallel For Multiple Queries
Solution 1:
You are not setting up the functions properly. The expected argument are function()
wrappers with a callback
argument which gets passed to when the contained async function completes.
You also really just want async.map
instead of what you are doing, because it's output is an array of the results from the looped calls. So no need to push results into an external variable:
app.get('/api/wherecritique/reviews/search/:author', function(req,res) {
Critique.find({author: req.params.author}, function(err,cris) {
async.map(
cris.map( c => c.reviewID ),
function(id, callback) {
Review.findOne({ id: id }, callback);
},
function(err,results) {
if (err) throw err; // or something with errconsole.log(results);
res.json(results);
}
);
});
});
But in all honesty you should really be using Promises here rather than import an external library
app.get('/api/wherecritique/reviews/search/:author', function(req,res) {
Critique.find({author: req.params.author}, function(err,cris) {
Promise.all(
cris.map( c =>Review.findOne({ id: c.reviewID }) )
).then( results => {
console.log(results);
res.json(results);
}).catch( e =>console.error(e) );
});
});
Or in a more modern way with async/await
:
app.get('/api/wherecritique/reviews/search/:author', async (req,res) => {
try {
let cris = awaitCritique.find({author: req.params.author});
let results = Promise.all(
cris.map( c =>Review.findOne({ id: c.reviewID }) )
);
console.log(results);
res.json(results);
} catch(e) {
console.error(e);
}
});
But in actual reality, this has nothing to do with JavaScript at all, and you really should be using MongoDB features.
Either with $lookup
where supported:
app.get('/api/wherecritique/reviews/search/:author', async (req,res) => {
try {
let results = await Critique.aggregate([
{ $match: { author: req.params.author } },
{ $lookup: {
from: Review.collection.name,
localField: 'reviewID',
foreignField: 'id'as: 'reviews'
}},
{ $unwind: '$reviews' }
]);
results = results.map( r => r.reviews );
console.log(results);
res.json(results);
} catch(e) {
console.error(e);
}
});
Or if you don't have that, then simply passing all id
values to $in
:
app.get('/api/wherecritique/reviews/search/:author', async (req,res) => {
try {
let cris = awaitCritique.find({ author: req.params.author });
let results = awaitReview.find({ id: { $in: cris.map( c => c.reviewID ) } });
console.log(results);
res.json(results);
} catch(e) {
console.error(e);
}
});
Which means either "one" or "two" actual calls to the database depending on your MongoDB version. No need to loop async calls at all.
Finally, it's really not necessary as explained by all the above, but the correct usage of async.parallel
would be:
app.get('/api/wherecritique/reviews/search/:author', (req,res) => {
Critique.find({author: req.params.author}, (err,cris) => {
var tasks = cris.map( c =>(callback) =>Review.findOne({ id: c.reviewID }, callback);
);
async.parallel(
tasks,
(err,results) => {
if (err) throw err; // or somethingconsole.log(results);
res.json(results);
}
)
});
});
Post a Comment for "How To Use Async Parallel For Multiple Queries"