【问题标题】:How to insert bulk data to postgresql db from CSV file?如何将批量数据从 CSV 文件插入到 postgresql db?
【发布时间】:2019-03-15 00:03:36
【问题描述】:

我必须将 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')
        })
}

路由器.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' ]

【问题讨论】:

  • 你必须通过代码来做到这一点吗?你不能直接打开 pgAdmin 并以这种方式导入吗?简单了 10000%...stackoverflow.com/questions/19400173/…
  • 您也可以使用psql。 (例如psql -h $SERVER_IP -d $DB -U $USERNAME -c "\copy tmp_special_phrases(word,Key,Value,Plural) from './special_phrases.csv' with delimiter as ',' CSV HEADER"
  • @dvsoukup 它只能通过代码完成,而不是来自 pgAdmin 面板

标签: node.js postgresql csv sequelize-cli


【解决方案1】:

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

替换:

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

与:

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

【讨论】:

  • 请记住,这也会导致高内存使用,因为 postgre 池将阻止大部分查询。 on('data') 事件处理程序不是异步的,在发出更多事件之前不会等待async 函数的执行。请参阅我的答案,了解在将数据插入数据库之前仅读取所需部分数据的解决方案。
【解决方案2】:

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

ES6 async/await 是一种语言结构,它允许您 await 解析 Promise 并继续执行 async 函数中的代码。在您的代码中,您确实有一个 async function 声明,但是您在非异步函数中添加了 await。澄清 - await 关键字只有在最接近的 function() {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。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-28
    • 2020-07-18
    相关资源
    最近更新 更多