Sequelize is a promise-based ORM for Node. More info: http://docs.sequelizejs.com/

How to define Sequelize associations using migrations

Andre Woons
Nov 23, 2017 · 4 min read

The Sequelize CLI is pretty great at generating model and migration files, but not at adding associations with other models.

Unfortunately there is not much (clear) documentation about adding associations in migration files — so whilst figuring this out myself I decided to write down to basic examples for the 4 types of associations to save others the time.

Creating models

Example order of files:

  • create-tags.js
  • create-products.js
  • create-orders.js
  • create-customers.js
  • create-payments.js
  • add-associations.js

Create all the models and their migrations usingsequelize model:generate.

To check if the models are created correctly I suggest running sequelize db:migrate and seeing if there any errors.

Note: if you get an error saying the ‘Dialect needs to be explicitly supplied as of v4.0.0’, export the NODE_ENV of your configuration first, e.g. export NODE_ENV="local"

If there are no errors, we can move on to the next step.

Adding associations

First, let’s create the migration file where we will be doing all the associations: sequelize migration:generate --name add-associations.

belongsTo

In our example an Order belongs to a Customer. In this case, the source is Order so we will need to add a CustomerId key to the Order table.

Order model file

Note: I’m using UUID’s for my ids. If you use the standard integers change the type to DataTypes.INTEGER, remove the defaultValue line and change autoIncrement to true.

In our migration file we will need to add a column called CustomerId. This can be done using the queryInterface.addColumn method. We also need to provide a down function that will return the database to the state before the migration.

First version of the add-assocations.js file

A couple of things to notice here:

  • Table names are plural and the reference key is exactly like the key used when defining the models (most of the time it will beid ).
  • The foreign key is capitalized.
  • We’re also defining onUpdate and onDelete. The default is CASCADE for update and SET NULL for delete for belongsTo, hasOne and hasMany. BelongsToMany associations will have CASCADE as default for both update and delete.

Note: if you’re using integers instead of UUID’s use type: Sequelize.INTEGER.

Save and run sequelize db:migrate. If all is well, let’s run sequelize db:migrate:undo to check if the undo function works too.

hasOne

In our example Payment has oneOrder. Order is the target so we will need to add a PaymentId key to the Order model.

Model definition of payment.js

Let’s add our migration of the hasOne key. We’re appending that migration to add-associations.js so the complete file will look like this:

add-associations.js with hasOne up and down

Notice that we are chaining the queryInterface methods because they return Promises.

Let’s run sequelize db:migrate again. If there are no errors run sequelize db:migrate:undo to check if our down function also works.

hasMany

In our example an Order has many Product s. Let’s update our order.js model file.

We just added line 16 where we define the hasMany relation.

Now we need to add the OrderId column to the Products table in the migration file:

Pretty straight-forward :)

belongsToMany

In our example a Product belongs to many Tag s and vice versa. Here are the model definitions:

Notice the following:

  • we are defining through: 'ProductTags'. This defines that we are storing the n:m association in the ProductTags table.
  • we are defining the belongsToMany association in both models using the same through.

To keep things more concise I’ll create a new migration file for this association by runningsequelize migration:generate --name associate-product-tag .

Instead of queryInterface.addColumn we now need to use queryInterface.createTable.

This table doesn’t need an id key. Please note that ProductId and TagId are both primary keys. For the down function we’re just dropping the table again.

Run sequelize db:migrate again and see if it works. Don’t forget to test the down function by running sequelize db:migrate:undo.

Done

Andre Woons

Written by

Founder & CTO of Nivoda - the B2B marketplace for the jewellery industry.⚡️