User model (the model that the function is being invoked on) is the source. Project model (the model being passed as an argument) is the target.

    Foreign Keys

    When you create associations between your models in sequelize, foreign key references with constraints will automatically be created. The setup below:

    1. class Task extends Model {}
    2. Task.init({ title: Sequelize.STRING }, { sequelize, modelName: 'task' });
    3. class User extends Model {}
    4. User.init({ username: Sequelize.STRING }, { sequelize, modelName: 'user' });
    5. User.hasMany(Task); // Will add userId to Task model
    6. Task.belongsTo(User); // Will also add userId to Task model

    Will generate the following SQL:

    1. CREATE TABLE IF NOT EXISTS "users" (
    2. "id" SERIAL,
    3. "username" VARCHAR(255),
    4. "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL,
    5. "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL,
    6. PRIMARY KEY ("id")
    7. );
    8. CREATE TABLE IF NOT EXISTS "tasks" (
    9. "id" SERIAL,
    10. "title" VARCHAR(255),
    11. "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL,
    12. "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL,
    13. "userId" INTEGER REFERENCES "users" ("id") ON DELETE
    14. SET
    15. NULL ON UPDATE CASCADE,
    16. PRIMARY KEY ("id")
    17. );

    The relation between tasks and users model injects the userId foreign key on tasks table, and marks it as a reference to the users table. By default userId will be set to NULL if the referenced user is deleted, and updated if the id of the userId updated. These options can be overridden by passing onUpdate and onDelete options to the association calls. The validation options are RESTRICT, CASCADE, NO ACTION, SET DEFAULT, SET NULL.

    underscored option

    Sequelize allow setting underscored option for Model. When true this option will set thefield option on all attributes to the underscored version of its name. This also applies toforeign keys generated by associations.

    Let's modify last example to use underscored option.

    Will generate the following SQL:

    1. CREATE TABLE IF NOT EXISTS "users" (
    2. "id" SERIAL,
    3. "username" VARCHAR(255),
    4. "created_at" TIMESTAMP WITH TIME ZONE NOT NULL,
    5. "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL,
    6. PRIMARY KEY ("id")
    7. );
    8. "id" SERIAL,
    9. "created_at" TIMESTAMP WITH TIME ZONE NOT NULL,
    10. "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL,
    11. "user_id" INTEGER REFERENCES "users" ("id") ON DELETE
    12. SET
    13. NULL ON UPDATE CASCADE,
    14. PRIMARY KEY ("id")
    15. );

    With the underscored option attributes injected to model are still camel cased but field option is set to their underscored version.

    Cyclic dependencies & Disabling constraints

    1. class Document extends Model {}
    2. Document.init({
    3. author: Sequelize.STRING
    4. }, { sequelize, modelName: 'document' });
    5. class Version extends Model {}
    6. Version.init({
    7. timestamp: Sequelize.DATE
    8. }, { sequelize, modelName: 'version' });
    9. Document.hasMany(Version); // This adds documentId attribute to version
    10. Document.belongsTo(Version, {
    11. as: 'Current',
    12. foreignKey: 'currentVersionId'
    13. }); // This adds currentVersionId attribute to document

    However, the code above will result in the following error: Cyclic dependency found. documents is dependent of itself. Dependency chain: documents -> versions => documents.

    In order to alleviate that, we can pass constraints: false to one of the associations:

    Which will allow us to sync the tables correctly:

    1. CREATE TABLE IF NOT EXISTS "documents" (
    2. "id" SERIAL,
    3. "author" VARCHAR(255),
    4. "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL,
    5. "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL,
    6. "currentVersionId" INTEGER,
    7. PRIMARY KEY ("id")
    8. );
    9. CREATE TABLE IF NOT EXISTS "versions" (
    10. "id" SERIAL,
    11. "timestamp" TIMESTAMP WITH TIME ZONE,
    12. "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL,
    13. "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL,
    14. "documentId" INTEGER REFERENCES "documents" ("id") ON DELETE
    15. SET
    16. PRIMARY KEY ("id")
    17. );

    Enforcing a foreign key reference without constraints

    Sometimes you may want to reference another table, without adding any constraints, or associations. In that case you can manually add the reference attributes to your schema definition, and mark the relations between them.

    1. Trainer.init({
    2. firstName: Sequelize.STRING,
    3. lastName: Sequelize.STRING
    4. }, { sequelize, modelName: 'trainer' });
    5. // Series will have a trainerId = Trainer.id foreign reference key
    6. // after we call Trainer.hasMany(series)
    7. class Series extends Model {}
    8. Series.init({
    9. title: Sequelize.STRING,
    10. subTitle: Sequelize.STRING,
    11. description: Sequelize.TEXT,
    12. // Set FK relationship (hasMany) with `Trainer`
    13. trainerId: {
    14. type: Sequelize.INTEGER,
    15. references: {
    16. model: Trainer,
    17. key: 'id'
    18. }
    19. }
    20. }, { sequelize, modelName: 'series' });
    21. // Video will have seriesId = Series.id foreign reference key
    22. // after we call Series.hasOne(Video)
    23. class Video extends Model {}
    24. Video.init({
    25. title: Sequelize.STRING,
    26. sequence: Sequelize.INTEGER,
    27. description: Sequelize.TEXT,
    28. // set relationship (hasOne) with `Series`
    29. seriesId: {
    30. type: Sequelize.INTEGER,
    31. references: {
    32. model: Series, // Can be both a string representing the table name or a Sequelize model
    33. key: 'id'
    34. }
    35. }
    36. }, { sequelize, modelName: 'video' });
    37. Series.hasOne(Video);