简体   繁体   English

如何使用 sequelize.js 将表的列设置为外键

[英]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.我想要实现的是:当添加新的比赛时,我需要在 table team_comp中创建一行,其中包含与表格比赛的字段“competition_teams”相同的 id 以及我通过请求发送的额外数据。 I'll have a lot of competitions but each competition has one team_comp that belongs to it.我会参加很多比赛,但每场比赛都有一个 team_comp 属于它。 If i delete a competition, its team_comp row must be deleted.如果我删除比赛,则必须删除其 team_comp 行。

table competition :桌上比赛

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

table team_comp :team_comp

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

In my models/index.js I'm defining associations like this:在我的models/index.js中,我正在定义这样的关联:

// 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).它在表 ** team_comp ** 中为我创建了一个指向competion.id而不是 Competition.competition_teams 的外键(这是我想要的)。 How can I let it points to competition.competition_teams?我怎样才能让它指向competition.competition_teams?

This is how I add a new competition (controllers/ competition.js):这就是我添加新比赛(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您需要在关联中指定sourceKey属性 - 如果忽略它将使用 table + id 参考

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:将导致生成并执行以下 SQL:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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