简体   繁体   中英

Using Multiple FindOne in Mongodb

I am trying to extend the amount of fields that our API is returning. Right now the API is returning the student info by using find, as well as adding some information of the projects by getting the student info and using findOne to get the info about the project that the student is currently registered to.

I am trying to add some information about the course by using the same logic that I used to get the project information.

So I used the same findOne function that I was using for Projects and my logic is the following.

I created a variable where I can save the courseID and then I will put the contents of that variable in the temp object that sending in a json file.

If I comment out the what I added, the code works perfectly and it returns all the students that I require. However, when I make the additional findOne to get information about the course, it stops returning anything but "{}"

I am going to put a comment on the lines of code that I added, to make it easier to find.

Any sort of help will be highly appreciated!

User.find({
    isEnrolled: true,
    course: {
      $ne: null
    }
  },
  'email pantherID firstName lastName project course',
  function(err, users) {
    console.log("err, users", err, users);
    if (err) {
      return res.send(err);
    } else if (users) {
      var userPromises = [];
      users.map(function(user) {
        userPromises.push(new Promise(function(resolve, reject) {

          ///////// Added Code  START///////
          var courseID;

          Course.findOne({
              fullName: user.course
            }, function(err, course) {
              console.log("err, course", err, course);
              if (err) {
                reject('')
              }

              courseID = course ? course._id : null


              //console.log(tempObj)
              resolve(tempObj)
            }),

            ///// ADDED CODE END //////

            Project.findOne({
              title: user.project
            }, function(err, proj) {
              console.log("err, proj", err, proj);
              if (err) {
                reject('')
              }
              //Course ID, Semester, Semester ID
              //map to custom object for MJ
              var tempObj = {
                email: user.email,
                id: user.pantherID,
                firstName: user.firstName,
                lastName: user.lastName,
                middle: null,
                valid: true,
                projectTitle: user.project,
                projectId: proj ? proj._id : null,
                course: user.course,
                courseId: courseID
              }

              //console.log(tempObj)
              resolve(tempObj)
            })
        }))
      })
      //async wait and set
      Promise.all(userPromises).then(function(results) {
        res.json(results)
      }).catch(function(err) {
        res.send(err)
      })
    }
  })

using promise could be bit tedious, try using async , this is how i would have done it.

// Make sure User, Course & Project models are required. 

const async = require('async');

let getUsers = (cb) => {
    Users.find({
        isEnrolled: true,
        course: {
            $ne: null
        }
    }, 'email pantherID firstName lastName project course', (err, users) => {
        if (!err) {
            cb(null, users);
        } else {
            cb(err);    
        }
    });
};

let findCourse = (users, cb) => {
    async.each(users, (user, ecb) => {
        Project.findOne({title: user.project})
            .exec((err, project) => {
                if (!err) {
                    users[users.indexOf(user)].projectId = project._id;
                    ecb();     
                } else {
                    ecb(err);
                }
            });
    }, (err) => {
        if (!err) {
            cb(null, users);
        } else {
            cb(err);
        }
    });
};

let findProject = (users, cb) => {
    async.each(users, (user, ecb) => {
        Course.findOne({fullName: user.course})
            .exec((err, course) => {
                if (!err) {
                    users[users.indexOf(user)].courseId = course._id;
                    ecb();     
                } else {
                    ecb(err);
                }
            });
    }, (err) => {
        if (!err) {
            cb(null, users);
        } else {
            cb(err);
        }
    });
};

// This part of the code belongs at the route scope
async.waterfall([
    getUsers,
    findCourse,
    findProject
], (err, result) => {
    if (!err) {
        res.send(result);
    } else {
        return res.send(err);        
    }
});

Hope this gives better insight on how you could go about with multiple IO transactions on the same request.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM