mongodb查询内的多个查询 [英] Multiple queries inside mongodb query

查看:90
本文介绍了mongodb查询内的多个查询的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尝试基于mongodb上另一个查询的结果进行查询时遇到问题.

I'm having an issue when trying to query based on the result of another query on mongodb.

我正在尝试进行初始查询,然后对第一个查询的每个结果进行另一个查询.之所以这样做,是因为我有两个不同的集合,并且需要将一个集合中的某些数据与另一个集合中的数据连接起来.在SQL世界中,我可以轻松地使用JOIN做到这一点,但是由于我在此代码中使用mongodb,所以我实际上并不能真正使用JOIN,因此我猜想在第一个查询的回调函数中进行for循环将是可行的方法

I'm trying to make an initial query and then do another query for each one of the result of the first query. The reason I'm doing it like this is because I have two different collections and I need to join some data from one collection with the data of the other collection. In a SQL world I could easily do this with a JOIN, but as I'm using mongodb in this one I can't really use JOINs, so I guessed doing a for loop inside the first query's callback function would be the way to go.

这是我正在使用的代码...

Here's the code I'm using...

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数组.

I need to res.send the resultSet array after all the values have been added.

我尝试了其他方法,但是事实是,当到达res.send行时,第二个查询根本没有完成.我也尝试在内部查询的回调中执行此操作,但我需要检查它是否是for循环中的最后一个,并且检查值o m不会执行该操作,因为它始终等效于docs.length.

I've tried some other ways of doing this, but the thing is that when the res.send line is reached the second query hasn't finished at all. I also tried doing that inside the inner query's callback, but I need to check if it's the last in the for loop, and checking the value o m won't do it as it always is equivalent to docs.length.

据我所知,在mongodb中没有同步查询之类的东西,但也许我错了.

As far as I know there's no such thing as a synchronous query in mongodb, but maybe I'm wrong.

做这件事的正确方法是什么?

What's the right way of doing this?

编辑

我找到了解决方法,但是我敢肯定必须有一个更好的方法.这就是我的做法...

I found a way around it, but I'm sure there's got to be a better way. Here's how I'm doing it...

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

推荐答案

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

Your updated solution in your question is generally fine, as using $in is an excellent way of fetching a set of results (you'll want to make sure that you've indexed the id_bus property).

以下是一些调整(需要一些清理和优化):

Here are a few tweaks (with a bit of cleanup and optimization):

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

这篇关于mongodb查询内的多个查询的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆