0

I have two schemas Teacher and Student

StudentSchema = new mongoose.Schema({
email:{type:String, index: {unique:true}}
name:{type:String},
marks:[{
subject:{type:String,
marks:{type:Number}
}]
})


TeacherSchema = new mongoose.Schema({
email:{type:String, index: {unique:true}}
name:{type:String},
students:[{
email:{type:String},
registerationDate:{type:Date}
}]
})

I have an API where I get teacher's email id and have to respond with marks and name of the students registered to that particular teacher.

For this, I'm using this code

var teacher = await Teacher.findOne({"email":req.body.email})

teacher.students.forEach(function(students){
let student = Student.findOne({"email":students.email})
console.log(student)   // to watch the result
})

I want to get the complete Student schema in my student variable so that I can use the data of the students.

But I'm not getting the desired output because I can't user await along with Student.findOne.

Like this

let student = await Student.findOne({"email":students.email})

I'm getting a Query object as a result.

Can anyone suggest any way to use await in the loop or any other way to get my desired output?

Node crashes if I use await anywhere inside my loop, so solutions answered elsewhere to use async/await in loop is not solving my problem.

harshit raghav
  • 593
  • 2
  • 9
  • 23

4 Answers4

1

Note: There is no native synchronous API for Mongoose queries but you can chain the queries.

Try this one;

Teacher.findOne({"email":req.body.email}, (err, teacher)=>{
    if( !err ) {
      let studentEmailIds = [];
      teacher.students.forEach( (students) => {
          studentEmailIds.push(students.email);
      });
      Student.find({'email': {"$in": studentEmailIds } }, (err, students)=>{     
         if(err){
          //error handle
         }else{
          console.log(students)
          //res.json(students);
         }
      });
    }
})
Vinesh Goyal
  • 607
  • 5
  • 8
0

Instead of forEach you can use find function of mongoose like below:

teacher.find({}, function (err, teachers) {
  // now you can use teachers.forEach here for getting students
  console.log(teachers.students)
});

I suppose you are trying to get all Teachers with their students.

Alexander Chef
  • 378
  • 1
  • 2
  • 13
0

Based on my understanding of your question, this should help

Teacher.find({}, (error, allTeachers) => {
  if (error) {
    // Handle Error
  } else {
    allTeachers.forEach(teacher=> {
      let student = Student.findOne({"email":teacher.email})
    });
  }
})
ibn_Abubakre
  • 112
  • 7
0

You cannot use await inside a forEach loop. You have to use a for .. of loop instead.

A forEach loop fires of multiple asynchronous requests but the function immediately returns after that. It does not wait for your promise to resolve while a for .. of loop does.

Change your code to:

for (let students of teacher.students) {
  let student = Student.findOne({"email":students.email})
  console.log(student)   // to watch the result
});
DragonBorn
  • 1,809
  • 5
  • 20
  • 44