Node JS / MongoDB中的嵌套查询

我在mongo中的用户列表是这样设置的:

email: email@email.com, uniqueUrl:ABC, referredUrl: ... 

我有下面的代码,我查询我的数据库中的所有用户,并为每个用户,找出有多less其他用户的被引用的URI等于当前用户的唯一url:

 exports.users = function(db) { return function(req, res) { db.collection('userlist').find().toArray(function (err, items) { for(var i = 0; i<= items.length; i++) { var user = items[i]; console.log(user.email); db.collection('userlist').find({referredUrl:user.uniqueUrl}).count(function(err,count) { console.log(count); }); } }); }; }; 

现在我第一次logging用户的电子邮件,然后是与用户相关的计数。 所以控制台应该是这样的:

 bob@bob.com 1 chris@chris.com 3 grant@grant.com 2 

相反,它看起来像这样:

 bob@bob.com chris@chris.com grant@grant.com 1 3 2 

这是怎么回事? 为什么嵌套查询只在第一个查询完成后才返回?

欢迎使用asynchronous编程和callback。

你期待的事情就是一切都按照线性顺序进行,但是这不是节点的工作方式。 整个学科在这里有点过于宽泛,但可以做一些阅读。

幸运的是驱动程序调用process.nextTick所有关键字,这会给你一些东西来查找和search。 但是由于事情排队的自然方式,有一种简单的方法可以补救代码。

 db.collection('userlist').find().toArray(function(err,items) { var processing = function(user) { db.collection('userlist').find({ referredUrl: user.uniqueUrl }) .count(function(err,count) { console.log( user.email ); console.log( count ); }); }; for( var i = 0; i < items.length; i++) { var user = items[i]; processing(user); } }); 

当然,这当然是一种简单的解释方式,但是在这里要理解的是,你将parameter passing给重复的.find() ,然后在那里做所有的输出。

正如所说的,幸运的是,在API函数中完成了一些工作,并且在添加调用时保持事件堆栈。 但大多数情况下,现在输出调用是在一起进行的 ,而不是在不同的事件集合中发生。

关于事件循环和callback的详细解释,我肯定有一个比我能写在这里更好的东西。

callback在node.js中是asynchronous的。 所以,你的计数函数( function(err,count) { console.log(count); } )不会在console.log(user.email);之后立即执行console.log(user.email); 。 所以输出是正常的,没有错。 编码风格是什么错。 当你用python(单线程)以相同的方式调用函数时,你不应该连续调用callback来得到相同的结果。 为了得到所需的结果,你应该做一切callback的工作。 但在这之前,我build议您了解callback如何在nodejs中工作。 这将显着帮助您在nodejs中的编码