使用自定义连接表主键

时间:2017-01-08 01:56:36

标签: sql node.js sequelize.js

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

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

当我尝试通过查询cookoffParticipant表获取cookoff和参与者数据时,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"
                });
            }
        }
    }
));

CookoffParticipant表

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。我在这里做错了什么?

提前感谢您的帮助。

1 个答案:

答案 0 :(得分:3)

这是您正在寻找的非常好的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;
};

Participant.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());
});
相关问题