2015-06-08 27 views
0

我收到一个包含产品列表的CSV文件。每个产品都有一个类别。当我保存产品时,我必须查找数据库中是否存在类别,如果不存在,我必须在保存产品之前创建它(并保存它)。使用Node.js在Mongodb中嵌套插入

module.exports.do_import = function (req, res) { 
var final_json = {}; 
fs.createReadStream(req.files.file.path) 
    .pipe(csv({ 
     separator: ';' 
    })) 
    .on('data', function (data) { 

     mongoose.model("Category").findOne({nombre: data.NOMBRE}, function (err, category) { 
      if (category == null) { 
       var created_category = new Category({nombre: data.NOMBRE}); 
       created_category.save(function (err, __category) { 
              var product = new Product({ 
         nombre: data.NOMVDA, 
         categoria: __category, 
         codigo: data.CODVAR 
        }); 
        product.save(function (err, prod) { 
         if (err) { 
          final_json.success = false; 
          res.json(final_json); 
         } 
        }); 
       }); 
      } else { 
       var product = new Product({ 
        nombre: data.NOMVDA, 
        categoria: category, 
        codigo: data.CODVAR 
       }); 
       product.save(function (err, prod) { 
        if (err) { 
         final_json.success = false; 
         res.json(final_json); 
        } 
       }); 
      } 
     }); 
    }).on('finish', function() { 
     final_json.success = true; 
    }).on('error', function() { 
     final_json.success = false; 
    }).on('end', function() { 
     res.json(final_json); 
    }); 

所以,我这里有麻烦的是,该类别的.save()函数是异步执行的,所以当被请求文件的下一个记录,前一个ISN的类别”还没有保存,所以它创建了两次相同的类别。如何让功能等到保存操作完成?

+2

回调...你必须做每个后续保存在前面返回的回调。这是一个常见问题。 –

+0

作为对@RobertMoskal评论的补充,请将您的回调看作“您程序的其余部分”。这被称为[continuation](http://en.wikipedia.org/wiki/Continuation),是节点中的一个非常基本的原则。 –

+0

但是'data'事件是在我的回调之外触发的,所以当该事件触发时我无法管理 –

回答

0

最后,我的一位朋友帮助我,并感谢这https://nodejs.org/api/stream.html#stream_readable_pause我们可以让流量停止,直到产品已经被创建。 这里是最终的代码:

module.exports.do_import = function (req, res) { 
var final_json = {}; 

var readable = fs.createReadStream(req.files.file.path) 
    .pipe(csv({separator: ';'})); 

function saveErrorHandler(err, prod) { 
    if (err) { 
     final_json.success = false; 
     res.json(final_json); 
    } 
    readable.resume(); 
    console.log('next category'); 
} 

readable.on('data', function (data) { 
    console.log('data'); 
    readable.pause(); 
    console.log('pausa'); 
    mongoose.xmodel("Category").findOne({nombre: data.NOMBRE}, function (err, category) { 
     // Manejá el error que no lo tenes. 
     if (category) { 
      // esto se podría sacar ya que esta duplicado, pasale la categoría a una función 
      var product = new Product({ 
       nombre: data.NOMVDA, 
       categoria: category, 
       codigo: data.CODVAR 
      }); 
      product.save(saveErrorHandler); 
     } else { 
      var created_category = new Category({nombre: data.NOMBRE}); 
      created_category.save(function (err, __category) { 
       var product = new Product({ 
        nombre: data.NOMVDA, 
        categoria: __category, 
        codigo: data.CODVAR 
       }); 
       product.save(saveErrorHandler); 
      }); 
     } 
    }); 
}); 

readable.on('finish', function() { 
    final_json.success = true; 
}); 

readable.on('error', function() { 
    final_json.success = false; 
}); 

readable.on('end', function() { 
    res.json(final_json); 
});