Tutorial de Migrations com Node.js e Sequelize

Node.js

Tutorial de Migrations com Node.js e Sequelize

Luiz Duarte
Escrito por Luiz Duarte em 27/01/2021
Junte-se a mais de 22 mil profissionais de TI

Entre para minha lista e receba conteúdos exclusivos e com prioridade

Recentemente escrevi tutoriais de como usar Node.js com o ORM Sequelize usando os bancos MySQL, PostgreSQL e SQLite. Na primeira parte sempre vemos como fazer o CRUD básico de Produtos e, na segunda parte, nosso foco maior foi no relacionamento das tabelas Produtos, Categorias e Fabricantes.

Tudo vai bem quando estamos em ambiente de dev, ainda criando nossa aplicação e modelando nossas tabelas. Eventualmente, se precisarmos, sempre podemos mandar o Sequelize forçar a recriação de toda a base usando a configuração de force no sync, como abaixo.

No entanto, temos três cenários em que você não vai querer usar o force e adotar abordagens mais profissionais:

  • quando você já tem dados na sua base que não quer que sejam perdidos;
  • quando já tem o seu projeto em produção;
  • quando você quer versionar as mudanças do seu banco de dados através de código;

Em todos os casos, o ideal é que você migre o schema do seu banco de dados para o novo schema, quer você tenha alterado tabelas já existentes ou criado tabelas novas.

A esse processo, damos o nome de migrations e esse é o assunto central do tutorial de hoje.

Atenção: este tutorial serve perfeitamente bem para qualquer banco de dados que o Sequelize suporta. Apenas instale o driver apropriado e defina a connection string corretamente e tudo correrá bem.

Sequelize CLI

O Sequelize possui um utilitário de linha de comando chamado Sequelize CLI que auxilia em diversas atividades ligadas aos models da nossa aplicação, incluindo funcionalidades para nos ajudar com migrations. Como eu queria que a gente começasse sem ele, só estou apresentando agora.

Esse utilitário permite que você gere automaticamente models, que você crie as tabelas no banco e que você crie e execute migrations automaticamente. Não vou conseguir aqui apresentar todo o potencial dele, mas vale uma estudada na documentação oficial. Vamos usá-lo via linha de comando para criar nossa primeira migration.

Vamos imaginar primeiro um cenário bem simples, onde quero criar uma nova tabela no meu banco de dados, mas quero fazer isso em dev através de um script que depois possa ser usado pelos meus colegas de time ou mesmo na hora do deploy em produção.

Para criar uma migration, você usa o seguinte comando no console, que baixa e executa o Sequelize CLI com o comando de criação de migration.

Isso irá criar uma pasta migrations no seu projeto e dentro dela nosso primeiro arquivo de migration, idêntico ao abaixo.

Toda migration possui um up e um down, referente ao script de migration e o rollback da mesma. Isso permite que em caso de erro seja desfeita a mudança, mas também permite a gestão das alterações do banco de dados com muito mais detalhe.

Considere que em nossa pasta models temos um novo modelo, de Cliente, como abaixo (dando continuidade ao projeto do tutorial anterior).

Agora, para criar a migration de criação desta tabela, podemos modificar nosso arquivo de migration para isto.

Repare como coloquei o script de up praticamente idêntico ao do model de Cliente e embora pareça muito tentador carregar o model e passá-lo como parâmetro, isso não deve ser feito pois o model pode mudar ao longo do tempo e a migration jamais deve mudar. Conforme quisermos novas alterações no banco, devemos criar novas migrations, nunca alterar as já existentes.

Já o script de down é bem direto, apenas mando dropar a tabela que acabei de criar.

Executando a migration

Para que nossa migration saiba as configurações que precisa usar para se conectar no banco certo, crie uma pasta config na raiz do projeto com um arquivo config.json dentro.

O conteúdo do config.json é a configuração para conexão em cada um dos ambientes de banco de dados que você tiver. Por exemplo, tendo 3 ambientes, teremos:

Aqui, estou dizendo que todos os ambientes na verdade vão usar uma variável de ambiente chamada DATABASE_URL, que precisará estar definida para que a migration funcione. Você pode fazer isso no seu ambiente de dev com o comando abaixo.

Repare que estou apontando para uma base local com as minhas configurações. Certifique-se de apontar para as configurações do seu servidor de banco

Para executar esta migration, rode o comando abaixo que vai ir na pasta migrations e executar todos os scripts que estiverem lá, na ordem correta (do primeiro ao último).

O resultado será visto no console.

E no banco de dados, que deve conter agora uma tabela clientes.

Se você quiser testar se seu model Clientes está se comunicando corretamente com o banco de dados, o código abaixo pode ser utilizado em uma index.js na raiz da sua aplicação.

Se tudo der certo, um cliente deve ser cadastrado no seu banco de dados. Além disso, uma nova tabela deve ser criada, chamada SequelizeMeta. Se olhar o seu conteúdo, verá que ela mantém registro de quais migrations já foram executadas neste banco, o que será útil mais tarde.

Repare também que, diferente dos tutoriais anteriores, eu não usei o sync do Sequelize aqui, pois estou confiando de que meu model e minha tabela estão idênticos. Se não estiverem, provavelmente terei algum erro.

Trabalhar com migrations exige que o time entre em acordo de que não deve alterar um model sem criar uma nova migration, caso contrário terão problemas.

Curso Node.js e MongoDB

Alterando uma tabela

Imagine agora que algo mudou na regra e negócio da empresa e os clientes devem ter seus telefones registrados também, sendo que cada cliente vai ter apenas um telefone. Neste caso devemos criar uma nova migration específica para isso.

Assim, rode o comando abaixo para a nova migration.

Repare que cada vez que executamos o comando npx, o pacote é baixado e executado. Se for fazer isso com frequência e quiser ganhar tempo, pode instalar a dependência e rodar com ‘npm sequelize-cli’.

Agora no script de migration novo que foi criado, altere para incluir a nova coluna na tabela.

Aqui usamos a função addColumn do objeto queryInterface informando a tabela, a coluna e as configurações da coluna, usando a mesma notação que usamos para definição do model.

Aliás, adicione também esta nova coluna no seu model.

Para executar a migration e atualizar o seu banco, execute:

Lembra que falei da tabela SequelizeMeta que foi criada automaticamente? Ao mandarmos rodar o comando acima novamente, o Sequelize CLI vai ir nesta tabela para ver quais migrations ele precisa executar ainda e quais ele já executou e é por isso que, novamente, reforço que devemos sempre criar novas migrations e nunca alterar migrations já existentes.

Ao executar o comando no banco já existente, você notará que será impresso no console somente a migration de telefone, mas que se executar em um banco novo, vai executar as duas.

E por hoje é só!

Quer aprender a construir aplicações completas em Node.js e Sequelize comigo, na prática? Conheça o meu curso clicando no banner abaixo.

Curso FullStack

Olá, tudo bem?

O que você achou deste conteúdo? Conte nos comentários.