简体   繁体   English

NodeJs Mongoose循环收集数据

[英]NodeJs Mongoose collecting data in loop

Hope for your help. 希望对您有所帮助。

I have collection tasks with document like this schema. 我有类似此架构的文档收集任务。

Task = { 
     title:'taskName', 
     performers:[ {userId:1,price:230}, {userId:2,price:260} ]
}   
Profiles = { id:1, name: 'Alex', surname: 'Robinson', etc.. }

Finally, I shoul collect all data, and in response return Array of profiles objects. 最后,我应该收集所有数据,并作为响应返回配置文件对象数组。 Problem is that for-loop end before finished all .findOne() for every elements, and it return empty Array. 问题是for循环在每个元素的所有.findOne()完成之前结束,并且返回空数组。 This is code form get. 这是代码形式的获取。

CODE HERE: 代码在这里:

apiRoutes.get('/performers/:id', function(req,res,next){

var profArr = []; 
Task.findOne({'_id':req.params.id},function(err, doc){
  for(var i = 0; i<doc.performers.length; i++){
    var profile = {
      price: 0,
      name: '',
      surname: ''         
    };
    profile.price = doc.performers[i].price;
    Profile.findOne({'_id':doc.performers[i].userId},function(err,doc){
      if (err) throw err;
      profile.name = doc.name;
      profile.surname = doc.surname;          
      profArr.push(profile);
    });
  }
  return res.json({success:true,
                   message:'Performers data collected',
                   data:profArr});
});    

A simple idea would be to introduce a countdown-counter before you start your for-loop like this: 一个简单的想法是在开始这样的for循环之前引入一个倒数计数器:

var countdown = doc.performers.length;

Decrement the countdown in the callback function of the findOne-Calls. 减少findOne-Calls的回调函数中的倒计时。 Check if you have reached 0 and call a function outside to send the result. 检查您是否已达到0并在外部调用函数以发送结果。

But still your code doesn't look very efficient. 但是您的代码仍然看起来效率不高。 There are a lot of calls to the db. 有很多对数据库的调用。 Maybe you could rethink your datamodel in order to minimize the calls to the db. 也许您可以重新考虑数据模型,以最大程度地减少对数据库的调用。

The problem is you need to return response inside mongoose query. 问题是您需要在猫鼬查询内返回响应。 You can't use any values assigned inside the query outside. 您不能使用外部查询内部分配的任何值。 For example : 例如 :

var sampleArr = [];
Users.find({}, function(err, users) {
  users.forEach(function(user) {
    Students.find({'userid' : user.id}, function(err, student) {
      sampleArr.push({
        'student' : student
      });
    })
    console.log(sampleArr);
    // It will only return empty array[];
  })
})

So, your task should be like this: 因此,您的任务应如下所示:

apiRoutes.get('/performers/:id', function(req,res,next){

var profArr = [];
// Get a task by ID
Task.findById(req.params.id, function (err, task) {
  // Get all profiles
  Profile.find({}, function (err, profiles) {
    task.performers.forEach(function(taskPerformer) {
      profiles.forEach(function(profile) {
        // Check the performer ID is the same with userID or not
        if (profile._id == taskPerformer.userId) {
          profArr.push({
            price: taskPerformer.price,
            name: profile.name,
            surname: profile.surname
          });
        }
      })
    });
    return res.json({
      success:true,
      message:'Performers data collected',
      data:profArr
    });
  });
})

您的“ for”循环将在findOne完成之前完成。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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