2013-09-08 2 views
1

누군가 다음 상황에 대한 해결책을 제시 할 수 있습니까?NodeJS (express) + MongoDB에서 검색된 결과에 더 많은 속성 추가 -SQL 시뮬레이션

로깅 응용 프로그램을 nodeJS express 프레임 워크로 작성하고 MongoDB 콜렉션을 사용합니다. 나는 컬렉션에서 결과를 얻을 수 있었지만 결과를 반복하고 첫 번째 쿼리의 참조 ID를 기반으로 다른 컬렉션을 쿼리 한 다음 초기 결과에 더 많은 값을 추가 한 다음 클라이언트에 응답을 보냅니다.

내가 코딩 한 내용을 아래에 붙여 넣겠습니다.하지만 제대로 작동하지 않습니다. 나는 그것을 잘못하고 있거나 내 원하는 논리가 옳지 않다.

비동기 JS 함수 밖에서 결과를 사용할 수 없다는 이론과 사실 이상으로 도와주세요.

미리 감사드립니다.

CODE :

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

내 코드가 제안한 것과 정확히 일치한다고 생각합니다. 비동기 함수가 실행 된 후 findOneBy 결과를 (단일) 결과를 만드는 데 문제가 있습니다. 왜냐하면 콘솔에 출력하면 내 객체가 정확히 필요한 방식으로 보이기 때문입니다. –

+0

귀하의 답변에 대한 나의 질문은 : "// 새로운 결과를 가져 와서 초기 결과와 결합"하는 방법은? –