Sequelize belongTo association giving error "table name "contact" specified more than once"

Viewed 1117

I am trying to connect the phone model to the contact model through the contact_phone model. When I .findAll like below, the error returns: Unhandled rejection SequelizeDatabaseError: table name "contact" specified more than once. Are the associations/'as' correct in this case? The error happens when I try to include the contact_phone model. I have also inserted the table with an initial phone row.

exports.findAll = (req, res) => {
  models.contact.findAll({
    include: [
      { 
        model: models.contact_phone, 
        as: 'contact'
      } 
    ]
  })
    .then(contacts => {
    res.status(200).send(contacts);
  });
};

Models

module.exports = (sequelize) => {
  const Contact = sequelize.define(
    'contact',
    {
      contact_id: {
        type: Sequelize.BIGINT,  
        primaryKey: true,
        autoIncrement: true,
        field: 'contact_id'
      },
      first_name: {
        type: Sequelize.STRING,
        field: 'first_name'
      },
      last_name: {
        type: Sequelize.STRING,
        field: 'last_name',
      },
      created_at: {
        type: Sequelize.DATE,
        field: 'created_at'
      },
      updated_at: {
        type: Sequelize.DATE,
        field: 'updated_at'   
      }
    },
    {
      tableName: 'contacts',
      freezeTableName: true,
    }
  );

  Contact.associate = (models) => {
    Contact.belongsTo(models.contact_phone, {foreignKey: 'contact_id', as: 'contact'});
    Contact.hasOne(models.phone, {foreignKey: 'phone_id', through: models.contact_phone});
  };

  return Contact;
};

module.exports = (sequelize) => {
  const ContactPhone = sequelize.define(
    'contact_phone',
    {
      contact_id: {
        type: Sequelize.BIGINT,
        references: {
          model: 'contact',
          key: 'contact_id'
        }
      },
      phone_id: {
        type: Sequelize.STRING,
        references: {
          model: 'phone',
          key: 'phone_id'
        }
      }
    }
  );

  ContactPhone.associate = (models) => {
    ContactPhone.belongsTo(models.phone, {foreignKey: 'phone_id', as: 'phone'});
    ContactPhone.belongsTo(models.contact, {foreignKey: 'contact_id', as: 'contact'});
  };

  return ContactPhone;
};

module.exports = (sequelize) => {
  const Phone = sequelize.define(
    'phone',
    {
      phone_id: {
        type: Sequelize.STRING,
        primaryKey: true,
        field: 'phone_id'
      },
      updated_at: {
        type: Sequelize.DATE,
        field: 'updated_at'        
      },
      created_at: {
        type: Sequelize.DATE,
        field: 'created_at'
      }
    },
    {
      tableName: 'phones',
      freezeTableName: true,
    }
  );

  Phone.associate = (models) => {
    Phone.belongsTo(models.contact, {foreignKey: 'phone_id', through: models.contact_phone});
  };

  return Phone;
};
1 Answers

you can do like this . you don't have include extra contact_phone you can directly do with contact & phone with association like this .

contact module :

module.exports = (sequelize) => {
    const Contact = sequelize.define(
        'contact',
        {
            contact_id: {
                type: Sequelize.INT,
                primaryKey: true,
                autoIncrement: true,
                field: 'contact_id'
            },
            first_name: {
                type: Sequelize.STRING,
                field: 'first_name'
            },
            last_name: {
                type: Sequelize.STRING,
                field: 'last_name',
            },
            created_at: {
                type: Sequelize.DATE,
                field: 'created_at'
            },
            updated_at: {
                type: Sequelize.DATE,
                field: 'updated_at'
            }
        },
        {
            tableName: 'contacts',
            freezeTableName: true,
        }
    );

    Contact.associate = (models) => {
        Contact.hasOne(models.phone, { // has many or hasOne relationship .here read like contact has one phone 
            foreignKey: 'phone_id',
            onDelete: "CASCADE"
        });
    };

    return Contact;
};

phone module :

module.exports = (sequelize) => {
    const Phone = sequelize.define(
        'phone',
        {
            phone_id: {
                type: Sequelize.INT,
                primaryKey: true,
                autoIncrement: true,
                field: 'phone_id'
            },
            contact_id: {
                type: Sequelize.INT,
            },
            updated_at: {
                type: Sequelize.DATE,
                field: 'updated_at'
            },
            created_at: {
                type: Sequelize.DATE,
                field: 'created_at'
            }
        },
        {
            tableName: 'phones',
            freezeTableName: true,
        }
    );

    Phone.associate = (models) => {
        Phone.belongsTo(models.contact, {
            foreignKey: 'contact_id',
            as: 'contact',
            onDelete: "CASCADE"
        });
    };
}

your query be like :

models.contact.findAll({
    include: [
        {
            model: models.phone,
            as: 'contact'
        }
    ]
}).then(contacts => {
    res.status(200).send(contacts);
});

EDIT :

how can you define more association with same key and different alias

Phone.associate = (models) => {
    Phone.belongsTo(models.contact, {
        foreignKey: 'contact_id',
        as: 'contact',
        onDelete: "CASCADE"
    });
    Phone.belongsTo(models.contact, {
        foreignKey: 'contact_id',
        as: 'phone',
        onDelete: "CASCADE"
    });
};
Related