Sails.js:嵌套的MongoDB查询

时间:2015-08-17 20:06:26

标签: javascript node.js sails.js waterline sails-mongo

我正在使用Sails v0.11并开发一个独立的导入器脚本,以便将数据导入到mongoDB中 - 现在是无法工作的部分 - 在模型之间建立关联。

对于这个过程,我在模型中引入了临时帮助器属性,以便找到相关的记录并用真正的MongoDB _ids替换它们。

  1. 脚本启动Sails以便能够使用其功能(水线等):

    var app = Sails();
    app.load({
      hooks: { grunt: false },
      log: { level: 'warn' }
    
    }, function sailsReady(err){
    
  2. processUsers()查找所有用户及其_id并迭代它们以调用第二个函数addOrgsToOneUser()

    var processUsers = function() {
    
        // Iterate through all users in order to retrieve their _ids and 
        app.models['user'].native(function(err, collection) {
            collection.find({}, projectionOrgInUser).toArray(function (err, users) {  
    
                Async.eachSeries(users, function (user, next){
    
    //                         prepare userInOrgs
    
                    whereUserInOrg = { orgId: { $in: userInOrgs } };
    
                    //This is invoking 
                    addOrgsToOneUser(user, whereUserInOrg);
    
                    next();
                    }, function afterwards (err) {
    
                        if (err) {
                          console.error('Import failed, error details:\n',err);
                          return process.exit(1);
                        }
    
                        console.log("done");
                        return process.exit(0); // This returns too early, not executing the addOrgsToOneUser
                });
            });
        });
    };
    
  3. addOrgsToOneUser()查找属于该用户的所有组织并更新该用户的orgs数组属性

    var addOrgsToOneUser = function(user, whereUserInOrg) {
    
        var projectionUserInOrg = "...";
    
        // Find all orgs that this user is associated to and store it in inOrgs
        app.models['org'].native(function(err, collection) {
            collection.find(whereUserInOrg, projectionUserInOrg).toArray(function (err, orgs) {
    
                // prepare inOrgs which is needed for updating
    
                //update user to have an updated orgs array based on inOrgs. 
                app.models['user'].update({'id' : user._id.toString()}, {'orgs': inOrgs}).exec(function afterwards(err, updated){                
                    console.log('Updated user ' + user._id.toString() + ' to be in their orgs');
                }); 
    
    
            });
        });
    }
    
  4. 问题:

    • 在saddOrgsToOneUser()的查询/更新完成之前调用Process.exit(0)。如果saddOrgsToOneUser()仅包含一个console.log,它的行为与预期的一样,但当然会异步触发查询。
    • 如果我注释掉Process.exit(0),脚本永远不会停止,但查询会按照意图执行。
    • 由于脚本会有进一步的嵌套查询,我需要一个更好的方法来手动终止这个脚本......
    • 如何正确嵌套查询和迭代结果?

    非常感谢, 曼努埃尔

1 个答案:

答案 0 :(得分:2)

addOrgsToOneUser是异步的。在addOrgsToOneUser中完成所有操作后,需要调用next()。我这样做的方法是传入一个回调(下一个)并在完成所有操作后调用它。所以电话是

addOrgsToOneUser(user, whereUserInOrg, next);

并且addOrgsToOneUser将有一个额外的参数:

var addOrgsToOneUser = function(user, whereUserInOrg, callback) {

  var projectionUserInOrg = "...";

  // Find all orgs that this user is associated to and store it in inOrgs
  app.models['org'].native(function(err, collection) {
    collection.find(whereUserInOrg, projectionUserInOrg).toArray(function (err, orgs) {

        // prepare inOrgs which is needed for updating

        //update user to have an updated orgs array based on inOrgs. 
        app.models['user'].update({'id' : user._id.toString()}, {'orgs': inOrgs}).exec(function afterwards(err, updated){                
            console.log('Updated user ' + user._id.toString() + ' to be in their orgs');

            callback();  // your original next() is called here
        }); 


    });
  });
}