2017-01-08 78 views
3

我与中间连接表具有多对多关系。这些表是Cookoff,Participant和CookoffParticipant。我应该提到我不允许Sequelize创建或修改我的表格,我只是简单地映射我现有的关系。我需要帮助了解哪些关系选项告诉将连接表与主表关联的外键调用什么。使用自定义连接表主键关联多个关系

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

当我试图通过cookoffParticipant表查询cookoff和参与者数据时,Sequelize使用错误的键来完成加入。必须有一些简单的事情,我没有做。以下是我的表格结构和查询结果。

Cookoff表

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正在尝试加入CookoffParticipant.CookoffParticipantID ON Participant.ParticipantID,它应该是CookoffParticipant.ParticipantID = Participant.ParticipantID同样地,对于CookoffID。我在这里做错了什么?

非常感谢您的帮助。

回答

2

这是一个非常好的discussion你正在寻找。他们非常好地总结说,你应该定义一个通过表和通过表声明belongsTo引用。您的问题可能是您使用hasOne而不是belongsTo。另外我认为你的钥匙是倒退的。

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()); 
}); 
+0

谢谢。关键错误是使用hasOne而不是belongsTo。做出这个切换立即解决了问题。 – rictionaryFever