2013-09-08 1 views
1

Может кто-нибудь просветить меня решением для следующей ситуации?Добавить дополнительные свойства к результатам, полученным от NodeJS (экспресс) + MongoDB - имитировать SQL-соединение

У меня есть приложение регистрации, написанное в nodeJS express framework и использующее коллекции MongoDB. Мне удалось получить результаты из коллекции, но я хочу повторить результаты, запросить другую коллекцию на основе идентификатора ссылки из первого запроса и добавить больше значений в исходные результаты, а затем отправить ответ клиенту.

Я вставлю ниже то, что я сейчас закодировал, но я не могу заставить его работать. Я либо делаю это неправильно, либо моя желаемая логика не правильная.

Пожалуйста, помогите мне с более чем теорией и тем фактом, что я не могу использовать результаты вне асинхронной функции JS.

Заранее благодарен!

КОД:

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); 
    }); 
} 

ответ

2

Ваша функция findOneBy является асинхронной. Поскольку ваш код проходит через массив результатов, хранящихся в items, каждый из них запускает асинхронный поиск.

Однако перед тем, как все возвратятся, вы отправляете результаты клиенту через `res.send (results). Таким образом, пока данные возвращаются в приложение Node.JS, это после, результаты уже отправлены.

Есть несколько способов справиться с этим, но я предлагаю вам рассмотреть логику больше, как это (псевдо-код, так как у меня нет DB зеркального отображения данных):

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, но это не приведет к существенному изменению того, что вам нужно сделать.

+0

Спасибо за ваше утомительное объяснение и ответили кодом. Это именно то, что мне нужно, и работает так, как ожидалось. Кроме того, для меня теперь стало более понятным, как должна выглядеть логика для этого. Ты мужчина! Желаю хорошей недели! –

0
 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) 
    } 

ли это помощь? Если не объясните, какие ошибки или результаты вы получаете

+0

Я думаю, что делаю именно то, что вы предложили, не так ли? У меня проблема там, где я совмещаю результаты, и я думаю, проблема в том, что я делаю это в асинхронной функции, но я не могу понять, как сделать результат, найденный в findOneBy, привязанным к объекту журнала, потому что, если я запишу ' log' внутри этой функции. Это похоже на то, что мне это нужно. –

+0

Я думаю, что мой код делает именно то, что вы предложили. У меня возникла проблема с созданием результата (single) из findOneBy на объект «log» после запуска асинхронной функции, потому что, если я выхожу на консоль, я вижу, что там мой объект выглядит точно так, как он мне нужен. –

+0

Итак, мой вопрос к вашему ответу: «// принять ваши новые результаты и объединить их с начальными результатами» можно сделать как? –

 Смежные вопросы

  • Нет связанных вопросов^_^