的NodeJS与猫鼬 - 嵌套查询异步问题

问题描述:

我不得不MongoDB的集合,像这样:的NodeJS与猫鼬 - 嵌套查询异步问题

UserGroup collection 
    fields: 
     name: String 
     group_id: Number 
User collection 
    fields: 
     user_name: String 
     group_id: Number 

我想产生这样的报告:

 
ADMINISTRATORS 
-------------------------- 
jlopez 
rdiaz 

OPERATORS 
-------------------------- 
amiralles 
dcamponits 

,但我得到了以下报告:

 
ADMINISTRATORS 
-------------------------- 
OPERATORS 
-------------------------- 
jlopez 
rdiaz 
amiralles 
dcamponits 

以下是生成报告的代码:

UserGroup.find({}, (err, groups) => { 
    for(var i in groups){ 
     console.log(groups[i].name) 
     console.log("--------------------") 
     User.find({group_id : groups[i].group_id}, (err, users) =>{ 
      for(var j in users){ 
       console.log(users[j].user_name) 
      } 
     }) 
    } 
}) 

显然,这是NodeJs/Mongoose异步性的问题。

问题:如何制作第一个For循环等待,直到每个UserGrop的内部循环结束?

在此先感谢,

David。

您可以运行使用$lookup做在同一个数据库中的“左加入”到另一个集合中从“加盟”收集处理文档过滤聚合管道。有了这个,你将不再需要任何异步库:

UserGroup.aggregate([ 
    { 
     "$lookup": { 
      "from": "users", 
      "localField": "group_id", 
      "foreignField": "group_id", 
      "as": "users" 
     } 
    }, 
    { 
     "$project": { 
      "_id": 0, 
      "name": 1, 
      "users": { 
       "$map": { 
        "input": "$users", 
        "as": "user", 
        "in": "$$user.user_name" 
       } 
      } 
     } 
    } 
], (err, groups) => { 
    if (err) throw err; 
    console.log(JSON.stringify(groups, null, 4)); 
}) 

样本输出

[ 
    { 
     "name": "ADMINISTRATORS", 
     "users": ["jlopez", "rdiaz"] 
    }, 
    { 
     "name": "OPERATORS", 
     "users": ["amiralles", "dcamponits"] 
    } 
] 
+1

这很有效,正如你提到的那样,没有必要使用另一个库。 ¡非常感谢你chridam! –

这是asyc的一个很好的用例,你可以从下面的代码中获得一个基本的想法。它基于异步每个&瀑布。 [请自行为以下代码添加适当的错误处理。]

UserGroup.find({}, (err, groups) => { 
    async.each(groups, (group, callback) =>{ 
    async.waterfall([ 
     (wCallback) => { 
     User.find({group_id : group.group_id}, wCallback) 
     }, 
     (users, wCallback) => { 
     console.log(group.name) 
     console.log("--------------------") 
     for(var j in users){ 
      console.log(users[j].user_name) 
     } 
     wCallback() 
     } 
    ], callback) 
}) 
}) 
+0

我是完美的拉坦·库马尔。非常感谢你! –

+0

你可以接受这个答案。 ;)欢迎。 –

+2

嗨拉坦。我是新来的Stackoverflow。 首先,我很惊讶人们回应的速度有多快。 虽然我说你的答案解决了这个问题,但我认为使用用户_chridam_提到的'Aggregation Pipeline'是最好的解决方案,因为它不需要使用外部库。 **无论如何非常感谢你!** –

添加对承诺的支持猫鼬。我使用q,但你也可以使用蓝鸟。

mongoose.Promise = require('q').Promise; 

然后,您可以使用q.all解决所有用户查询完成后。

var promises = []; 
var groups = []; 
UserGroup.find({}, (err, groups) => { 
    for(var i in groups){ 
     groups.push(groups[i]); 
     promises.push(User.find({group_id : groups[i].group_id})); 
    } 
}); 

q.all(promises).then(function(usersByGroup){ 
    var indx = 0; 
    usersByGroup.forEach(function(users){ 

    var grp = groups[indx]; 
    console.log(groups[i].name); 
    console.log("--------------------"); 
    for(var j in users){ 
     console.log(users[j].user_name) 
    } 
    indx++; 
    }); 
});