Sails.js: Nested MongoDB queries

旧街凉风 提交于 2019-12-24 13:24:42

问题


I am using Sails v0.11 and am developing an standalone importer script in order to import data to mongoDB and - that is now the not-working part - build the associations between the models.

For this process I introduced temporary helper properties in the models in order to find the associated records and replace them by in real MongoDB _ids.

  1. The script starts Sails in order to be able use its features (waterline, etc.):

    var app = Sails();
    app.load({
      hooks: { grunt: false },
      log: { level: 'warn' }
    
    }, function sailsReady(err){
    
  2. processUsers() finds all users and their _ids and iterates over them to invoke a second function 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() finds all orgs belonging to THIS user and updates then the orgs array property of THIS user

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

Problem:

  • Process.exit(0) is called before the query/update of saddOrgsToOneUser() has completed. It behaves as expected if saddOrgsToOneUser() contains just a console.log for instance, but queries are triggered ansynchronously of course.
  • In case I comment out Process.exit(0), the script never stops, but the queries are executed as intented.
  • As the script will have further nested queries, I need a better approach to this as manually kill this script ...
  • How is nesting queries and iterating over their results done properly?

Thank you very much, Manuel


回答1:


addOrgsToOneUser is asynchronous. next() needs to be called after everything is done inside addOrgsToOneUser. The way I would do it is to pass in a callback (next) and call it when everything is done. So the call is

addOrgsToOneUser(user, whereUserInOrg, next);

and the addOrgsToOneUser will have an extra argument:

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


    });
  });
}


来源:https://stackoverflow.com/questions/32058797/sails-js-nested-mongodb-queries

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!