Sails.js: вложенные запросы MongoDB

Я использую 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');
                }); 
    
    
            });
        });
    }
    

Проблема:

  • Process.exit (0) вызывается до завершения запроса / обновления saddOrgsToOneUser (). Он ведет себя так, как ожидалось, если saddOrgsToOneUser () содержит, например, только console.log, но, конечно, запросы запускаются асинхронно.
  • Если я закомментирую Process.exit (0), сценарий никогда не останавливается, но запросы выполняются так, как задумано.
  • Поскольку у скрипта будут дополнительные вложенные запросы, мне нужен лучший подход к этому, так как вручную убить этот скрипт ...
  • Как правильно выполняется вложение запросов и итерация по их результатам?

Большое спасибо, Мануэль


person Manuel Reil    schedule 17.08.2015    source источник


Ответы (1)


addOrgsToOneUser асинхронный. next () необходимо вызвать после того, как все будет выполнено внутри addOrgsToOneUser. Я бы сделал это так, чтобы передать обратный вызов (следующий) и вызвать его, когда все будет сделано. Итак, звонок

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


    });
  });
}
person Ben    schedule 17.08.2015