How to convert association join table to a model definition in Sequelize

You can't simply re-define an association table as a model and use it. This guide shows how to do it with a workaround.

Bahadir Balban

Buzz Founder,@buzzdevelopers


When you define an association, Sequelize automatically generates a join table for you. As an example:

  Post.associate = function(models) {
    Post.belongsTo(models.User, { as: "Author" });
    Post.belongsTo(models.Company);
    Post.belongsToMany(models.Topic, { through: "PostTopic" });
    Post.belongsToMany(models.User, { through: "PostAction" });
    Post.hasMany(models.Comment);
    Post.hasMany(models.Image);
  }

Here, Sequelize would generate “PostTopic” table. The table would be generated, but you would have limitations:

  • Sequelize doesn’t define any methods for this table. For example, if you tried to do:

    models.PostTopic.count()

    It won’t work, because Sequelize did not define the count method, because the PostTopic table was not explicitly defined.

  • If you need to add additional fields to the join table, you need to define a new model.

However, if you simply defined a “PostTopic” model, it doesn’t work, even though I think it should have.

There will be two differences from before:

  1. Sequelize will create a new table called “PostTopics” (plural), instead of “PostTopic”.

  2. It will also add a new “Id” field to this table, that does not exist in the original autogenerated join table.

This will confuse your database with 2 tables, namely “PostTopic” original, and “PostTopics”, and you will probably need to use a migration from the original join table to the new one or something. I haven’t tried this.

In order to remedy that I used the following work around.

'use strict';
module.exports = (sequelize, DataTypes) => {
  const PostTopic = sequelize.define('PostTopic', {

  }, {
  freezeTableName: true,
  tableName: 'PostTopic'
  });
  return PostTopic;
};

This defines the table as normal, but forces the singular name. By doing this, Sequelize finds that this table already exists, but also autogenerates the database methods that I needed. Tested to work. For the record we’re using PostgreSQL 10.x with Sequelize.








Join The Discussion