简体   繁体   中英

How to set a column of a table as a foreign key using sequelize.js

What I'm trying to achieve is: when a new competition is added, I need to create a row in the the table team_comp conteining the same id of field "competition_teams" of table competition and the extra data that i send by request. I'll have a lot of competitions but each competition has one team_comp that belongs to it. If i delete a competition, its team_comp row must be deleted.

table competition :

| id  | name  | competition_teams |
|  1  |  A    |      32           |

table team_comp :

| id  | competition_id  | test_h |
|  3  |       32        |  1     |

In my models/index.js I'm defining associations like this:

// Competition
db.competition.hasOne(db.competition_team, {as: 'compId', foreignKey : 'competition_id'});

// Competition Teams
db.competition_team.belongsTo(db.competition, {as: 'compTeam', foreignKey : 'competition_id', onDelete: 'CASCADE'});

By doing this, I get the wrong foreign key. It creates me a foreign key in table ** team_comp ** pointing to competion.id and not into competition.competition_teams (which is what i want). How can I let it points to competition.competition_teams?

This is how I add a new competition (controllers/ competition.js):

import db from '../models/index';
const Competition = db.competition;
const Competition_teams = db.competition_team;

// create competition
const create = (req, res) => {

    // generating a random id for the competition
    var competition_teams = Math.floor(Math.random() * 100);

    let { 
       name, 
       test_h,
    } = req.body;
     
    // create new Competition
    let newCompetition = { 
      name, 
      competition_teams // this must be also added in table team_comp, column competition_id
    }

    let newCompetitionTeams = {
      test_h
    }

    Competition.create(newCompetition)
      .then(Competition => {
        res.json({ Competition });
      })
      .catch(err => {
        console.log("Error: " + err);
        return res.status(500).json({ err });
      });

    // creating teams association    
    Competition_teams.create(newCompetitionTeams)
      .then(Competition_teams => {
        res.json({ Competition_teams });
      })
      .catch(err => {
        console.log("Error: " + err);
        return res.status(500).json({ err });
      });
}

You need to specify the sourceKey property in the association - if ignored it will use table + id Reference

The name of the attribute to use as the key for the association in the source table. Defaults to the primary key of the source table

See the following complete example:

class Competition extends Sequelize.Model {
}

Competition.init({
    id: {
        primaryKey: true,
        type: Sequelize.INTEGER,
        allowNull: false
    },
    name: {
        type: Sequelize.STRING(36)
    },
    team_competition_id: {
        type: Sequelize.INTEGER,
        allowNull: false,
    }
}, {
    sequelize,
    modelName: 'competition',
    tableName: 'competitions',
    timestamps: false
});

class Team_Competition extends Sequelize.Model {
}

Team_Competition.init({
    id: {
        primaryKey: true,
        type: Sequelize.INTEGER,
        allowNull: false
    },
    name: {
        type: Sequelize.STRING(36)
    },
}, {
    sequelize,
    modelName: 'team_competition',
    tableName: 'team_competitions',
    timestamps: false
});

// use sourceKey here - also make sure you specify `cascade` and `hooks` property
Competition.hasOne(Team_Competition, {sourceKey: 'team_competition_id', foreignKey: 'id', onDelete: 'cascade', hooks: true});

// tests
    // create the team_competition
    const team_competition = await Team_Competition.create({
        id: 1,
        name: 'Team A'
    });

    // create the competition
    const competition = await Competition.create({
        id: 1,
        name: 'Comp A',
        team_competition_id: team_competition.id
    });

    // test the join
    const competitions = await Competition.findAll({
        include: [
            {
                attributes: ['id', 'name'],
                model: Team_Competition,
            }
        ],
        raw: true
    });

    // delete and verify cascade
    await competition.destroy();

Will result in the following SQL generated and executed:

Executing (default): INSERT INTO "team_competitions" ("id","name") VALUES ($1,$2) RETURNING *;
Executing (default): INSERT INTO "competitions" ("id","name","team_competition_id") VALUES ($1,$2,$3) RETURNING *;

// query
Executing (default): SELECT "competition"."id", "competition"."name", "competition"."team_competition_id", "team_competition"."id" AS "team_competition.id", "team_competition"."name" AS "team_competition.name" FROM "competitions" AS "competition" LEFT OUTER JOIN "team_competitions" AS "team_competition" ON "competition"."team_competition_id" = "team_competition"."id";

// cascade deletes
Executing (default): DELETE FROM "team_competitions" WHERE "id" = 1
Executing (default): DELETE FROM "competitions" WHERE "id" = 1

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM