I do it the following way:
knex_insert_ignore(knex, 'rates', allRates);
// insert into `metric_names` (`a`, `b`, `c`, `d`) values (1, 2, DEFAULT, DEFAULT), (DEFAULT, DEFAULT, 3, 4)
// INSERT IGNORE `metric_names` (`a`, `b`, `c`, `d`) values (1, 2, DEFAULT, DEFAULT), (DEFAULT, DEFAULT, 3, 4)
function knex_insert_ignore(knex, table, rows)
{
if (rows.length == 0) {
return Promise.resolve();
}
const keys = rows_keys(rows);
const inserts = [];
const bindings = [table, ...keys];
for (let i = 0, end = rows.length; i < end; ++i) {
const row = rows[i];
const insert = [];
for (let j = 0, jj = keys.length; j < jj; ++j) {
const key = keys[j];
if (row[key] === undefined) {
insert.push('DEFAULT');
}
else {
insert.push('?');
bindings.push(row[key]);
}
}
inserts.push(`(${insert})`);
}
return knex.raw(`INSERT IGNORE INTO ?? (${keys.slice().fill('??')}) VALUES ${inserts}`, bindings);
}
// Return all keys mentioned in rows
function rows_keys(rows)
{
const unique = {};
for (let i = 0, end = rows.length; i < end; ++i) {
const keys = Object.keys(rows[i]);
for (let j = 0, jj = keys.length; j < jj; ++j) {
unique[keys[j]] = true;
}
}
return Object.keys(unique);
}