Tutorial Node.js com MongoDB, Mongoose, Express e EJS

Node.js

Tutorial Node.js com MongoDB, Mongoose, Express e EJS

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

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

Neste tutorial você vai aprender como criar uma aplicação web básica, apenas com listagem e cadastro, utilizando a stack Node.js, Express, EJS, Mongoose e MongoDB. É um excelente tutorial para quem não sabe nada de Node.js e/ou de algum dos componentes desta stack de tecnologia que citei, mas está longe de ser um material definitivo sobre o assunto.

Um outro excelente tutorial que faz a mesma coisa que este, mas que não usa Mongoose é este aqui. E se você não quer saber de MongoDB, mas sim de SQL, mude para este tutorial (inclui vídeo).

Ao término do artigo você encontrará um formulário para baixar os fontes, bem como outros posts adicionais, meus livros, cursos, etc. Qualquer dúvida que tiver sobre o assunto, deixe nos comentários.

Neste artigo você vai ver:

  1. Configurando o ambiente
  2. Entendendo o Express
  3. Preparando o banco de dados
  4. Conectando no Mongo com Node
  5. Escrevendo no banco

Vamos lá!

Curso FullStack

#1 – Configurando o ambiente

Nesta parte vamos instalar e configurar o ambiente necessário para o restante do tutorial. Vamos começar instalando o Node.js. Bem fácil: apenas clique no link do site oficial e depois no grande  botão verde para baixar o executável certo para o seu sistema operacional, sendo recomendada a versão LTS. Esse executável irá instalar o Node.js e o NPM, que é o gerenciador de pacotes do Node.

Uma vez com o NPM instalado, Crie uma pasta para guardar os seus projetos Node no computador e, dentro dela, via terminal de comando com permissão de administrador, rode o comando abaixo para instalar o Express Generator, um criador de aplicações Express que vai facilitar bastante o nosso trabalho:

Depois de instalado, para executá-lo rode o seguinte comando, onde web-app é o nome do seu projeto:

O “-e” é para usar a view-engine (motor de renderização) EJS, ao invés do tradicional Jade/Pug que seria usado por padrão. Eu faço esta mudança pois o EJS usa HTML tradicional, ficando muito mais simples de criar interfaces web. Já o “–git” deixa seu projeto preparado para versionamento com Git. Aperte Enter e o projeto será criado.

Depois entre na pasta e mande instalar as dependências:

Ainda no terminal de linha de comando e, dentro da pasta do projeto, digite o comando abaixo:

Isso vai fazer com que a aplicação inicie sua execução em localhost:3000, que você pode acessar pelo seu navegador.

Capture

OK, agora que temos a estrutura básica vamos fazer mais alguns ajustes em um arquivo que fica na raiz do seu projeto chamado package.json. Ele é o arquivo de configuração do seu projeto e determina, por exemplo, quais as bibliotecas que você possui dependência no seu projeto.

Precisamos alterar umas pequenas coisas nele, especificamente adicionar dependências para que o MongoDB funcione com essa aplicação usando o ORM Mongoose. Um ORM é uma biblioteca de programação que facilita o uso de bancos de dados e o Mongoose, em nosso caso, é um ORM para MongoDB.

Para adicionar dependências, usamos o NPM via linha de comando de novo:

Com isso, duas dependências serão baixadas e duas novas linhas de dependências serão adicionadas para dar suporte a MongoDB. Ainda em seu diretório web-app, digite o comando abaixo para criar uma pasta:

Nesta pasta vamos armazenar nossos dados do MongoDB, por uma questão de organização.

#2 – Entendendo o Express

Vamos abrir agora o arquivo app.js, que fica dentro do diretório da sua aplicação NodeJS (web-app no meu caso). Este arquivo é o coração da sua aplicação, embora não exista nada muito surpreendente dentro. Você deve ver algo parecido com isso logo no início:

Isto define um monte de variáveis JavaScript e referencia elas a alguns pacotes, dependências, funcionalidades do Node e rotas. Rotas são módulos JavaScript que recebem as requisições do usuário à sua aplicação web – elas direcionam o tráfego e contém também alguma lógica de programação (embora você consiga, se quiser, fazer uma arquitetura MVC, se desejar). Quando criamos o projeto com o Express-Generator, ele criou estes códigos JS pra gente e vamos ignorar a rota ‘users’ por enquanto e nos focar no index, controlado pelo arquivo /routes/index.js.

Na sequência você deve ver:

Este é bem importante. Ele instancia o Express em uma variável app. A próxima seção usa esta variável para configurar os middlewares do Express. Um middleware é um módulo que faz algum processamento em cima de uma requisição recebida. Caso o processamento seja concluído com sucesso, ele repassa a requisição para o próximo middleware, caso contrário, dispara um erro.

A configuração dos middlewares acima dizem ao app onde ele encontra suas views, qual engine usar para renderizar as views (EJS), define a interpretação do corpo de requisição (body parsing), como os cookies serão tratados e mais.

Note também que a última linha do segundo bloco diz ao Express para acessar os objetos estáticos a partir de uma pasta /public/, mas no navegador elas aparecerão como se estivessem na raiz do projeto. Por exemplo, mesmo se a pasta images fica em C:/node/web-app/public/images ela será acessada em http://localhost:3000/images

Estes são manipuladores de erros para desenvolvimento e produção (além dos 404). Não vamos nos preocupar com eles agora, mas resumidamente você tem mais detalhes dos erros quando está operando em desenvolvimento.

Uma parte importantíssima do Node é que basicamente todos os módulos exportam um objeto que pode ser facilmente chamado em qualquer lugar no código. Nosso app.js exporta seu objeto app.

OK! Vamos em frente, agora mexendo com persistência de dados.

#3 – Preparando o banco de dados

Agora vamos deixar nosso editor de texto um pouco de lado e voltar ao prompt de comando. Na verdade vamos primeiro usar nosso navegador para acessar o site oficial do MongoDB e baixar o Mongo, na versão Community Server. Esta é a versão gratuita e mais utilizada do MongoDB.

Clique no link de download e busque a versão de produção mais recente para o seu sistema operacional. Baixe o arquivo e, no caso do Windows, rode o executável que extrairá os arquivos na sua pasta de Arquivos de Programas, seguido de uma pasta server/versão, o que é está ok para a maioria dos casos. Note que não há instalação do MongoDB, mas sim apenas uma extração de arquivos.

Pelo prompt de comando, entre na subpasta bin que fica dentro da pasta de instalação do seu MongoDB e digite o comando abaixo, substituindo o caminho passado ao executável pelo caminho até a pasta data do seu projeto (que você pode criar agora, caso ainda não tenha feito). Repare que em ambientes Unix, o executável deve ser chamado como ./mongod, sendo que no Windows é apenas mongod, como abaixo.

Isso irá iniciar o servidor do Mongo, o que pode demorar um pouco na primeira vez. Uma vez que o prompt pare de correr texto e não tenha parado em um erro, está pronto, o servidor está executando corretamente. Na pasta data do seu projeto você vai ver que foram criados uma série de arquivos. Caso esteja usando Git, para que estes arquivos não vão parar no repositório (o que seria uma má prática), inclua a palavra ‘data’ (sem aspas) no seu arquivo .gitignore que deve estar na raiz do projeto.

Agora abra outro prompt de comando (o outro ficará executando o servidor) e novamente dentro da pasta bin do Mongo, digite o comando abaixo para abrir o Mongo Shell, um client de linha de comando para MongoDB:

Se você olhar no prompt onde o servidor do Mongo está rodando, verá que uma conexão foi estabelecida. mongod é o executável do servidor, e mongo é o executável de cliente, que você acabou de conectar. Note que não precisamos informar nenhuma configuração, já que nosso server de desenvolvimento não possui senha e está rodando na porta padrão (27017).

Opcionalmente você pode usar ferramentas visuais como MongoDB Compass, que particularmente eu gosto de utilizar e que ensino no vídeo abaixo.

 

No console do cliente Mongo Shell que acabou de conectar ao banco de dados, digite:

Agora estamos usando a base “web-app.” No entanto, ela somente será criada de verdade quando adicionarmos registros nela, o que faremos a partir do próprio cliente para exemplificar.

Uma de minhas coisas favoritas sobre MongoDB é que ele usa JSON como estrutura de dados, o que significa curva de aprendizagem zero para quem já conhece o padrão que é a base dos objetos JavaScript.

Vamos adicionar um registro à nossa coleção (o equivalente do Mongo às tabelas do SQL). Para este tutorial teremos apenas uma coleção de usuários e emails em nossa base, sendo o nosso formato de dados como abaixo:

Para cadastrar um usuário com o formato acima, basta usarmos o comando insert.

Uma coisa importante aqui: “db” é a base de dados na qual estamos conectados no momento, que um pouco antes havíamos definido como sendo “web-app”. A parte “users” é o nome da nossa coleção, que passará a existir assim que adicionarmos um documento JSON nela. Tecle Enter para que o comando seja enviado ao servidor. Se tudo deu certo, você receberá um WriteResult (resultado de escrita) com o número de documentos inseridos na base (nInserted).

Para ver se o registro foi parar no banco corretamente, vamos fazer um find na coleção users:

O pretty() no final do comando find() é para identar o resultado, que retornará como abaixo. Repare que foi gerado um campo _id que é a chave primária para os documentos do MongoDB e que é criado automaticamente.

Claro, o seu _id vai ser diferente desse, uma vez que o Mongo irá gerá-lo automaticamente. Isto é tudo que precisamos saber de MongoDB no momento, o que me parece bem fácil, aliás! Para saber mais sobre o MongoDB, consulte este guia de estudos!

Agora vamos adicionar mais alguns registros no seu console Mongo Shell:

Nesse exemplo passei um array com vários objetos para nossa coleção. Usando novamente o comando db.users.find().pretty() irá mostrar que todos foram salvos no banco.

Agora sim, vamos interagir de verdade com a web app + MongoDB.

Caso tenha gostado de mexer com MongoDB e queira se aprofundar mais no assunto, recomendo o curso que criei, que você pode conhecer clicando no banner abaixo:

Curso Node.js e MongoDB

#4 – Conectando no Mongo com Node

Vamos começar construindo uma página que mostre os registros de usuários que temos no nosso banco de dados (lembra-se que no trecho anterior eu adicionei alguns registros manualmente?). Meu objetivo agora é que você consiga criar um HTML com a seguinte aparência, considerando que esses dados vieram do banco:

Nada muito avançado, apenas uma lista de usuários com um link para lhes enviar um email. Na verdade nesta etapa do tutorial meu objetivo é lhe ensinar como ler e escrever no MongoDB a partir do Node.js, não vamos criar um site completo e/ou complexo.

Primeiramente, vamos criar um novo arquivo chamado db.js na raiz da nossa aplicação Express (web-app). Esse arquivo será o responsável pela conexão e estrutura do nosso banco de dados, usando o ORM Mongoose. Adicione estas duas linhas:

Estas linhas carregam o objeto Mongoose (que já havíamos deixado instalado na etapa de dependências no início do tutorial) e com ele fazemos a conexão em nosso banco de dados localhost, sendo 27017 a porta padrão do MongoDB.

Na sequência, ainda no db.js, adicione as seguintes linhas:

Aqui definimos a estrutura da nossa coleção users e exportamos um objeto contendo o Mongoose e a estrutura (schema) da nossa coleção de usuários, para que possamos usar este objeto em outras partes da aplicação.

A seguir, vamos modificar a nossa rota para que ela mostre dados vindos do banco de dados, usando esse db.js que acabamos de criar. Abra o arquivo /routes/index.js no seu editor de texto e modifique a rota que está lá e que hoje renderiza uma index vazia para que fique como abaixo:

OK … aqui compliquei um pouco as coisas.

router.get define que estamos esperando requisições HTTP GET no path (caminho) /.

O comando require está voltando uma pasta e carregando o conteúdo do arquivo db.js (extensão desnecessária) que, por sua vez, está carregando a conexão com o banco de dados (via Mongoose) e o esquema da coleção de users.

db.Mongoose.model carrega a coleção users e o esquema de usuários dela. Usamos essa coleção para dar um find por todos usuários (filtro vazio = {}). O lean() é opcional aqui, mas uma boa prática de performance, para retornar um JSON text-plain ao invés de objetos Mongoose complexos.

O comando exec executa a consulta em si, retornando um array docs, que contém os resultados da pesquisa. Por fim, apenas mandei esses docs serem renderizados na view users com res.render.

Repare que usei duas palavras reservadas do JavaScript que talvez sejam novidade para você: async e await. O async antes da função indica que a mesma é assíncrona, algo necessário para lidar com banco de dados. Já o await diz que, de maneira simplista, somente a execução deve seguir para a linha de baixo depois que o retorno do banco for concluído. Falo mais disso neste vídeo.

 

Agora vamos editar a nossa /views/index para listar os usuários. Entre na pasta views e crie um arquivo users.ejs. Então edite o HTML para que fique desse jeito:

Aqui estamos dizendo que o objeto docs, que será retornado pela rota que editamos no passo anterior, será iterado com um forEach e seus objetos utilizados um-a-um para compor uma lista HTML não-ordenada com seus emails e senhas.

Isto é o bastante para a listagem funcionar. Salve o arquivo e reinicie o servidor Node.js. Ainda se lembrar de como fazer isso? Abra o prompt de comando, derrube o processo atual (se houver) com Ctrl+C e depois:

Agora abra seu navegador, acesse http://localhost:3000/e maravilhe-se com o resultado.

Se você viu a página acima é porque sua conexão com o banco de dados está funcionando!

Agora vamos finalizar nosso projeto!

#5 – Escrevendo no banco

Salvar dados em um banco de dados não é algo particularmente difícil. Essencialmente precisamos definir uma rota para receber um POST, ao invés de um GET.

Primeiro vamos criar a nossa tela de cadastro de usuário com dois clássicos e horríveis campos de texto à moda da década de 90. Dentro da pasta views, crie um user.ejs com o seguinte HTML dentro:

Agora vamos voltar à pasta routes e abrir o nosso arquivo de rotas, o index.js onde vamos adicionar duas novas rotas. A primeira, é a rota GET para acessar a página user.ejs quando acessarmos /user no navegador:

Se você reiniciar seu servidor Node e acessar http://localhost:3000/user verá a página abaixo:

Enquanto que ao digitar um endereço na barra do navegador ou clicar em um link você faz uma requisição HTTP GET, quando você clica em um botão de salvar em um formulário você estará fazendo uma requisição POST. Se você preencher esse formulário agora e clicar em salvar, dará um erro 404. Isso porque ainda não criamos a rota que receberá o POST desse formulário!

Aqui o processo não é muito diferente do que fizemos para listar os usuários, ou seja, criar uma rota para que, quando acessada (POST nesse caso) nós chamaremos o objeto de banco para salvar os dados nele. A rota, nesse caso, é /user novamente, mas a função será diferente.

Então abra novamente o arquivo /routes/index.js e adicione o seguinte bloco de código logo após as outras rotas e antes do modules.export:

Obviamente no mundo real você irá querer colocar validações, tratamento de erros e tudo mais, eu apenas coloquei um try/catch para em caso de erro, o próximo middleware do Express assumir o tratamento do mesmo (tem um middleware configurado pra erro no app.js). Aqui, apenas carregamos o objeto db onde temos a conexão com o Mongoose, pegamos o username e email vindos no corpo da requisição (foram postados pelo formulário, lembra?) e depois carregamos o model da coleção de usuários.

Então entram as novidades: uma vez com o model carregado, podemos criar novos objetos do mesmo tipo, populando seus campos e depois mandando salvar os mesmos. A save() não retorna nada de especial e se tudo correu bem, retornamos o fluxo à tela de listagem de usuários, onde devemos ver um novo usuário cadastrado.

Com isso estamos oficialmente lendo e escrevendo dados em um banco MongoDB a partir de uma aplicação Node.js com Express, EJS e Mongoose. Se conseguiu executar este tutorial até aqui, você é o que chamam atualmente de desenvolvedor full stack. Ok, não é um BOM dev full stack, mas isso o tempo resolve. 🙂

Se for colocar um projeto em produção, você pode fazê-lo usando a Umbler, a Heroku, a AWS ou a Digital Ocean. Tirando a primeira que dispensa tutoriais, as demais tem tutoriais aqui no blog.

Curtiu o post? Então clica no banner abaixo e dá uma conferida no meu livro sobre programação web com Node.js!

Olá, tudo bem?

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