Update multiple rows , is using a bulk update a good solution or something like the code below works ? . I supposed wanted to update all the records with the id and filename.
I did try to update inside a loop but the migration hang up and take too long in this block. is it because of the iterations ? or is there something wrong with the update syntax?. Thank you.
#Code
for (let i = 0; i < documents.length; i++) { const prefix = Date.now().toString(); const fileParts = documents[i].filename.split('.'); const finalname = `${fileParts[0]}-${prefix}.${fileParts[1]}`; // eslint-disable-next-line no-await-in-loop await queryInterface.sequelize.query(`UPDATE ${EmployeeDocumentsModel.tableName} SET filename='${finalname}' WHERE id=${documents[i].id};`, { transaction }); }
#CODE
module.exports = { up: async (queryInterface) => { const transaction = await queryInterface.sequelize.transaction(); try { const sequelizeClient = app.get('sequelizeClient'); const documents = await sequelizeClient.query( `SELECT id, filename, COUNT(filename) FROM ${EmployeeDocumentsModel.tableName} GROUP BY filename HAVING COUNT(filename) > 1;`, { type: QueryTypes.SELECT }, ); // eslint-disable-next-line no-plusplus for (let i = 0; i < documents.length; i++) { const prefix = Date.now().toString(); const fileParts = documents[i].filename.split('.'); const finalname = `${fileParts[0]}-${prefix}.${fileParts[1]}`; // eslint-disable-next-line no-await-in-loop await queryInterface.sequelize.query(`UPDATE ${EmployeeDocumentsModel.tableName} SET filename='${finalname}' WHERE id=${documents[i].id};`, { transaction }); } // eslint-disable-next-line no-unused-vars // const file = await sequelizeClient.query( // `DELETE d1 from ${EmployeeDocumentsModel.tableName} d1 inner join ${EmployeeDocumentsModel.tableName} d2 on d2.id < d1.id and d2.filename = d1.filename and d2.employeeId = d1.employeeId`, // { type: QueryTypes.DELETE }, // ); await queryInterface.addConstraint(EmployeeDocumentsModel.tableName, ['employeeId', 'filename'], { type: 'unique', name: 'composite_employee_filename', }, { transaction, }); await transaction.commit(); } catch (err) { // eslint-disable-next-line no-console console.log(err); await transaction.rollback(); throw err; } return true; },
Advertisement
Answer
I think the biggest issue is that each update is waiting on the previous to complete:
for (let i = 0; i < documents.length; i++) { // ... await queryInterface.sequelize.query(`UPDATE ${EmployeeDocumentsModel.tableName} SET filename='${finalname}' WHERE id=${documents[i].id};`, { transaction }); }
If you change it to:
const promises = []; for (let i = 0; i < documents.length; i++) { // ... promises.push(queryInterface.sequelize.query(`UPDATE ${EmployeeDocumentsModel.tableName} SET filename='${finalname}' WHERE id=${documents[i].id};`, { transaction })); } await Promise.all(promises);
you should see a big speedup.