如何从CSV文件向Postgresql数据库插入批量数据?

时间:2018-10-10 06:38:53

标签: node.js postgresql csv sequelize-cli

我必须将CSV文件中存在的100多个记录插入到PostgreSQL数据库中。所以我尝试了下面提到的代码,它正在从文件中读取数据,但是无法将它们插入到PostgreSQL表中,所以还有其他方法可以执行此操作吗?像csvtojson等?

const csv = require('csv');
var csvParser = require('csv-parse');

Controller.uploadCsv = async(data) => {
    fs.createReadStream(data.path)
        .pipe(csvParser({
            delimiter: '\t', 
            endLine: '\n', 
            escapeChar: '"', 
            enclosedChar: '"'
        }))
        .on('data', function(data) {
             console.log(data)// returning in console mentioned below
             console.log(data.name) // is undefined 

             const add = {
                name: data.name,
                address: data.address,
                phoneNo: data.phoneNumber,
                email: data.email,
                created_at: new Date(),
                updated_at: new Date()
            };
            const result = await models.table.create(add);
        })
        .on('end', function(data) {
             console.log('reading finished')
        })
}

router.js

router.post('/file', upload.single('file'),(req, res, next) => {
    Controller.uploadCsv(req.file)
        .then((result) => res.json(result))
        .catch(next)
})

控制台数据

    [ 'name',
      'address'
      'phoneNumber',
      'email',
      'created_at',
      'updated_at']
    [ 'aaa',
      'delhi',
      '1102558888',
      'test@gmail.com',
      '2017-10-08T06:17:09.922Z',
      '2018-10-08T06:17:09.922Z',]
    [ 'Oreo',
      'bgl',
      '1112589633',
      'test123@gmail.com',
      '2017-10-08T06:17:09.922Z',
      '2018-10-08T06:17:09.922Z' ]

2 个答案:

答案 0 :(得分:0)

TL; DR。 。您的代码有一个小错误,可能会引起您的问题-使用await时,需要运行它将async放在function处理程序的data之前-可能适用于小文件,但是请阅读这不是正确的解决方案-我在下面添加了一种适当的方法

ES6异步/等待是一种语言构造,使您可以await来解决Promise,并继续在async函数中执行代码。在代码中,您确实有一个async function声明,但是您在非异步函数中添加了await。需要说明的是-仅在最接近的awaitfunction() {时才允许使用async关键字-在您的情况下则不允许。

我实际上不认为您的代码甚至无法编译,经过一些更改,您将直接陷入this question中提到的问题-这是因为您试图在同步事件上运行异步操作节点中的处理程序。此对数据库的异步插入将开始运行,但是end事件将在操作完成之前触发

为了正确执行此操作-您可以完全使用转换流或完全放弃流,而仅使用CSV中的数组(为此,有足够多的好模块了)。但是,我是scramjet框架的作者,我也认为这应该像您编写时那样简单,甚至可能更简单。

以下代码将执行您想要的操作:

const {StringStream} = require('scramjet');

Controller.uploadCsv = async(data) => 
    fs.createReadStream(data.path)
        .pipe(new StringStream('utf-8'))
        .CSVParse({
            delimiter: '\t', 
            newline: '\n', 
            escapeChar: '"', 
            quoteChar: '"'
        })
        .map(data => ({
            name: data.name,
            address: data.address,
            phoneNo: data.phoneNumber,
            email: data.email,
            created_at: new Date(),
            updated_at: new Date()
        }))
        .each(async entry => await models.table.create(entry))
        .each(result => log(result)) // if it's worth logging
        .run();

Scramjet仅在下面使用流(所有类都扩展了内置的node.js流),但在Array等上公开了类似于同步接口的接口。您可以运行异步操作,并从run返回Promise操作。

答案 1 :(得分:0)

在OnData函数上插入 async 关键字。请记住,它不是顺序执行,因此在一个程序执行与另一个程序执行之间,记录可能以完全不同的顺序插入。

替换:

.on('data', function(data) {

使用:

.on('data', async function(data) {