Advanced associations using Sequelize

Aditya Naik
Nomads Of Code
Published in
4 min readJul 3, 2020

Setting up ‘Many-to-many-through’ association between models using junction/through table.

Photo by Timo Volz on Unsplash

This is Part 6 of multi-part series on ExpressJS.

You can find Part 1 here. It talks about building a basic express api and setting up mocha for testing.

You can find Part 2 here. It talks about setting up PostgreSQL, sequelize for connecting express api with databases.

You can find Part 3 here. It talks about setting up associations (has many as well as belongs to) between two models.

You can find Part 4 here. It talks about setting up user authentication based on email and password.

You can find Part 5 here. It talks about using json web token to protect a route.

In this part of the series, we will take User and Post models, which are already associated via ‘Author’ , and add another association which will be ‘Saved’.

One user can have many saved posts, and one post can be saved by many users.

We will then set up appropriate routes to test expected response.

  • A specific post should tell us who is the author, but also who have saved this post.This will not be a protected route.
  • A specific user should have authored posts as well as saved posts. This will be a protected route.

Let’s handle the tests first —

Update factories

So we set it up two ways

  • post.addSavedBy(reader) and
  • reader.addSaved(post)

This is just to showcase the functions offered by sequelize on our models.

Add specific post test —

The whole test now looks like this —

Update our JWT test —

So we check for both Written posts and Saved posts associated with our author.

So our tests are all set up, time for coding.

Add a through table via migration

We will create a new table in our database, that only stores association information about which user saved which post.

Each row in our through table represents a save action — One user has saved one post.

So, if we have to look up all saved posts for a user, or for a post who have saved it — We will (or rather sequelize will) make use of this table.

This is called as a ‘Junction or Through Table’.

We need to create a migration to add the table to our database.

migration:generate and migration:create are both aliases which achieve the same goal — to create a migration file.

Update the migration file —

So we name this through table as SavedPosts .

Time to use it for associating our User and Post models.

Add association in models

Add to User model —

User.belongsToMany(models.Post, { through: ‘SavedPosts’, as: ‘Saved’ })

Add to Post model —

Post.belongsToMany(models.User, { through: ‘SavedPosts’, as: ‘savedBy’ })

Here, we alias the association as Saved and SavedBy depending on the model. It makes more semantic sense to say

  • A User Saved a post

and

  • A Post was Saved By a user.

Run the migration —

sequelize db:migrate as you know well by now.

We have now successfully constructed our through table, added the association for both models, and updated database tables accordingly.

Time to connect to our request/response flow using routes and controllers.

Add a route —

We go to routes/posts.js and add a route for specifc post.

router.get(‘/:id’, postsController.getSpecificPost)

This route handlet the request for following URL — https:<host>/posts/id for ex. https://articleWebsite.com/posts/7 . 7 here is the id of the post and handled as a parameter OR param in our API.

Add a method to controller —

Add getSpecificPost method to our posts controller —

getSpecificPost method will search for a post with matching id and return it as response.

Update User controller —

We will also update user controller to attach saved posts whenever we request for a user.

So we have set up the routes, and connected controller actions to handle requests received on those routes. We have also set up associations between models and have ran the migrations to reflect the new relationship in our database table.

The tests should go green now and they do indeed.

In next part of the series, we will talk about refactoring our API by extracting out database query methods in separate files and making the API RESTful.

We will also add unit tests for our models and controllers.

Craft Academy is a Tech Education Provider that aims to bring new talent to the market and help to solve the shortage of tech workers. We are founded on the belief that modern development standards, agile methodologies, and business skills are fundamental for IT professionals.

Our primary service is a 12-week coding bootcamp designed to provide individuals with a foundation of skills that allows them to enter the industry as junior developers.

With that foundation, our learners find employment in various industries or start their own businesses that bring new innovations to the market.

Would you like to know more about what we do? Follow us here on Medium, Facebook, Twitter or visit our website.

--

--