Working in bulk (creating, updating and destroying multiple rows at once)

In addition to updating a single instance, you can also create, update, and delete multiple instances at once. The functions you are looking for are called

  • Model.bulkCreate
  • Model.update
  • Model.destroy

Since you are working with multiple models, the callbacks will not return DAO instances. BulkCreate will return an array of model instances/DAOs, they will however, unlike create, not have the resulting values of autoIncrement attributes.update and destroy will return the number of affected rows.

First lets look at bulkCreate

  1. User.bulkCreate([
  2. { username: 'barfooz', isAdmin: true },
  3. { username: 'foo', isAdmin: true },
  4. { username: 'bar', isAdmin: false }
  5. ]).then(() => { // Notice: There are no arguments here, as of right now you'll have to...
  6. return User.findAll();
  7. }).then(users => {
  8. console.log(users) // ... in order to get the array of user objects
  9. })

Insert several rows and return all columns (Postgres only):

  1. User.bulkCreate([
  2. { username: 'barfooz', isAdmin: true },
  3. { username: 'foo', isAdmin: true },
  4. { username: 'bar', isAdmin: false }
  5. ], { returning: true }) // will return all columns for each row inserted
  6. .then((result) => {
  7. console.log(result);
  8. });

Insert several rows and return specific columns (Postgres only):

  1. User.bulkCreate([
  2. { username: 'barfooz', isAdmin: true },
  3. { username: 'foo', isAdmin: true },
  4. { username: 'bar', isAdmin: false }
  5. ], { returning: ['username'] }) // will return only the specified columns for each row inserted
  6. .then((result) => {
  7. console.log(result);
  8. });

To update several rows at once:

  1. Task.bulkCreate([
  2. {subject: 'programming', status: 'executing'},
  3. {subject: 'reading', status: 'executing'},
  4. {subject: 'programming', status: 'finished'}
  5. ]).then(() => {
  6. return Task.update(
  7. { status: 'inactive' }, /* set attributes' value */
  8. { where: { subject: 'programming' }} /* where criteria */
  9. );
  10. }).then(([affectedCount, affectedRows]) => {
  11. // Notice that affectedRows will only be defined in dialects which support returning: true
  12. // affectedCount will be 2
  13. return Task.findAll();
  14. }).then(tasks => {
  15. console.log(tasks) // the 'programming' tasks will both have a status of 'inactive'
  16. })

And delete them:

  1. Task.bulkCreate([
  2. {subject: 'programming', status: 'executing'},
  3. {subject: 'reading', status: 'executing'},
  4. {subject: 'programming', status: 'finished'}
  5. ]).then(() => {
  6. return Task.destroy({
  7. where: {
  8. subject: 'programming'
  9. },
  10. truncate: true /* this will ignore where and truncate the table instead */
  11. });
  12. }).then(affectedRows => {
  13. // affectedRows will be 2
  14. return Task.findAll();
  15. }).then(tasks => {
  16. console.log(tasks) // no programming, just reading :(
  17. })

If you are accepting values directly from the user, it might be beneficial to limit the columns that you want to actually insert.bulkCreate()accepts an options object as the second parameter. The object can have a fields parameter, (an array) to let it know which fields you want to build explicitly

  1. User.bulkCreate([
  2. { username: 'foo' },
  3. { username: 'bar', admin: true}
  4. ], { fields: ['username'] }).then(() => {
  5. // nope bar, you can't be admin!
  6. })

bulkCreate was originally made to be a mainstream/fast way of inserting records, however, sometimes you want the luxury of being able to insert multiple rows at once without sacrificing model validations even when you explicitly tell Sequelize which columns to sift through. You can do by adding a validate: true property to the options object.

  1. class Tasks extends Model {}
  2. Tasks.init({
  3. name: {
  4. type: Sequelize.STRING,
  5. validate: {
  6. notNull: { args: true, msg: 'name cannot be null' }
  7. }
  8. },
  9. code: {
  10. type: Sequelize.STRING,
  11. validate: {
  12. len: [3, 10]
  13. }
  14. }
  15. }, { sequelize, modelName: 'tasks' })
  16. Tasks.bulkCreate([
  17. {name: 'foo', code: '123'},
  18. {code: '1234'},
  19. {name: 'bar', code: '1'}
  20. ], { validate: true }).catch(errors => {
  21. /* console.log(errors) would look like:
  22. [
  23. { record:
  24. ...
  25. name: 'SequelizeBulkRecordError',
  26. message: 'Validation error',
  27. errors:
  28. { name: 'SequelizeValidationError',
  29. message: 'Validation error',
  30. errors: [Object] } },
  31. { record:
  32. ...
  33. name: 'SequelizeBulkRecordError',
  34. message: 'Validation error',
  35. errors:
  36. { name: 'SequelizeValidationError',
  37. message: 'Validation error',
  38. errors: [Object] } }
  39. ]
  40. */
  41. })