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

How to insert bulk data to postgresql db from CSV file?

我必须将 CSV 文件中存在的 100 多条记录插入到 PostgreSQL 数据库中。所以我尝试了下面提到的代码,它正在从文件中读取数据但无法将它们插入到 PostgreSQL table 那么有没有其他方法可以执行此操作?比如 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' ]

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

ES6 async/await 是一种语言结构,允许您 await 解决 Promise 并继续执行 async 函数中的代码。在您的代码中,您确实有一个 async function 声明,但是您在非异步函数中添加了 await 。澄清 - 只有当最接近的 function() {async 时才允许使用 await 关键字 - 在你的情况下它不是。

实际上我认为您的代码甚至无法编译,经过一些更改后您会直接遇到 中提到的问题 - 这是因为您正在尝试 运行节点中同步事件处理程序的异步操作。此异步插入数据库将获得 运行,但 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 等上公开一个类似于同步接口的接口。你可以 运行 你的异步操作,它 returns 来自 run 操作的 Promise。

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

替换:

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

与:

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