我需要将CSV文件(大约20K行)中的数据导入我的数据库。某些行可能已存在于数据库中,因此只需要更新它们,但必须插入新行。如果任何操作失败,则必须取消该交易。
我该怎么做?这是我正在使用的代码:
num_threads
此代码位于for循环中,但在第二次迭代中失败,可能是因为var vehicle = {
id: row.id,
lastUpdate: moment(row.lastUpdate, 'DD/MM/YYYY - HH:mm').toDate(),
version: row.version,
color: row.color,
location: row.location,
status: row.status
};
Vehicle.forge({
id: row.id
})
.save(vehicle, { transacting: t, patch: true })
.then(model => {
console.log('*************' + vehicle.id);
})
.catch(Vehicle.NoRowsUpdatedError, err => {
// There are no rows for this chassis, so let's insert it
Vehicle.forge(vehicle)
.save(null, { transacting: t, method: 'insert' })
.then(model => {
console.log('++++++++++++++' + vehicle.id);
})
.catch(err => {
console.log(`INSERT ERROR: ${err.message}`);
t.rollback();
return res.json({ status: false, count: 0, error: err.message });
});
})
.catch(err => {
console.log(`UPDATE ERROR: ${err.message}`);
t.rollback();
return res.json({ status: false, count: 0, error: err.message });
});
之间的并发性。
我还尝试将自定义函数添加到我的模型文件中,但它说该函数不存在。
promises
答案 0 :(得分:2)
您可以直接使用knex来代替使用书架。只需抓住传递给书架的knex实例,就可以像这样使用它:
knex.transaction((trx) => {
return Bluebird.map(vehicles, vehicle => {
const insert = knex('vehicles').insert(vehicle).toString();
delete vehicle.id;
const update = knex('vehicles').update(vehicle).toString();
const set = update.substring(18);
return trx.raw(`${insert} ON CONFLICT (id) DO UPDATE ${set}`);
});
});
我们可以利用Knex的方便toString
方法为我们生成大部分原始查询;通过这种方式,我们可以做一个upsert,即使它没有Knex直接支持。 Bluebird的map
函数非常适合干净地处理这样的数据数组,并且可以让你等待完全遍历它。