2017-01-08 10 views
3

У меня есть отношение «многие ко многим» с таблицей объединения в середине. Таблицами являются Cookoff, Участник и CookoffParticipant. Я должен упомянуть, что я не разрешаю Sequelize создавать или изменять мои таблицы, я просто сопоставляю свои существующие отношения. Мне нужна помощь в понимании того, какие параметры отношений говорят о том, как вызвать внешний ключ, который связывает таблицу соединений с основной таблицей.Sequelize BelongsToMany с персонализированным основным ключом таблицы соединений

Как я понимаю, Sequelize предполагает, что CookoffID и MemberantID являются составным первичным ключом на CookoffParticipant. В моей ситуации я требую, чтобы первичный ключ был столбцом идентификации. Я вызываю CookoffParticipantID и создаю уникальный индекс в паре CookoffID, PartantID в таблице CookoffParticipant.

Когда я пытаюсь получить данные cookoff и участников, запросив таблицу cookoffPanticipant, 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 пытается присоединиться CookoffParticipant.CookoffParticipantID ON Participant.ParticipantID, где он должен быть CookoffParticipant.ParticipantID = Participant.ParticipantID и аналогично для CookoffID. Что я здесь делаю неправильно?

Заранее благодарю вас за помощь.

ответ

2

Здесь очень хорошо discussion того, что вы ищете. Они подвели его очень хорошо, сказав, что вы должны определить как сквозную таблицу, так и сквозную таблицу, объявляющую ссылки на принадлежность. Вероятно, ваша проблема заключается в том, что вы использовали 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()); 
}); 
+0

Спасибо. Ключевая ошибка заключалась в использовании hasOne вместо applyTo. Это решение немедленно устранило проблему. – rictionaryFever