-
Notifications
You must be signed in to change notification settings - Fork 0
4. Sequelize com PostgreSQL
Vou compartilhar como iniciei a implementação no meu projeto, indo desde a configuração inicial até a criação de seeds (registros) em uma tabela!
Até aqui estou utilizando NodeJS, Express, EJS, Sequelize e Postgres! O ponto de partida é ter um servidor rodando com o express e o postgres devidamente instalado no PC.
Aqui eu já comentei sobre como inicializar um servidor com o express (é bem fácil 😉)
Conteúdo:
- Sobre ORMs e a instalação do Sequelize
- Como conectar o banco de dados PostgreSQL com o Sequelize
- Como criar uma tabela no banco de dados, via Sequelize
- Como rodar uma migração para atualizar o banco de dados
- Como desfazer uma migração
- Como incluir registros na tabela via Sequelize - Seeds
- Como desfazer seeds
- Concluindo
ORM significa "mapeador de objeto relacional". Com essa ferramenta podemos abstrair comandos de SQL, além de documentar e rastrear mudanças em um banco de dados. Basicamente o ORM é responsável por se conectar ao banco de dados e converter os métodos e funções em queries. O Sequelize é o ORM que será utilizado no meu projeto.
-
Duas dependências serão instaladas:
- sequelize: utilizado para instalar e utilizar os métodos da ferramenta;
- sequelize-cli: instalado para utilizar alguns recursos de linha de comando que o sequelize tem: conexão com banco, criação de modelos, arquivos e etc.
-
Na pasta do projeto, rodar o comando
npm install sequelize sequelize-cli; -
Para iniciar a base com os arquivos que serão utilizados, rodar o comando
npx sequelize-cli init, isso criará as seguintes pastas no projeto:- config: contém o arquivo de configuração, que diz à CLI como se conectar ao banco de dados
- models: contém os modelos para o projeto
- migrations: contém os arquivos de migração
- seeders: contém os arquivos de seed
-
Como a hierarquia de pastas do meu projeto é diferente do padrão esperado pelo Sequelize, é necessário criar o arquivo com o nome
.sequelizerc.
Este é um arquivo padrão da ferramenta que possibilita algumas configurações especiais, como é possível consultar na documentação. Irei utilizar apenas para indicação do caminho das pastas (path):

Feito isto, é hora de configurar o banco de dados!
- Instalar o postgres como dependência do projeto, através do comando
npm install pg;
Na pasta "config" que foi criada anteriormente, há o arquivo config.json, que é onde consta a configuração necessária para conexão com o banco de dados.
Inicialmente o arquivo possui essas informações:

- Na configuração de desenvolvimento irei incluir os dados do Postgres (essas informações foram configuradas durante a instalação dele).
Em database consta o nome do banco de dados "Receitas", ele que será utilizado no meu projeto. A criação de um banco de dados não é realizada pelo Sequelize, fiz diretamente no PostgreSQL (apenas a criação do banco, porque o restante, como as tabelas, será implementado via Sequelize).
{
"development": {
"username": "postgres",
"password": "admin",
"database": "receitas",
"host": "127.0.0.1",
"dialect": "postgres"
},A criação de tabelas é feita através dos modelos do Sequelize, então, uma tabela corresponde a um modelo.
- Para criar uma tabela chamada "Usuarios", que contenha as colunas "nome" e "email", é necessário informar o nome do modelo e seus atributos, com o comando:
npx sequelize-cli model:create --name Usuarios --attributes nome:string,email:string. - Será criado um arquivo para o modelo e outro para migração (próximo tópico):

É bem importante dar uma olhada nos tipos de dados do Sequelize, conforme consta aqui nessa parte da documentação, pois eu já criei uma coluna com o tipo incorreto e depois precisei ajustar (assunto para um texto específico!).
Sobre o nome dos modelos, é um ponto de atenção o fato de que o Sequelize converte os nomes para o plural (apenas adicionando um "s" no final), então se definir o nome "Usuario" ele irá criar como "Usuarios". O problema acontece em casos como: "cor", que será convertido para "cors". Então é importante definir o nome das tabelas sempre no plural.
- No arquivo
usuarios.jsque foi criado automaticamente dentro da pasta "models" consta a configuração da tabela:
'use strict';
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class Usuarios extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate(models) {
// define association here
}
};
Usuarios.init({
nome: DataTypes.STRING,
email: DataTypes.STRING
}, {
sequelize,
modelName: 'Usuarios',
});
return Usuarios;
};Mas a tabela ainda não foi criada, pois para atualizar no banco de dados é necessário rodar uma migração!
Obs.: sobre a criação de tabelas com associações e chaves estrangeiras, irei compartilhar um texto específico sobre isso 🤓
Primeiro, o que são migrações: no ORM, migração corresponde a alterações de tabelas de forma rastreável, sendo possível voltar o estado da tabela para um anterior caso necessário. Os arquivos de migração são utilizados para comunicar ao banco a estrutura das tabelas, suas colunas e tipos de dados.
Na criação do modelo, este arquivo 20201201194736-create-usuarios.js foi criado automaticamente dentro da pasta "migrations", com o seguinte conteúdo:
'use strict';
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable('Usuarios', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
nome: {
type: Sequelize.STRING
},
email: {
type: Sequelize.STRING
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable('Usuarios');
}
};- No nome do arquivo consta a data e hora em que ele foi criado (
20201201194736-create-usuarios.js). Isso acontece porque o Sequelize roda as migrações na ordem em que foram criadas :) - O que está configurado neste arquivo de migração:
- ao rodar a migração acontecerá o que está definido em "up":
createTable; - em "down" consta a definição do que acontecerá quando for necessário desfazer essa migração, isto é, excluir a tabela (
dropTable); - como primeiro atributo da tabela, já foi configurado automaticamente a coluna "id" 😀
- e no final outros dois atributos foram criados automaticamente:
createdAteupdatedAt
- ao rodar a migração acontecerá o que está definido em "up":
- Executar o comando
npx sequelize-cli db:migratepara rodar a migração. Este é o retorno esperado:

Uma consulta básica no banco de dados só pra confirmar que está tudo certo, a tabela está lá:
😅 👍

Sobre o comando npx sequelize-cli db:migrate, conforme a documentação, este comando executará as seguintes etapas:
- Vai garantir uma tabela chamada SequelizeMeta no banco de dados. Esta tabela é usada para registrar quais migrações foram executadas no banco de dados atual
- Começa a procurar arquivos de migração que ainda não foram executados. Isso é possível verificando a tabela SequelizeMeta;
- Cria uma tabela com o nome e todas as colunas conforme especificado no arquivo de migração.
👇 Um basiquinho de comandos do Postgres (executados no psql) que uma hora dessas eu vou decorar:
- Como listar as bases de dados existentes no postgres:
\l - Como conectar em uma base dados:
\c nome_do_banco - Como listar as tabelas existentes na base de dados conectada:
\d
Para os casos em que há alguma inconsistência no modelo: tabela criada incorretamente, colunas incorretas, índices, nomes de colunas e etc.
Existe mais de uma opção para isso!
- Comando
npx sequelize-cli db:migrate:undo: irá reverter a migração mais recente; - Comando
npx sequelize-cli db:migrate:undo:allvolta ao estado inicial, desfazendo todas as migrações; - Comando
npx sequelize-cli db:migrate:undo XXXXXXXXXXXXXX-nome-do-arquivo.jsirá desfazer uma migração específica (exemplo:npx sequelize-cli db:migrate:undo 20201201194736-create-usuarios.js)
Lembrando que ao desfazer a migração o que será executado é o que foi especificado em "down" no arquivo de migração.
Claro que outra opção também seria gerar uma nova migração com as alterações necessárias no modelo, mas vou compartilhar isso em outro momento 😜
Para testar as funcionalidades implementadas no projeto são necessários alguns dados na tabela e é aqui que entram os "seeds". Como consta na documentação, os arquivos de sementes são algumas alterações nos dados que podem ser usados para preencher a tabela do banco de dados com dados de amostra ou dados de teste.
Criando um seed para registrar 3 usuários fictícios na tabela:
- executar o comando
npx sequelize-cli seed:generate --name nome, exemplo:npx sequelize-cli seed:generate --name demo-usuario - será gerado um arquivo dentro da pasta "seeders". Esse arquivo não vem pronto, deve ser editado com a inclusão dos dados desejados:
Arquivo criado automaticamente:
'use strict';
module.exports = {
up: async (queryInterface, Sequelize) => {
/**
* Add seed commands here.
*
* Example:
* await queryInterface.bulkInsert('People', [{
* name: 'John Doe',
* isBetaMember: false
* }], {});
*/
},
down: async (queryInterface, Sequelize) => {
/**
* Add commands to revert seed here.
*
* Example:
* await queryInterface.bulkDelete('People', null, {});
*/
}
};Arquivo atualizado com os registros que eu desejo criar na tabela Usuarios:
'use strict';
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.bulkInsert('Usuarios', [{
nome: 'Malu',
email: 'malu@malu.com',
createdAt: new Date(),
updatedAt: new Date()
},
{
nome: 'Joao',
email: 'joao@joao.com',
createdAt: new Date(),
updatedAt: new Date()
},
{
nome: 'Cris',
email: 'cris@cris.com',
createdAt: new Date(),
updatedAt: new Date()
}], {});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.bulkDelete('Usuarios', null, {});
}
};Atenção para os campos createdAt e updatedAt que também devem constar no arquivo, pois sem eles dará erro na criação dos registros.
- rodar o comando
npx sequelize-cli db:seed:allpara atualizar a tabela com os seeds;
Esse comando vai executar todos os seeds, caso seja necessário rodar somente um arquivo específico, é possível utilizar o comando npx sequelize db:seed --seed nome-do-arquivo.js.
Também existe mais de uma opção para isso!
- comando
npx sequelize db:seed:undodesfaz o último seed feito; - comando
npx sequelize-cli db:seed:undo --seed nome-do-arquivo.jsdesfaz seeds de uma tabela em específico; - comando
npx sequelize-cli db:seed:undo:alldesfaz todos os seeds criados.
Pontos de atenção:
Os seeds não tem recurso de "versionamento" como acontece com as migrações.
Se rodar o :undo em uma tabela para apagar os registros e mais tarde utilizar os seeds novamente na mesma tabela, os IDs deles serão outros. Por exemplo:
Ao rodar o comando npx sequelize-cli db:seed:all para popular a tabela a primeira vez, no banco serão criados estes registros:
| id | Nome | |
|---|---|---|
| 1 | Malu | malu@malu.com |
| 2 | João | joao@joao.com |
| 3 | Cris | cris@cris.com |
Se rodar o comando npx sequelize-cli db:seed:undo:all para deletar esses registros e, em seguida, refazer os seeds, o resultado será esse:
| id | Nome | |
|---|---|---|
| 4 | Malu | malu@malu.com |
| 5 | João | joao@joao.com |
| 6 | Cris | cris@cris.com |
Os registros terão novos IDs, pois uma vez deletado o ID nunca é reutilizado.
Por que isso é relevante?
Se estiver atuando com tabelas relacionadas, é importante conferir os IDs para não ocorrer erro. Eu já bati a cabeça por uns bons minutos com um erro gerado porque eu informei um ID que não existia na tabela! (sobre tabelas relacionadas, vou compartilhar em um texto específico!).
Até aqui o Sequelize está configurado, a conexão com o banco está funcionando e há uma tabela com registros para teste. Ainda tem muita coisa legal a ser feita, como a criação dos métodos para interação com o banco de dados, criação de tabelas com associação, algumas dicas de como resolver situações que acontecem no dia a dia e por aí vai. Em outros textos vou compartilhar como fiz tudo isso no meu projeto
Ah! Meu primeiro contato com o Sequelize foi através de dois cursos da Alura e eu gostei bastante do conteúdo:
- ORM com NodeJS: API com Sequelize e MySQL
- ORM com NodeJS: Avançando nas funcionalidades do Sequelize
Eu que não conhecia nem o conceito de ORM saí com os primeiros passos dados e o projeto elaborado durante os dois cursos foi bem tri 👍. Depois disso eu consultei muito a documentação e confesso que achei ela confusa em vários momentos. PostgreSQL que foi novidade pra mim (os cursos que eu tinha feito eram sobre MySQL), mas o uso até agora tem sido bem tranquilo.
Enfim, até a próxima!
