附加更多的属性,从NodeJS(快速)+ MongoDB检索结果 – 模拟SQL连接

有人能给我解决以下情况的解决办法吗?

我有一个用nodeJS express框架编写并使用MongoDB集合的日志应用程序。 我设法从一个集合中获得结果,但我想迭代结果,根据第一个查询中的引用ID查询另一个集合,并将更多的值附加到初始结果中,然后将响应发送到客户端。

我会粘贴我现在编码,但我不能得到它的工作。 我要么做错了,要么我想要的逻辑不是正确的。

请帮助我超过理论和事实,我不能使用asynchronousJS函数以外的结果。

提前致谢!

码:

exports.findLogs = function(req, res) { var params = req.body; var query = req.query; var coll = params.section; if (coll === undefined) { coll = 'traces'; } db.collection(coll, function(err, collection) { collection.count(function(err, count) { var criteria = { 'limit': limit, 'skip': skip, 'sort': [[options.sortname, options.sortorder]] } collection.find({}, criteria).toArray(function(err, items) { Object.keys(items).forEach(function(logIndex) { var trace = items[logIndex]; var crit = { 'find': {LogId: trace.LogId}, 'projection': {}, 'limit': 1 } // Get entry based on Criteria from `log` table findOneBy(crit, 'log', function(err, log) { if (log.length !== 1) { // no reference found } else { // Appending here to log DOES NOT stick as expected trace.ComputerName = log.ComputerName; trace.ComputerIP = log.ComputerIP; trace.LastSeen = log.LastSeen; trace.TestVar = 'test1234'; } }); // Appending here to trace works as expected trace.Actions = 'MyAction'; }); results['total'] = count; results['results'] = items.length; results['rows'] = items; res.send(results); }); }); }); } function findOneBy(criteria, coll, callback) { var cFind = criteria.find; var cProj = criteria.projection; db.collection(coll, function(err, collection) { if (err) return callback(err); else return collection.find(cFind, cProj).toArray(callback); }); } 

你的函数findOneBy是asynchronous的。 当你的代码遍历存储在items的结果数组时,每一个都会触发asynchronous查找。

但是,在所有这些返回之前,您通过`res.send(results)将结​​果发送到客户端。 所以,当数据被返回到Node.JS应用程序时,结果已经被发送了。

有几种方法来处理这个问题,但我build议你考虑更像这样的逻辑(伪代码,因为我没有一个数据库镜像你的数据):

 collection.find({}, criteria).toArray(function(err, items) { var allLogIds = []; var logIdsByUse = {}; Object.keys(items).forEach(function(logIndex) { // here, we'll first bit a list of all LogIds var trace = items[logIndex]; allLogIds.push(trace.LogId); // now build a index of logId and a list of dependent objects logIdsByUse[trace.LogId] = [] || logIdsByUse[trace.LogId]; logIdsByUse[trace.LogId].push(trace); }); // now that the LogIds are all gathered, we'll do a search for all of them // at once. // *** You should make certain that the LogId field is indexed or this will // *** never perform adequately in any situation db.collection("log", function(err, collection) { if (err) { /* do something with the error, maybe 500 error */ } else { collection.find({ LogId: { $in : allLogIds}}) .toArray(function(err, logs) { logs.forEach(function(log) { // grab the LogId, // get the array of traces that use the LogId // from the logIdsByUse[LogId] // loop through that array, and do the fix up that you // want }); // now, you may send the results results['total'] = count; results['results'] = items.length; results['rows'] = items; res.send(results); }); }); }); 

您也可以使用Node.JS的一个asynchronous库,但不会显着改变您需要做的事情。

  callMe(function(initialResults) { //iterate over the array or object //take your new results and combine them with the initial Results, //To be done differently depending if you have an array, object, or array of objects. res.send(newResults) }; function callMe(callback) { //query your database and get your first results callback(initialResults) } 

这有帮助吗? 如果不解释你得到什么样的错误或结果