Tutorial NodeJS com MongoDB

node-js-mongodb

Atualizado em 16/04/2017!

Têm algum tempo que não tenho mais achado ASP.NET tão incrível assim. Não que a tecnologia não seja boa, mas depois de quase 10 anos usando ela, comecei a questionar algumas de suas características, alguns dos motivos pelos quais sempre usei-a em meus projetos e decidi que estava na hora (mais que na hora, na verdade) de testar algo novo para meus projetos web.

Esse post trata de NodeJS, uma plataforma que eu já havia testada há mais de 1 ano e que não tinha compreendido sua finalidade até que conheci alguns frameworks criados sobre a plataforma, como o Express, que seria o subtópico deste post. NodeJS por si só pode criar qualquer coisa, assim como a linguagem C, e ao mesmo tempo você fica com preguiça de usar porque é muito “cru” (na minha opinião), assim como a linguagem C. Mas quando conheci Express, e espero que vocês sintam o mesmo, minha “vida” mudou como programador. Era o que estava buscando.

No momento que escrevo este post, um tutorial bem bacana (modéstia à parte), sobre NodeJS e MongoDB, estou reescrevendo todo o site do meu projeto Busca Acelerada para que ele fique mais rápido, consumindo menos recursos (consequentemente em um servidor menor) e sem precisar usar o Windows no servidor (cujo custo de licença encarece minha infraestrutura). Também tive a oportunidade de trabalhar em outro projeto que está em produção tem mais de um ano, tendo inclusive já feito refatorações nele, com milhares e usuários por mês usando a plataforma, o BuildIn, bem como outro projeto mais recente chamado Só Famosos.

O resultado com meus projetos está ficando excelente e fiquei tão feliz com o que tenho aprendido nos últimos meses usando a plataforma que resolvi compartilhar com meus leitores, para que tenham essa experiência também.

Eu sei, NodeJS e MongoDB é um tanto hipster demais, mas cara, eu tenho um Mac e um iPhone, o que você esperava de mim?

Neste artigo você vai ver:

  1. Instalando
  2. Olá Mundo
  3. Criação e acesso ao banco
  4. Escrevendo no banco

PARTE 1: Instalando!

Nesta parte vamos instalar e configurar o ambiente necessário para o restante do tutorial.

Passo 1: Instalar NodeJS

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. Esse executável irá instalar o NodeJS e o NPM, que é o gerenciador de pacotes do Node.

Uma vez com o NPM instalado, vamos instalar dois módulos que serão úteis mais pra frente. Crie uma pasta para guardar os seus projetos Node no computador (recomendo C:\node) e dentro dela, via terminal de comando com permissão de administrador, rode os dois comandos abaixo, um depois do outro:

Passo 2: Instale um editor de texto (ou não)

Você pode programar com NodeJS em qualquer editor de texto, incluindo o bloco de notas, Nodepad++, Sublime e vários outros, incluindo os excelentes Visual Studio e Visual Studio Code.

Para quem quiser usar o Visual Studio, você pode baixar a versão gratuita dele (Community, bem completa) neste link. Funciona apenas em Windows (com preview para Mac), e caso já tenha ele instalado, certifique-se de possuir a última versão (2017) que é a que funciona com Node. Caso vá utilizar a 2015, é melhor instalar também o Update 3 que corrige muitos bugs e obrigatoriamente o plugin de Node.js neste link.

Caso esteja usando Mac ou Linux (ou mesmo um Windows modesto), tem o Visual Studio Code, uma versão mais leve e com (bem) menos recursos mas que funciona bem com Node (suporte nativo), disponível neste link. É a ferramenta que eu recomendo usar.

Caso Não queira instalar nada, nem esquenta, abre um editor de texto qualquer e já era! 😀

Passo 3: Crie um projeto Express

Caso esteja usando o Visual Studio, você pode ir no menu File e criar um novo projeto do tipo Node.js Express, que vai ser uma das novas opções listadas lá.

No entanto, caso não esteja usando Visual Studio, você pode rapidamente criar a estrutura básica de um projeto Express via linha de comando, da seguinte maneira (aqui considero que você salva seus projetos na pasta C:\node):

Aperte Enter e você verá algo parecido com o código abaixo:

E depois mande instalar as dependências:

Para executar essa aplicação criada em Express, pelo Visual Studio, basta clicar no botão padrão de Run (o play), já no VS Code você deve acessar a aba lateral Debug e depois clicar no botão de Run. Caso esteja usando qualquer outra ferramenta (ou mesmo nenhuma), volte para o terminal de linha de comando e, dentro da pasta do projeto, digite:

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

Capture

Passo 4: Edite as dependências

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. Se você abri-lo no bloco de notas, verá algo semelhante à isso:

É um arquivo JSON básico. Precisamos alterar umas pequenas coisas nele, especificamente adicionar dependências para que o MongoDB funcione com essa aplicação e para usarmos o view-engine EJS, que considero melhor que o Jade, para lidar com a construção da interface HTML. As alterações devem deixar o seu arquivo com a seguinte aparência na seção de “dependencies”:

Passo 5: Instale as dependências

Agora que definimos no package.json as dependências que nossa aplicação possui, estamos prontos para começar. Ou quase.

Por padrão o Express cria páginas dentro da pasta views com a extensão .jade, que é a view-engine padrão do Express. Aqui nós trocamos ela pela EJS, que é mais fácil de aprender uma vez que usa HTML comum com um pouco de Javascript para compor a interface. Sendo assim, renomeie a extensão da página index.jade para index.ejs e dentro coloque o seguinte código HTML:

Essa troca de view engine (Jade para EJS) requer uma pequena alteração no arquivo app.js que fica dentro do seu projeto NodeJS. Busque pelo seguinte trecho que define a view engine a ser utilizada:

E troque por esse trecho:

Agora que definimos nossas dependências estamos prontos para seguir em frente. Volte ao seu prompt de comando, cd para sua pasta nodetest1 e digite:

Muitos pacotes aparecerão no console porque o NPM (que é o gerenciador de pacotes do NodeJS) está lendo o arquivo JSON e instalando as dependências necessárias. Uma vez que ele termine, você verá uma pasta node_modules dentro da pasta do seu projeto, com todas as dependências dentro.

Agora você tem um aplicação pronta para funcionar. Mas antes de executarmos ela novamente, vamos fazer uma rápida mudança para deixá-la preparada para o banco de dados que usaremos depois. Ainda em seu diretório nodetest1, digite:

Nesta pasta vamos armazenar nossos dados do MongoDB. Se este diretório não for criado, teremos problemas mais tarde. Para testar nossa aplicação novamente, digite:

Capture

Tudo funcionando! Você acaba de terminar de montar seu primeiro webserver NodeJS com a engine Express e o pré-processador HTML EJS. Não foi tão difícil, certo?

Parte 2: Olá Mundo!

Vamos abrir agora o arquivo app.js, que fica dentro do diretório da sua aplicação NodeJS (nodetest1 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 como uma combinação de models e controllers nesta configuração – elas direcionam o tráfego e contém também alguma lógica de programação (embora você consiga, se quiser, fazer um MVC mais puro se desejar). Quando criamos o projeto Express, ele criou estes códigos JS pra gente e vamos ignorar a rota ‘users’ por enquanto e nos focar no index, controlado pelo arquivo c:\node\nodetest1\routes\index.js.

Na sequência você deve ver:

Este é bem importante. Ele instancia o Express e associa nossa variável app à ele. A próxima seção usa esta variável para configurar coisas do Express (que inclusive já modificamos antes, para trocar o Jade pelo EJS).

Isto diz ao app onde ele encontra suas views, qual engine usar para renderizar as views (EJS) e chama alguns métodos para fazer com que as coisas funcionem. Note também que esta linha final 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, a pasta images fica em c:\node\nodetest1\public\images mas é 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 master exporta seu objeto app.

Agora mãos à obra, e nada de Olá Mundo a partir de agora. Ao invés disso, vamos aproveitar esta oportunidade para aprender um pouco mais de rotas e dar uma olhada em como o EJS funciona para juntar as páginas.

Vamos começar adicionando uma nova diretiva app.use no app.js. Encontre a seção que se parece com isso:

Esta diretiva diz ao Express quais arquivos de rotas usar. O normal e mais aconselhável é criar diferentes arquivos de rota para lidar com o CRUD de cada entidade e/ou view do sistema. Aqui, no entanto, para manter tudo simples, vamos usar apenas a rota index, logo você pode ignorar a rota users.

Lembre-se que o Express gerou automaticamente a variável “routes” e apontou para a rota index. Nós vamos adicionar um método “helloworld” à rota que irá renderizar uma página diferente do que a default. No seu editor de texto, abra a pasta routes, encontre o index.js, e abra-o. Ele se parecerá com isso:

Basicamente estamos requisitando as funcionalidades do Express, então anexando uma variável “router” ao método de roteamento do Express, então definindo que quando uma requisição HTTP GET chegar na raiz do website, uma função será chamada. Finalmente, exportamos nossa função de roteamento de volta para nosso app.

Você pode facilmente clonar a função get para outra página, que é o que vou fazer aqui. No final do arquivo, exatamente acima da linha module.exports, adicione este código:

E isto é tudo que necessitamos para manipular o roteamento de URLs, faltando apenas a página helloworld que referenciamos em nosso res.render. É aqui que o EJS entra. Abra sua pasta views e vá até o arquivo index.ejs e copie-o com o nome de helloworld.ejs. Mude seu conteúdo HTML para algo diferente do index.ejs, salve o arquivo e vá até o seu prompt de comando, Ctrl+C para derrubar o servidor (se ele já estiver rodando) e então digite “npm start” para iniciá-lo novamente.

Algo digno de nota é que mudanças nos EJS não necessitam reiniciar o servidor, mas toda vez que mudar um arquivo JS você precisará reiniciá-lo.

Com o servidor reiniciado, acesse http://localhost:3000/helloworld no seu navegador e você verá a nova página que criou, que atende à rota especificada:

browsershot2

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

Parte 3: Criação e acesso ao banco

Passo 1: Instalar o MongoDB

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. Clique no link de download e busque a versão de produção mais recente (3.2?) 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, mas que eu preferi colocar em C:\Mongo.

Passo 2: Executar mongod e mongo

Dentro da pasta do seu projeto Node, que aqui chamei de nodetest1, deve existir uma subpasta data. Pelo prompt de comando, entre na subpasta bin dentro da pasta de instalação do seu MongoDB e digite:

Isso irá iniciar o servidor do Mongo, o que pode demorar um pouco na primeira vez. Uma vez que apareça no prompt “[initandlisten] waiting for connections on port 27017”, está pronto, o servidor está executando corretamente.

Agora abra outro prompt de comando (o outro ficará executando o servidor) e novamente dentro da pasta bin do Mongo, digite:

Você deverá ver algo parecido com isso:

Adicionalmente, 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. Opcionalmente você pode usar ferramentas visuais como Studio3T, que particularmente eu gosto de utilizar (antiga MongoChef, gratuita).

Passo 3: Criando uma base de dados

No console do cliente mongo, digite:

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

Passo 4: Inserindo alguns dados

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. Caso não seja o seu caso, terá que buscar algum tutorial de JSON na Internet antes de prosseguir.

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

O atributo _id pode ser definido manualmente ou omitido, onde neste caso o próprio Mongo gera um guid pra você. No seu cliente mongo, digite:

Uma coisa importante aqui: “db” é a base de dados na qual estamos conectados no momento, que um pouco antes havíamos definido como sendo “nodetest1”. A parte “usercollection” é o nome da nossa coleção, que passará a existir assim que adicionarmos um objeto JSON nela. Tecle Enter para que o comando seja enviado ao servidor. Se tudo deu certo, nada acontecerá. Para ver se o registro foi parar no banco, digite:

O pretty() no final do comando find() é para identar o resultado, que retornará:

Claro, o seu _id pode 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, Google!

Agora vamos adicionar mais alguns registros no seu console mongo:

Nesse exemplo passei um array com vários objetos para nossa coleção. Usando novamente o comando db.usercollection.find().pretty() irá mostrar que todos foram salvos no banco. Agora sim, vamos interagir de verdade com o web server + MongoDB.
Passo 5: 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 post 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 segunda parte do tutorial meu objetivo é lhe ensinar como ler e escrever no MongoDB a partir do NodeJS, não vamos criar um site completo.

Primeiramente, vamos criar um novo arquivo chamado db.js na raiz da nossa aplicação Express (nodetest1). 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 da Parte 1 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 de usuários (um tanto auto explicativo) e exportamos um objeto contendo o Mongoose e a estrutura 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.

Passo 6: Exibindo os dados do mongo

Abra o arquivo C:\node\nodetest1\routes\index.js no seu editor de texto. Dentro dele temos a rota index e a rota helloworld, que criamos para teste anteriormente. Vamos adicionar uma terceira rota, da seguinte maneira:

OK … aqui compliquei um pouco as coisas.

router.get define a nova rota que estou criando com o nome de userlist.

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 usuários.

db.Mongoose.model carrega a coleção e usuários com o esquema deles. 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, passando para o callback um objeto e (erro) e um objeto docs, que contém os resultados da pesquisa. Por fim, apenas mandei esses docs serem renderizados na tela com res.render.

Agora vamos arrumar a nossa view para listar os usuários. Entre na pasta C:\node\nodetest1\views\ e crie um arquivo userlist.ejs. Então edite o HTML para que fique desse jeito:

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

Isto é o bastante para a listagem funcionar. Salve o arquivo e reinicie o servidor NodeJS. 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/userlist e maravilhe-se com o resultado.

Capture

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

No entanto, eu sei que nem sempre tudo é um mar de rosas. É muito fácil em uma linguagem como JS acontecerem erros principalmente devido à código mal digitado. Sendo assim, vamos criar uma página para onde os erros podem ser direcionados e possamos descobrir o que pode estar acontecendo caso o seu teste anterior não tenha sido bem sucedido.

Primeiro, abra sua pasta views e crie um arquivo error.ejs, com o seguinte código dentro:

Agora toda vez que seu código disparar um erro, essa página será exibida com os detalhes do mesmo, ao menos durante os seus testes (debug mode).

Agora vamos finalizar nosso projeto!

Parte 4 – 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.

Passo 1: Criando sua entrada de dados

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 newuser.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 newuser quando acessarmos /newuser no navegador:

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

Capture

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!.

Passo 2: Crie as suas funções de banco

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

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. 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 função de callback do save() é disparada após o mesmo ter sido concluído e, em caso de erro, imprimimos no console do NPM o erro, caso contrário, retornamos o fluxo à tela de listagem de usuários, onde devemos ver um novo usuário cadastrado.

Capture

Com isso estamos oficialmente lendo e escrevendo dados em um banco MongoDB a partir de uma aplicação NodeJS 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. 🙂

E aí, o que achou? Curtiu desenvolver com NodeJS e MongoDB?

Se for colocar um projeto em produção, em servidor Windows, dê uma olhada nesse tutorial aqui, pois eu passei maus bocados pra fazer funcionar.

Agora, se quiser aprender como fazer uma API/webservice com NodeJS, leia esse post aqui.

Recentemente eu dei um workshop com o mesmo conteúdo desse post. Os slides você confere abaixo:

O que achou desse artigo?
[Total: 1 Média: 5]