Skip to content

Sequelize

StarterStack uses the Sequelize database ORM as an abstraction layer between the application and database. It allows for a separation of concerns in that the application code does not need to know about the underlying database engine being MySQL, Postgres, etc. You don't need to write SQL in your application...unless you want to and Sequelize can handle that too. Additionally, as we'ved talked about in previous docs, it offers migrations and seeds. All things to help you speed up development and ship faster!

Model Classes

For every database table in your schema, you should generate a corresponding Sequelize model class. This is basically a nodejs based class to interact with your table offering many many convenient methods to find, update, create, etc. You can find a full list of the methods available in the Sequelize docs.

Generating a Model Class

Model classes are created along with their associated migration file. See Add a Table.

The generated model class contains a javascript access model around the underlying table. For example, here is the StartStack Users model found in /backend/models/users.js

js
'use strict';
const {
  Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
  class Users extends Model {
    /**
     * Helper method for defining associations.
     * This method is not a part of Sequelize lifecycle.
     * The `models/index` file will call this method automatically.
     */
    static associate(models) {
      // define association here
      
    }
  }
  Users.init({
    first_name: DataTypes.STRING,
    last_name: DataTypes.STRING,
    email: {
        type: DataTypes.STRING,
        validate: {
          isEmail: {
            msg: 'invalid email format'
          },
          notEmpty: {
            msg: 'email is required'
          },
        }
    },
    password: DataTypes.STRING,
    password_reset_hash: DataTypes.STRING,
    stripe_customer_id: {
        type: DataTypes.STRING,
        allowNull: true
    },
    deletedAt: DataTypes.DATE,
  }, {
    sequelize,
    modelName: 'Users',
    paranoid: true
  });
  return Users;
};

TIP

As you add/remove fields from your migration file (your table), you'll need to adjust the model too. If you add a field in the migration but not model you will not see the field coming back in your queries.

Using a Model Class in Your Application

You will most commonly use models in your route middleware. You will first have to import the model class:

js
const { Users } = require('../models');

Then execute your database operation. This example fetches a user by id and exludes the password field:

js
const id = 1
const user = await Users.findByPk(id, {
    attributes: {
        exclude: ['password']
    } 
})

Results:

json
{
    "id": 1,
    "first_name": "Kaci",
    "last_name": "Lesch-Ankunding",
    "email": "[email protected]",
    "password_reset_hash": null,
    "stripe_customer_id": null,
    "deletedAt": null,
    "createdAt": "2024-09-04T21:18:48.000Z",
    "updatedAt": "2024-09-04T21:18:48.000Z"
}