Model Instances

As you already know, a model is an ES6 class. An instance of the class represents one object from that model (which maps to one row of the table in the database). This way, model instances are DAOs.

For this guide, the following setup will be assumed:

  1. const { Sequelize, Model, DataTypes } = require("sequelize");
  2. const sequelize = new Sequelize("sqlite::memory:");
  3. const User = sequelize.define("user", {
  4. name: DataTypes.TEXT,
  5. favoriteColor: {
  6. type: DataTypes.TEXT,
  7. defaultValue: 'green'
  8. },
  9. age: DataTypes.INTEGER,
  10. cash: DataTypes.INTEGER
  11. });
  12. (async () => {
  13. await sequelize.sync({ force: true });
  14. // Code here
  15. })();

Creating an instance

Although a model is a class, you should not create instances by using the new operator directly. Instead, the build method should be used:

  1. const jane = User.build({ name: "Jane" });
  2. console.log(jane instanceof User); // true
  3. console.log(jane.name); // "Jane"

However, the code above does not communicate with the database at all (note that it is not even asynchronous)! This is because the build method only creates an object that represents data that can be mapped to a database. In order to really save (i.e. persist) this instance in the database, the save method should be used:

  1. await jane.save();
  2. console.log('Jane was saved to the database!');

Note, from the usage of await in the snippet above, that save is an asynchronous method. In fact, almost every Sequelize method is asynchronous; build is one of the very few exceptions.

A very useful shortcut: the create method

Sequelize provides the create method, which combines the build and save methods shown above into a single method:

  1. const jane = await User.create({ name: "Jane" });
  2. // Jane exists in the database now!
  3. console.log(jane instanceof User); // true
  4. console.log(jane.name); // "Jane"

Note: logging instances

Trying to log a model instance directly to console.log will produce a lot of clutter, since Sequelize instances have a lot of things attached to them. Instead, you can use the .toJSON() method (which, by the way, automatically guarantees the instances to be JSON.stringify-ed well).

  1. const jane = await User.create({ name: "Jane" });
  2. // console.log(jane); // Don't do this
  3. console.log(jane.toJSON()); // This is good!
  4. console.log(JSON.stringify(jane, null, 4)); // This is also good!

Default values

Built instances will automatically get default values:

  1. const jane = User.build({ name: "Jane" });
  2. console.log(jane.favoriteColor); // "green"

Updating an instance

If you change the value of some field of an instance, calling save again will update it accordingly:

  1. const jane = await User.create({ name: "Jane" });
  2. console.log(jane.name); // "Jane"
  3. jane.name = "Ada";
  4. // the name is still "Jane" in the database
  5. await jane.save();
  6. // Now the name was updated to "Ada" in the database!

Deleting an instance

You can delete an instance by calling destroy:

  1. const jane = await User.create({ name: "Jane" });
  2. console.log(jane.name); // "Jane"
  3. await jane.destroy();
  4. // Now this entry was removed from the database

Reloading an instance

You can reload an instance from the database by calling reload:

  1. const jane = await User.create({ name: "Jane" });
  2. console.log(jane.name); // "Jane"
  3. jane.name = "Ada";
  4. // the name is still "Jane" in the database
  5. await jane.reload();
  6. console.log(jane.name); // "Jane"

The reload call generates a SELECT query to get the up-to-date data from the database.

Saving only some fields

It is possible to define which attributes should be saved when calling save, by passing an array of column names.

This is useful when you set attributes based on a previously defined object, for example, when you get the values of an object via a form of a web app. Furthermore, this is used internally in the update implementation. This is how it looks like:

  1. const jane = await User.create({ name: "Jane" });
  2. console.log(jane.name); // "Jane"
  3. console.log(jane.favoriteColor); // "green"
  4. jane.name = "Jane II";
  5. jane.favoriteColor = "blue";
  6. await jane.save({ fields: ['name'] });
  7. console.log(jane.name); // "Jane II"
  8. console.log(jane.favoriteColor); // "blue"
  9. // The above printed blue because the local object has it set to blue, but
  10. // in the database it is still "green":
  11. await jane.reload();
  12. console.log(jane.name); // "Jane II"
  13. console.log(jane.favoriteColor); // "green"

Change-awareness of save

The save method is optimized internally to only update fields that really changed. This means that if you don’t change anything and call save, Sequelize will know that the save is superfluous and do nothing, i.e., no query will be generated (it will still return a Promise, but it will resolve immediately).

Also, if only a few attributes have changed when you call save, only those fields will be sent in the UPDATE query, to improve performance.

Incrementing and decrementing integer values

In order to increment/decrement values of an instance without running into concurrency issues, Sequelize provides the increment and decrement instance methods.

  1. const jane = await User.create({ name: "Jane", age: 100 });
  2. const incrementResult = await jane.increment('age', { by: 2 });
  3. // Note: to increment by 1 you can omit the `by` option and just do `user.increment('age')`
  4. // In PostgreSQL, `incrementResult` will be the updated user, unless the option
  5. // `{ returning: false }` was set (and then it will be undefined).
  6. // In other dialects, `incrementResult` will be undefined. If you need the updated instance, you will have to call `user.reload()`.

You can also increment multiple fields at once:

  1. const jane = await User.create({ name: "Jane", age: 100, cash: 5000 });
  2. await jane.increment({
  3. 'age': 2,
  4. 'cash': 100
  5. });
  6. // If the values are incremented by the same amount, you can use this other syntax as well:
  7. await jane.increment(['age', 'cash'], { by: 2 });

Decrementing works in the exact same way.