# Sequelize Associations

1. **<mark>Introduction</mark>**  
    In Sequelize, **associations** define relationships between models in a relational database (like PostgreSQL, MySQL, etc.). Sequelize supports several types of associations, which allow you to model relationships between tables. Here are the main types of associations,
    
    1) One-to-One (1:1)  
    2) One-to-Many (1)  
    3) Many-to-Many (N)
    
2. **<mark>One-to-One (1:1)</mark>**
    
    This represents a relationship where a record in one table is related to exactly one record in another table.
    
    `hasOne`: A model can have one related model. This creates a one-to-one relationship where the foreign key is on the target model.
    
    ```javascript
    const User = sequelize.define('User' /* ... */);
    const Profile = sequelize.define('Profile' /* ... */);
    User.hasOne(Profile);
    Profile.belongsTo(User);  // Optional, to define the inverse relationship
    ```
    
3. **<mark>One-to-Many (1)</mark>**
    
    This is a relationship where a record in one table can be associated with many records in another table.
    
    `hasMany`: A model can have multiple related models. This places a foreign key on the target model.
    
    ```javascript
    const User = sequelize.define('User' /* ... */);
    const Post = sequelize.define('Post' /* ... */);
    User.hasMany(Post);
    Post.belongsTo(User);  // Optional, for the inverse relationship
    ```
    
4. **<mark>Many-to-Many (N)</mark>**
    
    This represents a relationship where records in both tables can be associated with multiple records in the other table. This is typically done with a **junction table** that holds the foreign keys for both tables.
    
    `belongsToMany`: Both models can be associated with multiple records of the other. Sequelize automatically creates a join table to manage the relationship.
    
    ```javascript
    const User = sequelize.define('User' /* ... */);
    const Role = sequelize.define('Role' /* ... */);
    User.belongsToMany(Role, { through: 'UserRole' });
    Role.belongsToMany(User, { through: 'UserRole' });
    ```
    
5. **<mark>Summary of Association Methods</mark>**
    
    `hasOne`: One-to-One, foreign key on the target model.
    
    `hasMany`: One-to-Many, foreign key on the target model.
    
    `belongsTo`: Inverse relationship where a model belongs to another model (used for foreign keys on the source model).
    
    `belongsToMany`: Many-to-Many relationship with a join table.
    
6. **<mark>Foreign Keys</mark>**
    
    In Sequelize, when associations are defined, Sequelize automatically generates foreign keys in the target models. You can customize the foreign key and other options as needed
    
    ```javascript
    const User = sequelize.define('User' /* ... */);
    const Profile = sequelize.define('Profile' /* ... */);
    User.hasOne(Profile, { foreignKey: 'userId' });
    Profile.belongsTo(User, { foreignKey: 'userId' });
    ```
    
7. **<mark>Eager Loading and Lazy Loading</mark>**
    
    **Eager Loading** - Sequelize allows you to load associated models at the same time using the `include` option in queries.
    
    ```javascript
    User.findAll({
      include: [Profile]  // Eager load the Profile with User
    });
    ```
    
    **Lazy Loading**: Associations can also be loaded lazily by calling the association methods generated by Sequelize,
    
    ```javascript
    const user = await User.findByPk(1);
    const profile = await user.getProfile();  // Lazy load the Profile
    ```
