MH. Abdi
MH. Abdi

Reputation: 308

mongoose find() inside a foreach

I want to find documents based on some conditions that are in a array for example:

subscriptions=[
{teacher: 'john', student:'david' ,course:'math'},
{teacher: 'john', student:'david' ,course:'english'},
{teacher: 'matt', student:'max' ,course:'math'}]

I want to find in Exam collection where: teacher, student, and course is based on this array:

subscriptions.forEach(sub=>{
Exam.find({teacher:sub.teacer, student:sub.student, course:sub.course},(err,res)=>{})})

whoever, I can't call find inside a for loop, should I use async library? I think there is a better way for this query and I dont need a loop

Upvotes: 0

Views: 1598

Answers (3)

Saurabh Mistry
Saurabh Mistry

Reputation: 13669

use async

app.get('/',function(req,res){ 
var examsArray= [];

async.each(subscriptions,function(sub,callback){
      Exam.find({teacher:sub.teacher,
                student:sub.student,
                course:sub.course},
             function(err,exams){
                 if(err) return callback(error);
                 if(!err && exams){ 
                     examsArray.push(exams);
                     return callback(exams);
                 }
            });
     },
     , function(err) {
         if (err) { res.json(err); }
         console.log("ALL FINISH");
         if(!err){ res.json(examsArray); }
      });
    });
 });

Upvotes: -1

Orelsanpls
Orelsanpls

Reputation: 23515

If you want to get all the documents matching one of your array entry :

const subscriptions = [{
    teacher: 'john',
    student: 'david',
    course: 'math',
  },
  {
    teacher: 'john',
    student: 'david',
    course: 'english',
  },
  {
    teacher: 'matt',
    student: 'max',
    course: 'math',
  },
];

Exam.find({
    $or: subscriptions,
  })
  .then((ret) => {
    // Deal with the data
  })
  .catch((err) => {
    // Deal with the error
  });

If you want to get the data in separated arrays :

const subscriptions = [{
    teacher: 'john',
    student: 'david',
    course: 'math',
  },
  {
    teacher: 'john',
    student: 'david',
    course: 'english',
  },
  {
    teacher: 'matt',
    student: 'max',
    course: 'math',
  },
];

Promise.all(subscriptions.map(x => Exam.find(x))
  .then(([
    find1,
    find2,
    find3,
  ]) => {
    // Deal with the data
  })
  .catch((err) => {
    // Deal with the error
  });


// Explaination of :

.then(([
  find1,
  find2,
  find3,
]) => {
  // Deal with the data
})


// This is the equivalent

.then((rets) => {
  const find1 = rets[0];
  const find2 = rets[1];
  const find3 = rets[2];

  // Deal with the data
});

Upvotes: 2

ninesalt
ninesalt

Reputation: 4354

You should select using an or operator rather than in a loop:

Exam.find().or(subscriptions).then(docs => { 
/*logic here*/ 
})
.catch(error => { 
/*error logic here*/ 
})

Upvotes: 0

Related Questions