Skip to main content
Version: v7 - alpha

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:

const { Sequelize, Model, DataTypes } = require('@sequelize/core');
const sequelize = new Sequelize("sqlite::memory:");

const User = sequelize.define("user", {
name: DataTypes.TEXT,
favoriteColor: {
type: DataTypes.TEXT,
defaultValue: 'green'
},
age: DataTypes.INTEGER,
cash: DataTypes.INTEGER
});

(async () => {
await sequelize.sync({ force: true });
// Code here
})();

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:

const jane = User.build({ name: "Jane" });
console.log(jane instanceof User); // true
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:

await jane.save();
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:

const jane = await User.create({ name: "Jane" });
// Jane exists in the database now!
console.log(jane instanceof User); // true
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).

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

Default values

Built instances will automatically get default values:

const jane = User.build({ name: "Jane" });
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:

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

You can update several fields at once with the set method:

const jane = await User.create({ name: "Jane" });

jane.set({
name: "Ada",
favoriteColor: "blue"
});
// As above, the database still has "Jane" and "green"
await jane.save();
// The database now has "Ada" and "blue" for name and favorite color

Note that the save() here will also persist any other changes that have been made on this instance, not just those in the previous set call. If you want to update a specific set of fields, you can use update:

const jane = await User.create({ name: "Jane" });
jane.favoriteColor = "blue"
await jane.update({ name: "Ada" })
// The database now has "Ada" for name, but still has the default "green" for favorite color
await jane.save()
// Now the database has "Ada" for name and "blue" for favorite color

Deleting an instance

You can delete an instance by calling destroy:

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

Reloading an instance

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

const jane = await User.create({ name: "Jane" });
console.log(jane.name); // "Jane"
jane.name = "Ada";
// the name is still "Jane" in the database
await jane.reload();
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:

const jane = await User.create({ name: "Jane" });
console.log(jane.name); // "Jane"
console.log(jane.favoriteColor); // "green"
jane.name = "Jane II";
jane.favoriteColor = "blue";
await jane.save({ fields: ['name'] });
console.log(jane.name); // "Jane II"
console.log(jane.favoriteColor); // "blue"
// The above printed blue because the local object has it set to blue, but
// in the database it is still "green":
await jane.reload();
console.log(jane.name); // "Jane II"
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.

const jane = await User.create({ name: "Jane", age: 100 });
const incrementResult = await jane.increment('age', { by: 2 });
// Note: to increment by 1 you can omit the `by` option and just do `user.increment('age')`

// In PostgreSQL, `incrementResult` will be the updated user, unless the option
// `{ returning: false }` was set (and then it will be undefined).

// 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:

const jane = await User.create({ name: "Jane", age: 100, cash: 5000 });
await jane.increment({
'age': 2,
'cash': 100
});

// If the values are incremented by the same amount, you can use this other syntax as well:
await jane.increment(['age', 'cash'], { by: 2 });

Decrementing works in the exact same way.