1

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 Answer 1

2

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


    });
  });
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.