2015-06-08 130 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); 
});