2019-11-06 01:47:10 +00:00
|
|
|
'use strict';
|
|
|
|
|
2019-12-31 02:12:52 +00:00
|
|
|
const knex = require('../knex');
|
2020-02-08 01:49:39 +00:00
|
|
|
const logger = require('../logger')(__filename);
|
2019-12-31 02:12:52 +00:00
|
|
|
|
|
|
|
async function upsert(table, items, identifier = ['id'], _knex) {
|
2020-05-14 02:26:05 +00:00
|
|
|
const identifiers = Array.isArray(identifier) ? identifier : [identifier];
|
|
|
|
|
2021-11-20 22:59:15 +00:00
|
|
|
const duplicates = await knex(table).whereIn(identifiers, items.map((item) => identifiers.map((identifierX) => item[identifierX])));
|
2020-05-14 02:26:05 +00:00
|
|
|
const duplicatesByIdentifiers = duplicates.reduce((acc, duplicate) => {
|
2021-11-20 22:59:15 +00:00
|
|
|
const duplicateIdentifier = identifiers.map((identifierX) => duplicate[identifierX]).toString();
|
2020-05-14 02:26:05 +00:00
|
|
|
|
|
|
|
return { ...acc, [duplicateIdentifier]: duplicate };
|
|
|
|
}, {});
|
|
|
|
|
|
|
|
const { insert, update } = items.reduce((acc, item) => {
|
2021-11-20 22:59:15 +00:00
|
|
|
const itemIdentifier = identifiers.map((identifierX) => item[identifierX]).toString();
|
2020-05-14 02:26:05 +00:00
|
|
|
|
|
|
|
if (duplicatesByIdentifiers[itemIdentifier]) {
|
|
|
|
acc.update.push(item);
|
|
|
|
return acc;
|
|
|
|
}
|
|
|
|
|
|
|
|
acc.insert.push(item);
|
|
|
|
return acc;
|
|
|
|
}, {
|
|
|
|
insert: [],
|
|
|
|
update: [],
|
|
|
|
});
|
|
|
|
|
|
|
|
if (knex) {
|
|
|
|
logger.debug(`${table}: Inserting ${insert.length}`);
|
|
|
|
logger.debug(`${table}: Updating ${update.length}`);
|
|
|
|
|
|
|
|
const [inserted, updated] = await Promise.all([
|
2021-11-20 23:19:10 +00:00
|
|
|
insert.length > 0 ? knex(table).returning('*').insert(insert) : [],
|
|
|
|
update.length > 0 ? knex.transaction(async (trx) => Promise.all(update.map((item) => {
|
2020-05-14 02:26:05 +00:00
|
|
|
const clause = identifiers.reduce((acc, identifierX) => ({ ...acc, [identifierX]: item[identifierX] }), {});
|
|
|
|
|
|
|
|
return trx
|
|
|
|
.where(clause)
|
|
|
|
.update(item)
|
|
|
|
.into(table)
|
|
|
|
.returning('*');
|
2021-11-20 23:19:10 +00:00
|
|
|
}))) : [],
|
2020-05-14 02:26:05 +00:00
|
|
|
]);
|
|
|
|
|
|
|
|
return {
|
|
|
|
inserted: Array.isArray(inserted) ? inserted : [],
|
|
|
|
updated: updated.reduce((acc, updatedItems) => acc.concat(updatedItems), []),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
return { insert, update };
|
2019-11-06 01:47:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = upsert;
|