Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Exemplo simples de relação muitos-para-muitos usando Sequelize

Migrações


Eu sugiro que você use sequelize migrations em vez de fazer sync() em cada modelo. Existe um módulo - sequelize.cli que permite gerenciar migrações e sementes facilmente. De alguma forma, força uma estrutura de projeto criando o arquivo de inicialização index.js dentro de /models diretório do projeto. Ele assume que todas as suas definições de modelo estarão neste diretório. Este script itera através de todos os arquivos de modelo (cada definição de modelo está em um arquivo separado, por exemplo, mentee.js , question.js ) e executa sequelize.import() para atribuir esses modelos à instância sequelize - isso permite acessá-los posteriormente por meio de sequelize[modelName] por exemplo. sequelize.question .

Observação: ao criar arquivos de migração, lembre-se dos campos de timestamps - createdAt , updatedAt e, eventualmente, deletedAt .

Sincronizar


Pessoalmente eu uso sync() apenas quando executo os testes - isso pode ser mostrado em três etapas
  1. executar sequelize.sync({ force: true }) para sincronizar todos os modelos
  2. execute algumas seeds do banco de dados (também pode ser feito via sequelize-cli ),
  3. executar testes.

Isso é muito confortável porque permite limpar o banco de dados antes de executar os testes e, para distinguir desenvolvimento de testes, os testes podem usar banco de dados diferente, por exemplo project_test , para que o banco de dados de desenvolvimento permaneça intacto.

Muitos para muitos


Agora vamos para o seu problema - relação m:n entre dois modelos. Em primeiro lugar, devido ao fato de você executar Promise.all() , a sync pode ser executado em ordem diferente da que você adiciona as funções nele. Para evitar essa situação, sugiro que você use mapSeries recurso do Bluebird promessa, que o Sequelize usa e expõe em sequelize.Promise (este é também o motivo do seu último erro sobre a exclusão da linha pai - você tenta excluir mentees que é referenciado em menteequestion ).
sequelize.Promise.mapSeries([
    Mentee.sync({ force: true })
  , Question.sync({ force: true })
  , MenteeQuestion.sync({ force: true })
], (model) => { return model.destroy({ where: {} }); }).then(() => {

});

Primeiro parâmetro de mapSeries é uma matriz de promessas, porém a segunda é uma função que é executada com o resultado de cada promessa definida anteriormente. Devido ao fato de que Model.sync() resultados no próprio modelo, podemos executar model.destroy() em cada iteração.

Depois disso, você pode inserir alguns dados no banco de dados via create() , como no exemplo. Agora é hora de corrigir o Erro:mentee não está associado a menteequestion! erro. Isso ocorre porque você associou Mentee com Question mas não há associação entre MenteeQuestion e Mentee (ou Question ). Para corrigir isso, depois de belongsToMany , Você pode adicionar
MenteeQuestion.belongsTo(Mentee, { foreignKey: 'menteeId' });
MenteeQuestion.belongsTo(Question, { foreignKey: 'questionId' });

Agora você pode adicionar include: [Mentee, Question] ao consultar MenteeQuestion . Você também executaria outro erro ao fazer toJSON() , porque você faz findAll que retorna array de instâncias. Você poderia fazer forEach()
menteeQuestions.forEach(menteeQuestion => {
    console.log(menteeQuestion.toJSON());
});