2014-04-18 10 views
1

mongodb에 대한 다른 쿼리 결과를 기반으로 쿼리를 수행 할 때 문제가 있습니다.mongodb 쿼리 내의 복수 쿼리

초기 쿼리를 만들고 첫 번째 쿼리의 결과 각각에 대해 다른 쿼리를 수행하려고합니다. 이런 식으로하는 이유는 두 개의 서로 다른 컬렉션이 있고 한 컬렉션의 데이터 중 일부를 다른 컬렉션의 데이터와 조인해야하기 때문입니다. SQL 세계에서 나는 JOIN으로 이것을 쉽게 할 수 있지만,이 중 하나에서 mongodb를 사용하고 있기 때문에 JOIN을 실제로 사용할 수 없다. 그래서 첫 번째 쿼리의 콜백 함수 내에서 for 루프를 수행하는 것이 길일 것이라고 추측했다. .

은 여기에 모든 값을 추가 한 후 결과 집합 배열을 res.send 필요

var resultSet = []; 
db.get('busstopcollection').find({id_bus_stop: parseInt(req.body.busstopid)}, function(e, docs){ 
    if(e || docs.length === 0) { 
     console.log("Sorry, wrong id."); 
     return e; 
    } 
    for(var m=0; m<docs.length; m++){ 

     var auxRes = {}; 
     auxRes.id_bus = docs[m].id_bus; 
     auxRes.id_bus_stop = docs[m].id_bus_stop; 
     auxRes.coord_x = docs[m].coord_x; 
     auxRes.coord_y = docs[m].coord_y; 
     auxRes.id_bus_variation = docs[m].id_bus_variation; 
     db.get('buscollection').find({id_bus: parseInt(docs[m].id_bus)}, function(e, busDocs){ 
      auxRes.s_origin_description = busDocs[0].s_origin_description; 
      auxRes.s_destination_description = busDocs[0].id_destination_description; 
      resultSet.push(auxRes); 
     }); 
     res.send(JSON.stringify(resultSet)); 
    } 
}); 

... 내가 사용하는 코드입니다.

다른 방법을 시도했지만, res.send 행에 도달하면 두 번째 쿼리가 전혀 완료되지 않은 것입니다. 또한 내부 쿼리의 콜백 내부에서 그 일을 시도했지만 for 루프의 마지막인지 확인하고 값을 확인하는 것은 항상 docs.length과 동일하므로 값을 확인하지 않아도됩니다.

내가 아는 한 mongodb에는 동기 쿼리와 같은 것이 없지만 어쩌면 틀렸어.

이 작업을 수행하는 올바른 방법은 무엇입니까?

편집

나는 주위에 방법을 발견,하지만 난 더 나은 방법이있을거야 확신합니다. 여기에 프로그래머는이 동작의 고려를 복용 코딩하는,

db.get('busstopcollection').find({id_bus_stop: parseInt(req.body.busstopid)}, function(e, docs){ 
    if(e || docs.length === 0) { 
     console.log("Ha ocurrido un error, no existe esa parada"); 
     return e; 
    } 
    var busIDs = []; 
    for(var m=0; m<docs.length; m++){ 
     busIDs.push(parseInt(docs[m].id_bus)); 
     var auxRes = {}; 
     auxRes.id_bus = docs[m].id_bus; 
     auxRes.id_bus_stop = docs[m].id_bus_stop; 
     auxRes.coord_x = docs[m].coord_x; 
     auxRes.coord_y = docs[m].coord_y; 
     auxRes.id_bus_variation = docs[m].id_bus_variation; 
     resultSet.push(auxRes); 
    } 
    db.get('buscollection').find({id_bus: {$in: busIDs}}, function(e, busDocs){ 
     for(var n = 0; n<busDocs.length; n++){ 
      for(var k=0; k<resultSet.length; k++){ 
       if(resultSet[k].id_bus == busDocs[n].id_bus){ 
        resultSet[k].s_origin_description = busDocs[n].s_origin_description; 
        resultSet[k].s_destination_description = busDocs[n].id_destination_description; 
       } 
      } 
     } 
     res.send(JSON.stringify(resultSet)); 
    }); 
}); 

답변

1

업데이트 된 솔루션은 일반적으로 괜찮습니다.

db.get('busstopcollection') 
    .find({id_bus_stop: parseInt(req.body.busstopid)}).toArray(function(e, docs){ 
    var auxById = {}; // store a dictionary of all the results for later 
    if(e || docs === null || docs.length === 0) { 
     console.log("Ha ocurrido un error, no existe esa parada"); 
     return e; 
    } 
    var busIDs = []; 
    docs.forEach(function(doc) { 
     busIDs.push(parseInt(doc.id_bus)); 
     // consider just using the doc directly rather than copying each property 
     // especially if you're not manipulating any of the data as it passes 
     var auxRes = {   
      id_bus : doc.id_bus, 
      id_bus_stop : doc.id_bus_stop, 
      coord_x : doc.coord_x, 
      coord_y : doc.coord_y, 
      id_bus_variation : doc.id_bus_variation 
     }; 
     // you could just use each doc directly ... 
     // var auxRes = doc; ?? 
     // ** importantly, store off the id_bus for each one so you can 
     // ** avoid a costly loop trying to match an id below. 
     auxById[doc.id_bus] = auxRes; 
     resultSet.push(auxRes); 
    }); 
    // might want to consider using a cursor ... here's an example 
    db.get('buscollection') 
     .find({id_bus: {$in: busIDs}}).each(function(e, busDoc){ 
     // the last item in the cursor will be null 
     if (busDoc === null) { 
      res.send(JSON.stringify(resultSet)); 
      return; 
     } 
     var res = auxById[busDoc.id_bus]; 
     if (res) { // did we find it in our dictionary of results? 
      // yes, we did == copy the necessary field data 
      res.s_origin_description = busDoc.s_origin_description; 
      res.s_destination_description = busDoc.id_destination_description; 
     }    
    }); 
}); 
2

Node.js를 동작은 비동기입니다 ... 나는 그것을하고있어 방법입니다. 콜백이나 약속 또는 흐름 제어 라이브러리를 사용하십시오. 귀하의 프로그램에서 은 루프 내부에 mongo query를 넣었습니다. 이는 잘못된 쿼리 방법입니다. 대신 여러 번 쿼리하는 경우 연산자에서 $를 사용하십시오. 그것은 귀하의 코드 성능을 최적화하고 귀하의 응답 보내는 문제도 해결할 수 있습니다. $in를 사용하여 결과 세트를 (당신이 id_bus 속성을 인덱스했는지 확인하는 것이 좋습니다) 가져 오는 중 훌륭한 방법입니다 귀하의 질문에

var resultSet = []; 
     db.get('busstopcollection').find({id_bus_stop: parseInt(req.body.busstopid)}, function(e, docs){ 
      if(e || docs.length === 0) { 
       console.log("Sorry, wrong id."); 
       return e; 
      } 
      var bus_ids = []; 
      for(var m=0; m<docs.length; m++){ 
       var auxRes = {}; 
       auxRes.id_bus = docs[m].id_bus; 
       bus_ids.push(parseInt(docs[m].id_bus)); // collect all ids 
       auxRes.id_bus_stop = docs[m].id_bus_stop; 
       auxRes.coord_x = docs[m].coord_x; 
       auxRes.coord_y = docs[m].coord_y;    
       auxRes.id_bus_variation = docs[m].id_bus_variation; 
       resultSet.push(auxRes);   

      } 
      // Query at one time for all document 
      db.get('buscollection').find({id_bus: {$in : bus_ids}}).toArray(function(e, busDocs){ 
        // Now find and merge in one go 
        busDocs.forEach(function(eachBusDoc){ 
         for(var i=0,len = resultSet.length;i< len;i++){ 
          if(resultSet[i].id_bus == busDocs.id_bus){ 
           resultSet[i].s_origin_description = eachBusDoc.s_origin_description; 
           resultSet[i].s_destination_description = eachBusDoc.id_destination_description; 
          } 
         } 
        });    
         res.send(JSON.stringify(resultSet)); 
       }); 
     }); 
+0

그래, 그건 나도 알아 낸 것을 사실입니다 : 여기

은 (정리 및 최적화의 비트와 함께) 몇 개조하면 되겠 어 있습니다. 나는 그때 그것을하는 다른 방법이 없다고 생각한다. 귀하의 답변 주셔서 감사합니다! – lascort

+0

재귀를 사용할 수 있지만 다시 mongodb를 여러 번 쿼리하게됩니다. – Sumeet