如何将JSON数组从NodeJS流式传输到postgres

时间:2016-01-08 22:48:10

标签: json node.js postgresql express

我试图通过接收来自客户端的请求来插入数百万条记录(大约6个字段/列),每次批量插入尝试使用10,000条记录(使用sequelize。js和bulkCreate()

这显然是个坏主意,所以我试着调查node-pg-copy-streams

但是,我不想在客户端发起更改,其中json数组是这样发送的

# python
data = [
    {
     "column a":"a values",
     "column b":"b values",
    },
    ...
    # 10,000 items
    ...
]
request.post(data=json.dumps(data), url=url)

在nodejs的服务器端,我如何在以下骨架中流式传输收到的request.body

.post(function(req, res){

    // old sequelize code
    /* table5.bulkCreate(
        req.body, {raw:true}
    ).then(function(){
        return table5.findAll();
    }).then(function(result){
        res.json(result.count);
    });*/

    // new pg-copy-streams code
    pg.connect(function(err, client, done) {
    var stream = client.query(copyFrom('COPY my_table FROM STDIN'));
    // My question is here, how would I stream or pipe the request body ?
    // ?.on('error', done);
    // ?.pipe(stream).on('finish', done).on('error', done);
    });
});

2 个答案:

答案 0 :(得分:2)

这是我如何解决我的问题,

首先将我的req.body dict转换为TSV的函数(不是初始问题的一部分)

each

其余的原始.post功能

/**
 * Converts a dictionary and set of keys to a Tab Separated Value blob of text
 * @param {Dictionary object} dict
 * @param {Array of Keys} keys
 * @return {Concatenated Tab Separated Values} String
 */
function convertDictsToTSV(dicts, keys){
    // ...
}

答案 1 :(得分:0)

从技术上讲,这里没有流媒体,不是NodeJS流的工作方式。

每次发送一大块10,000条记录,并希望服务器端插入这些记录并向客户端返回OK以发送另外10,000条记录。那是限制/分页数据,而不是流媒体。

一旦您的服务器收到了接下来的10,000条记录,请插入它们(通常作为一个事务),然后用OK回复客户端,以便它可以发送下一条10,000条记录。

使用node-postgres编写事务并不是一件容易的事,因为它太低级了。

以下是在pg-promise的帮助下如何执行此操作的示例:

function insertRecords(records) {
    return db.tx(t=> {
        var inserts = [];
        records.forEach(r=> {
            var query = t.none("INSERT INTO table(fieldA, ...) VALUES(${propA}, ...)", r);
            inserts.push(query);
        });
        return t.batch(inserts);
    });
}

然后在你的HTTP处理程序中,你会写:

function myPostHandler(req, res) {        
    // var records = get records from the request;    
    insertRecords(records)
        .then(data=> {
            // set response as success;
        })
        .catch(error=> {
            // set response as error;
        });    
}