我如何通过两个独立的查询查询mongoose依赖于父查询?

时间:2014-10-14 16:33:14

标签: node.js mongodb mongoose

var EmpSchema = {_id:String, empName:String}
var ProjectSchema = {_id:String, projectName}
var reportSchema = {empId:String, projectId:String, comments:String}
//These are two many to many relations

现在,当我使用mongoose查询报告架构并将empId,empName,projectId,projectName,注释存储在每个报告的数组中时,我会遇到不一致的情况。

var showDetails = []
reportModel.find({}, function(err, reps){
    var dispItem = {};
    reps.forEach(function(value, index, arr){

        //querying empColl
        empModel.findOne({value.empId},function(err, emp){
          dispItem["empName"] = emp.empName;
        });

        //querying projectColl
        projectModel.findOne({value.projectId},function(err, pro){
          dispItem["projectName"] = pro.projectName;
        });

        dispItem["comments"] = pro.comments;
        showDetails.push(dispItem);
    });
    res.end(showDetails);
});

请忽略任何语法错误。我在这里要问的是查询empColl和projectColl的两个回调是独立的并且同时被解雇了。所以showDetails中的数据不正确。 我尝试嵌套两个查询,这也没有工作(不一致)。也许承诺是要走的路? (承诺的新手)

1 个答案:

答案 0 :(得分:2)

嵌套调用应该有助于构建每个dispItem。

但是你需要一些方法来检测它们在res.end(showDetails);之前完成的时间 你可以用一个计数器来做到这一点:

var showDetails = []
reportModel.find({}, function(err, reps){
    var numLeft = reps.length;
    reps.forEach(function(value, index, arr){

        //querying empColl
        empModel.findOne({_id : value.empId},function(err, emp){
            projectModel.findOne({_id : value.projectId},function(err, pro){
                showDetails.push({
                    empName     :  emp.empName,
                    projectName : pro.projectName,
                    comments    : pro.comments
                });
                if ( --$numLeft === 0 ) {
                    res.end(showDetails);
                }
            });
        });
    });
});

或承诺方式:

var repsPromises = [];
reportModel.find({}, function(err, reps){
    var repDefer = Q.defer();
    repsPromises.push(repDefer.promise);
    reps.forEach(function(value, index, arr){

        var empDefer = Q.defer();
        var proDefer = Q.defer();

        //querying empColl
        empModel.findOne({value.empId},function(err, emp){
            if ( err ) { empDefer.reject(err); }
            else       { empDefer.resolve(emp); }
        });

        //querying projectColl
        projectModel.findOne({value.projectId},function(err, pro){
            if ( err ) { proDefer.reject(err); }
            else       { proDefer.resolve(pro); }
        });

        Q.all([empDefer.promise, proDefer.promise])
        .then(
            function (emp, pro) {
                repDefer.resolve({
                    empName     : emp.empName,
                    projectName : pro.projectName,
                    comments    : pro.comments
                });
            },
            function (err) {
                console.log("The first error encountered was: "+err);
                repDefer.reject(err);
            }
        );
    });
});

Q.all(repsPromises)
.then(
    function () {
        res.end(Array.prototype.slice.call(arguments, 0));
    },
    function (err) {
        console.log("The first error encounter was: "+err);
    }
);