2019-11-06 01:47:10 +00:00
|
|
|
'use strict';
|
|
|
|
|
2019-12-19 01:35:07 +00:00
|
|
|
async function upsert(table, items, identifier = 'id', knex) {
|
|
|
|
const duplicates = await knex(table).whereIn(identifier, items.map(item => item[identifier]));
|
|
|
|
const duplicatesByIdentifier = duplicates.reduce((acc, item) => ({ ...acc, [item[identifier]]: item }), {});
|
|
|
|
|
2019-11-06 01:47:10 +00:00
|
|
|
const { insert, update } = items.reduce((acc, item) => {
|
2019-12-19 01:35:07 +00:00
|
|
|
if (duplicatesByIdentifier[item[identifier]]) {
|
|
|
|
acc.update.push(item);
|
|
|
|
return acc;
|
2019-11-06 01:47:10 +00:00
|
|
|
}
|
|
|
|
|
2019-12-19 01:35:07 +00:00
|
|
|
acc.insert.push(item);
|
|
|
|
return acc;
|
|
|
|
}, {
|
2019-11-06 01:47:10 +00:00
|
|
|
insert: [],
|
|
|
|
update: [],
|
|
|
|
});
|
|
|
|
|
|
|
|
if (knex) {
|
|
|
|
console.log(`${table}: Inserting ${insert.length}`);
|
|
|
|
console.log(`${table}: Updating ${update.length}`);
|
|
|
|
|
2019-12-19 01:35:07 +00:00
|
|
|
const [inserted, updated] = await Promise.all([
|
|
|
|
knex(table).returning('*').insert(insert),
|
2019-11-06 01:47:10 +00:00
|
|
|
knex.transaction(async trx => Promise.all(update.map(item => trx
|
2019-11-27 03:58:38 +00:00
|
|
|
.where({ [identifier]: item[identifier] })
|
2019-11-06 01:47:10 +00:00
|
|
|
.update(item)
|
2019-12-19 01:35:07 +00:00
|
|
|
.into(table)
|
|
|
|
.returning('*')))),
|
2019-11-06 01:47:10 +00:00
|
|
|
]);
|
2019-12-19 01:35:07 +00:00
|
|
|
|
|
|
|
return {
|
|
|
|
inserted: Array.isArray(inserted) ? inserted : [],
|
|
|
|
updated: updated.reduce((acc, updatedItems) => acc.concat(updatedItems), []),
|
|
|
|
};
|
2019-11-06 01:47:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return { insert, update };
|
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = upsert;
|