首页 > 解决方案 > 如何使用 kenxjs 在 psql 中批量插入?

问题描述

我搜索了很多,这是不推荐使用的问题。

我正在尝试在表中批量插入。

我的方法是这样的

knex('test_table').where({
  user: 'user@example.com',
})
.then(result => {
  knex.transaction(trx => {
    Bluebird.map(result, data => {
      return trx('main_table')
        .insert(data.insert_row)
    }, { concurrency: 3 })
    .then(trx.commit);
  })
  .then(() => {
    console.log("done bulk insert")
  })
  .catch(err => console.error('bulk insert error: ', err))
})

如果文本或数字列的列可以工作,但我有jsonb

所以我得到了这个错误

json 类型的输入语法无效

那么我该如何解决这个问题呢?

标签: node.jspostgresqlknex.js

解决方案


听起来有些 json 列在发送到 DB 时没有字符串化数据。

这也是插入多行最慢的方法,因为您正在为每个插入的行执行 1 次查询并使用单个连接进行插入。

该并发 3 仅导致 pg 驱动程序在通过与所有其他查询相同的事务将它们发送到数据库之前缓冲这两个查询。

像这样的东西应该非常有效(没有测试运行代码,所以可能会有错误):

const rows = await knex('test_table').where({ user: 'user@example.com' });
rows.forEach(row => {
  // make sure that json columns are actually json strings
  row.someColumnWithJson = JSON.stringify(row.someColumnWithJson);
});

await knex.transaction(async trx => {
  let i, j, temparray, chunk = 200;

  // insert rows in 200 row batches
  for (i = 0, j = rows.length; i < j; i += chunk) {
    rowsToInsert = rows.slice(i, i + chunk);
    await trx('main_table').insert(rowsToInsert);
  }
});

knex.batchInsert可能对你有用。


推荐阅读