【问题标题】:Sequelize BelongsToMany with custom join table primary key使用自定义连接表主键 Sequelize BelongsToMany
【发布时间】:2017-05-22 13:44:15
【问题描述】:

我有一个多对多的关系,中间有一个连接表。这些表是 Cookoff、Participant 和 CookoffParticipant。我应该提到我不允许 Sequelize 创建或修改我的表,我只是在映射我现有的关系。我需要帮助了解哪些关系选项告诉 sequelize 调用将连接表与主表相关联的外键。

据我了解,Sequelize 假定 CookoffID 和 ParticipantID 是 CookoffParticipant 上的复合主键。在我的情况下,我要求主键是我调用 CookoffParticipantID 的标识列,并在 CookoffParticipant 表中的 CookoffID、ParticipantID 对上创建唯一索引。

当我尝试通过查询 cookoffParticipant 表来获取烹饪和参与者数据时,Sequelize 使用了错误的键来完成连接。一定有一些简单的事情我没有做。下面是我的表结构和带有结果的查询。

烹饪台

var Cookoff = sequelize.define("Cookoff", {

    // Table columns

    CookoffID: {
        type: DataTypes.INTEGER,
        primaryKey: true,
        autoIncrement: true
    },
    Title: {
        type: DataTypes.STRING,
        allowNull: false
    },
    EventDate: {
        type: DataTypes.DATE,
        allowNull: false
    }
}, _.extend({},

    // Table settings
    defaultTableSettings,

    {
        classMethods: {
            associate: function(models) {
                Cookoff.belongsToMany(models.Participant, {
                    through: {
                        model: models.CookoffParticipant
                    },
                    as: "Cookoffs",
                    foreignKey: "CookoffID",
                    otherKey: "ParticipantID"
                });
            }
        }
    }
));

参与者表

var Participant = sequelize.define("Participant", {

    // Table columns
    ParticipantID: {
        type: DataTypes.INTEGER,
        primaryKey: true,
        autoIncrement: true
    },
    Name: {
        type: DataTypes.STRING(100),
        allowNull: false
    }

}, _.extend({},

    defaultTableSettings,

    {
        classMethods: {
            associate: function(models) {
                Participant.belongsToMany(models.Cookoff, {
                    through: {
                        model: models.CookoffParticipant
                    },
                    as: "Participants",
                    foreignKey: "ParticipantID",
                    otherKey: "CookoffID"
                });
            }
        }
    }
));

Cookoff 参与者表

var CookoffParticipant = sequelize.define("CookoffParticipant", {
    CookoffParticipantID: {
        type: DataTypes.INTEGER,
        allowNull: false,
        primaryKey: true,
        autoIncrement: true
    },
    CookoffID: {
        type: DataTypes.INTEGER,
        allowNull: false,
        references: {
            model: cookoff,
            key: "CookoffID"
        }
    },
    ParticipantID: {
        type: DataTypes.INTEGER,
        allowNull: false,
        references: {
            model: participant,
            key: "ParticipantID"
        }
    }
}, _.extend(
    { },
    defaultTableSettings,
    {
        classMethods: {
          associate: function (models) {
              CookoffParticipant.hasOne(models.Cookoff, { foreignKey: "CookoffID" });
              CookoffParticipant.hasOne(models.Participant, { foreignKey: "ParticipantID" });

            }
        }
    }
));

我的查询

return cookoffParticpants.findOne({
        where: { CookoffID: cookoffID, ParticipantID: participantID },
        include: [
            { model: participants },
            { model: cookoffs }
        ]
    });

生成的 SQL

SELECT 
    [CookoffParticipant].[CookoffParticipantID], 
    [CookoffParticipant].[CookoffID], 
    [CookoffParticipant].[ParticipantID], 
    [Participant].[ParticipantID] AS [Participant.ParticipantID], 
    [Participant].[Name] AS [Participant.Name], 
    [Cookoff].[CookoffID] AS [Cookoff.CookoffID], 
    [Cookoff].[Title] AS [Cookoff.Title], 
    [Cookoff].[EventDate] AS [Cookoff.EventDate] 
FROM [CookoffParticipant] AS [CookoffParticipant] 
LEFT OUTER JOIN [Participant] AS [Participant] 
    ON [CookoffParticipant].[CookoffParticipantID] = [Participant].[ParticipantID]  -- This should be CookoffParticipant.ParticipantID
LEFT OUTER JOIN [Cookoff] AS [Cookoff] 
    ON [CookoffParticipant].[CookoffParticipantID] = [Cookoff].[CookoffID] -- This should be CookoffParticipant.CookoffID
WHERE [CookoffParticipant].[CookoffID] = 1 
AND [CookoffParticipant].[ParticipantID] = 6 
ORDER BY [CookoffParticipantID] 
OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY;

您可以看到 Sequelize 正在尝试在 Participant.ParticipantID 上加入 CookoffParticipant.CookoffParticipantID,其中应该是 CookoffParticipant.ParticipantID = Participant.ParticipantID 和 CookoffID 类似。我在这里做错了什么?

提前感谢您的帮助。

【问题讨论】:

    标签: sql node.js sequelize.js


    【解决方案1】:

    这是您正在寻找的非常好的discussion。他们很好地总结了这一点,说您应该同时定义一个直通表和声明belongsTo 引用的直通表。您的问题可能是您使用了hasOne 而不是belongsTo。另外我认为你的as 键是向后的。

    Cookoff.hasMany(Book, { through: CookoffParticipant })
    Participant.hasMany(User, { through: CookoffParticipant })
    CookoffParticipant.belongsTo(Cookoff)
    CookoffParticipant.belongsTo(Participant)
    

    这是我用来测试的代码。

    Cookoff.js

    module.exports = (sequelize, DataTypes) => {
        var Cookoff = sequelize.define("Cookoff", {
            CookoffID: {
                type: DataTypes.INTEGER,
                primaryKey: true,
                autoIncrement: true
            }
        }, _.extend(
            {},
            {
                classMethods: {
                    associate: function(models) {
                        Cookoff.belongsToMany(models.Participant, {
                            through: models.CookoffParticipant,
                            foreignKey: "CookoffID",
                            otherKey: "ParticipantID"
                        });
                    }
                }
            }
        ));
        return Cookoff;
    };
    

    参与者.js

    module.exports = (sequelize, DataTypes) => {
        var Participant = sequelize.define("Participant", {
            ParticipantID: {
                type: DataTypes.INTEGER,
                primaryKey: true,
                autoIncrement: true
            }
        }, _.extend(
            {},
            {
                classMethods: {
                    associate: function(models) {
                        Participant.belongsToMany(models.Cookoff, {
                            through: models.CookoffParticipant,
                            foreignKey: "ParticipantID",
                            otherKey: "CookoffID"
                        });
                    }
                }
            }
        ));
        return Participant;
    };
    

    CookoffParticipant.js

    module.exports = (sequelize, DataTypes) => {
        var CookoffParticipant = sequelize.define("CookoffParticipant", {
            CookoffParticipantID: {
                type: DataTypes.INTEGER,
                allowNull: false,
                primaryKey: true,
                autoIncrement: true
            }
        }, _.extend(
            {},
            {
                classMethods: {
                    associate: function(models) {
                        CookoffParticipant.belongsTo(models.Cookoff, { foreignKey: "CookoffID" });
                        CookoffParticipant.belongsTo(models.Participant, { foreignKey: "ParticipantID" });
                    }
                }
            }
        ));
        return CookoffParticipant;
    };
    

    test.js

    const db = require('../db');
    const Cookoff = db.Cookoff;
    const Participant = db.Participant;
    const CookoffParticipant = db.CookoffParticipant;
    let cookoff,
        participant;
    
    Promise.all([
        Cookoff.create({}),
        Participant.create({})
    ]).then(([ _cookoff, _participant ]) => {
        cookoff = _cookoff;
        participant = _participant;
    
        return cookoff.addParticipant(participant);
    }).then(() => {
        return CookoffParticipant.findOne({
            where: { CookoffID: cookoff.CookoffID, ParticipantID: participant.ParticipantID },
            include: [ Cookoff, Participant ]
        });
    }).then(cookoffParticipant => {
        console.log(cookoffParticipant.toJSON());
    });
    

    【讨论】:

    • 谢谢。关键错误是使用 hasOne 而不是 belongsTo。进行该开关立即解决了问题。
    猜你喜欢
    • 2018-08-18
    • 2017-01-16
    • 1970-01-01
    • 2018-03-29
    • 2018-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多