mongodb查询里面有多个查询

在尝试根据mongodb上的另一个查询的结果进行查询时遇到问题。

我试图做一个初步的查询,然后对第一个查询的结果中的每一个做另一个查询。 我这样做的原因是因为我有两个不同的集合,我需要从一个集合中join一些数据与另一个集合的数据。 在一个SQL世界中,我可以很容易地使用JOIN来做到这一点,但是因为我在这个中使用了mongodb,所以我不能真正使用JOIN,所以我猜想在第一个查询的callback函数内部做一个for循环是要走的路。

这是我正在使用的代码…

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 resultSet数组。

我已经尝试了一些其他的方式来做到这一点,但事情是,当res.send行到达第二个查询还没有完成。 我也尝试过在内部查询的callback中做这件事,但是我需要检查它是否是for循环中的最后一个,并且检查值om将不会执行,因为它总是等同于docs.length

据我所知在mongodb中没有同步查询这样的事情,但也许我错了。

什么是这样做的正确方法?

编辑

我find了一个方法,但我相信有一个更好的方法。 我是这么做的

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

您的问题中更新的解决scheme通常很好,因为使用$in是获取一组结果的绝佳方法(您需要确保已经为id_bus属性编制索引)。

这里有一些调整(有一些清理和优化):

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

Node.js的行为是asynchronous的,程序员必须考虑到这个行为。 使用callback或承诺或stream量控制库。 在你的程序中,你已经把mongo查询放在循环里了,这是一个不好的查询方法。 相反,如果多次查询,请使用$ in操作符。 它将优化您的代码性能,并解决您的响应发送问题。

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