Node.js数据库从具有Sequelize的文件插入

也许我不完全明白承诺或者Sequalize,但是经过一段时间的处理,感觉asynchronousDB操作只适用于简单的情况。 并且通过询问同步数据库访问的问题的数量,它看起来并不是唯一的。

这是我的情况。 假设我们有化合物的CSV文件,其中每行包含有关化合物的信息,以及以分号分隔的其成分列表。 我们希望从其中填充成分表,但没有重复。

例如,如果文件包含行

C1 IngA; IngB

C2 IngA; IngC

我们想要三个loggingIngA,IngB和IngC的成分表。 所以当阅读行时,应该保存复合体,对于每个成分检查是否已经存在,如果不添加。 这里是代码:

var lineReader=require('readline').createInterface({ input: require('fs').createReadStream(filename) }); lineReader.on('line', function(line) { let parts=line.split('\t'); compoundModel.create({ name: parts[0], }).then(entity => { let ingredients=parts[1].split(';'); ingredients.forEach((ing, index) => { ingModel.findOne({ where: {name: ing} }).then(ingEntity => { if (ingEntity) { return ingEntity; } return ingModel.create({ name: ing }) }); }).then(ingEntity => { //something else }); }); }); 

问题在于IngA被插入到表中两次。 我的猜测是find或创buildSequelize方法返回承诺,并从数据库插入文件行读取更快。 因此,在读取新行并尝试findIngA时,第一行的IngA尚未插入。

我尝试了几种方法,但是对于这类任务来说,一切看起来都太复杂了。 而更重要的是,不起作用。

您需要通过locking进行交易。

做一个表级locking,以防止在你的情况下发生幻读

http://docs.sequelizejs.com/en/v3/api/transaction/

请在下面的解决scheme,它应该工作。

 var await = require('asyncawait/await'); var lineReader=require('readline').createInterface({ input: require('fs').createReadStream(filename) }); lineReader.on('line', function(line) { let parts=line.split('\t'); compoundModel.create({ name: parts[0], }).then(entity => { let ingredients=parts[1].split(';'); ingredients.forEach((ing, index) => { await(ingModel.findOrCreate({ where: {name: ing}, defaults: {name: ing}, }).spread(function(_record, _created){ //Do something if required. _create will return true in case of entry already exists })) }).then(ingEntity => { //something else }); }); }); 

在执行这个之前,请执行npm install asyncawait 。 在await的帮助下,它将等待,直到承诺完成它的执行,然后再执行下一个承诺。