Victor Hazin é um engenheiro de software e professor com mais de 10 anos de experiência. Ele possui graduação e mestrado em Ciências da Computação pela UFPE.
2. Victor Hazin
Engenheiro de Software do CESAR (+ 7 anos)
Professor da FBV Devry (+3 anos)
Graduação e Mestrado em Ciências da
Computação (CIn-UFPE) (2010 e 1013)
6. Presentation layer Business Logic layer Data Access layer
NodeJS
and
NodeJS Modules
Single page Apps
using Javascript Frameworks
(AngularJS)
MongoDB
JSON documents
REST API
serving JSON
7. Presentation layer Business Logic layer Data Access layer
NodeJS Modules
NodeJS
BaaS
MongoDB
UI
Framework
Bootstrap
JS
Framework
Angular JS
JS CSS HTML
8. Presentation layer Business Logic layer Data Access layer
NodeJS Modules
NodeJS
BaaS
MongoDB
UI
Framework
Bootstrap
JS
Framework
Angular JS
JS CSS HTML
Back-end
12. “é uma plataforma para aplicações JavaScript
criada por Ryan Dahl sob o ambiente de execução
JavaScript do Chrome.
É possível utilizar bibliotecas desenvolvidas pela
comunidade através de seu gerenciador de
pacotes chamado npm”
19. Configurando o ambiente de
desenvolvimento
Adicionar uma variável de ambiente NODE_ENV no sistema operacional.
Linux ou OSX:
1. acessar com um editor de texto qualquer e em modo super user (sudo) o arquivo .bash_profile
ou .bashrc
2. adicionar o seguinte comando: export NODE_ENV=’development
No Windows:
1. Clique com botão direito no ícone Meu Computador e selecione a opção Propriedades
2. Clique em Configurações avançadas do sistema.
3. Na janela seguinte, acesse a aba Avançado e clique no botão Variáveis de Ambiente.
4. No campo Variáveis do sistema clique no botão Novo.
5. Em nome da variável digite NODE_ENV e em valor da variável digite: development.
22. npm
• Gerenciador de pacotes do node.js;
• Similar ao Maven do Java ou ao Gems do Ruby;
• Foi integrado ao instalador do Node.js a partir da versão
0.6.
23. npm install nome_do_módulo: instala um módulo no projeto;
npm install -g nome_do_módulo: instala um módulo global;
npm install nome_do_módulo --save: instala o módulo no projeto,
atualizando o package.json na lista de dependências;
npm list: lista todos os módulos do projeto;
npm list -g: lista todos os módulos globais;
Comandos Principais (npm)
24. npm remove nome_do_módulo: desinstala um módulo do projeto;
npm remove -g nome_do_módulo: desinstala um módulo global;
npm update nome_do_módulo: atualiza a versão do módulo;
npm update -g nome_do_módulo: atualiza a versão do módulo global;
Comandos Principais (npm)
25. Comandos Principais (npm)
npm -v: exibe a versão atual do npm;
npm adduser nome_do_usuário: cria uma conta no npm, através do site
https://npmjs.org.
npm whoami: exibe detalhes do seu per l público npm (é necessário
criar uma conta antes);
npm publish: publica um módulo no site do npm (é necessário ter uma
conta antes).
28. node modules
Todo projeto Node.js é chamado de módulo;
O termo módulo, biblioteca e framework possuem o
mesmo significado (na prática);
O termo módulo surgiu do conceito de que a arquitetura do
Node.js é modular;
Todo módulo é acompanhado de um arquivo descritor
(package.json).
31. CommonJS
• O Node.js utiliza nativamente o padrão CommonJS para
organização e carregamento de módulos;
• Para criar um código Javascript que seja modular e
carregável pelo require, utilizam-se as variáveis globais:
exports ou module.exports.
32. hello.js human.js
Em hello.js carregamos uma
única função modular;
Em human.js é carregado
um objeto com funções
modulares.
app.js
module.exports = function(msg) {
console.log(msg);
};
exports.hello = function(msg) {
console.log(msg);
};
var hello = require(’./hello’);
var human = require(’./human’);
hello(’Olá pessoal!’);
human.hello(’Olá galera!’);
34. 1. Crie uma pasta com o nome: node-exemplos
2. Crie um arquivo com o nome retangulo.js
3. Execute execute a aplicação com o comando: node retangulo.js
var rect = {
perimeter: function (x, y) {
return (2*(x+y));
},
area: function (x, y) {
return (x*y);
}
};
function solveRect(l,b) {
console.log("Solving for rectangle with l = " + l + " and b = " + b);
if (l < 0 || b < 0) {
console.log("Rectangle dimensions should be greater than zero: l = "
+ l + ", and b = " + b);
}
else {
console.log("The area of a rectangle of dimensions length = "
+ l + " and breadth = " + b + " is " + rect.area(l,b));
console.log("The perimeter of a rectangle of dimensions length = "
+ l + " and breadth = " + b + " is " + rect.perimeter(l,b));
}
}
solveRect(2,4);
solveRect(3,5);
solveRect(-3,5);
35. 1. Crie um novo arquivo com o nome retangulo-1.js
exports.perimeter = function (x, y) {
return (2*(x+y));
}
exports.area = function (x, y) {
return (x*y);
}
2. Crie um novo arquivo com o nome solucao-1.js
var rect = require('./retangulo-1');
function solveRect(l,b) {
console.log("Solving for rectangle with l = " + l + " and b = " + b);
if (l < 0 || b < 0) {
console.log("Rectangle dimensions should be greater than zero: l = "
+ l + ", and b = " + b);
}
else {
console.log("The area of a rectangle of dimensions length = "
+ l + " and breadth = " + b + " is " + rect.area(l,b));
console.log("The perimeter of a rectangle of dimensions length = "
+ l + " and breadth = " + b + " is " + rect.perimeter(l,b));
}
}
solveRect(2,4);
solveRect(3,5);
solveRect(-3,5);
3. Execute execute a aplicação com o comando: node solucao-1
41. module.exports = function(x,y,callback) {
try {
if (x < 0 || y < 0) {
throw new Error("Rectangle dimensions should be greater than zero: l = "
+ x + ", and b = " + y);
}
else
callback(null, {
perimeter: function () {
return (2*(x+y));
},
area:function () {
return (x*y);
}
});
}
catch (error) {
callback(error,null);
}
}
1. Crie um arquivo com o nome retangulo-2.js
42. var rect = {
perimeter: function () {
return (2*(x+y));
},
area:function () {
return (x*y);
}
module.exports = function(x,y,callback) {
try {
if (x < 0 || y < 0) {
throw new Error("Rectangle dimensions should be greater than zero: l = "
+ x + ", and b = " + y);
}
else
callback(null, rect);
}
catch (error) {
callback(error,null);
}
}
1. Crie um arquivo com o nome retangulo-2.js
43. var rect = require('./retangulo-2');
function solveRect(l,b) {
console.log("Solving for rectangle with l = "
+ l + " and b = " + b);
rect(l,b, function(err,rectangle) {
if (err) {
console.log(err);
}
else {
console.log("The area of a rectangle of dimensions length = "
+ l + " and breadth = " + b + " is " + rectangle.area());
console.log("The perimeter of a rectangle of dimensions length = "
+ l + " and breadth = " + b + " is " + rectangle.perimeter());
}
});
};
solveRect(2,4);
solveRect(3,5);
solveRect(-3,5);
2. Crie um novo arquivo com o nome solucao-2.js
3. Execute execute a aplicação com o comando: node solucao-2
44. var argv = require('yargs')
.usage('Usage: node $0 --l=[num] --b=[num]')
.demand(['l','b'])
.argv;
var rect = require('./retangulo-2');
function solveRect(l,b) {
console.log("Solving for rectangle with l = "
+ l + " and b = " + b);
rect(l,b, function(err,rectangle) {
if (err) {
console.log(err);
}
else {
console.log("The area of a rectangle of dimensions length = "
+ l + " and breadth = " + b + " is " + rectangle.area());
console.log("The perimeter of a rectangle of dimensions length = "
+ l + " and breadth = " + b + " is " + rectangle.perimeter());
}
});
};
solveRect(argv.l,argv.b);
1. Crie um novo arquivo com o nome solucao-3.js
3. Execute execute a aplicação com o comando: node solucao-3 --l=5 --b=6
2. Instale o yargs com o comando: npm install yargs --save
46. Node.js é multi-protocolo: HTTP, HTTPS, FTP, SSH, DNS,
TCP, UDP, WebSockets;
Toda aplicação web necessita de um servidor para
disponibilizar todos os seus recursos;
Na prática, com o Node.js você desenvolve uma aplicação
middleware;
Além de programar as funcionalidades da sua aplicação,
você também programa códigos de configuração de
infraestrutura da sua aplicação.
48. Esses módulos já são preparados para lidar com desde
uma infraestrutura mínima até uma mais enxuta;
E permitem trabalhar com diferentes arquiteturas e padrões.
• RESTFul;
• Padrão MVC;
• Model-View-Controller
• e conexões real-time utilizando WebSocket;
49. var http = require('http');
var server = http.createServer(function(request, response){
response.writeHead(200, {"Content-Type": "text/html"});
response.write("<h1>Hello World!</h1>");
response.end();
});
server.listen(3000);
1. Crie um novo arquivo com o nome hello_server.js
2. Execute execute a aplicação com o comando: node hello_server.js
3. No seu navegador acesse o endereço http://localhost:3000
50. var http = require('http');
var server = http.createServer(function(request, response){
response.writeHead(200, {"Content-Type": "text/html"});
response.write("<h1>Hello World!</h1>");
response.end();
});
server.listen(3000);
O require(‘http') carrega o módulo http padrão do node
51. var http = require('http');
var server = http.createServer(function(request, response){
response.writeHead(200, {"Content-Type": "text/html"});
response.write("<h1>Hello World!</h1>");
response.end();
});
server.listen(3000);
A função http.createServer() é responsável por levantar um
servidor;
O callback function(request, response) só é executada
quando o servidor recebe uma requisição.
Event loop constantemente verifica se o servidor foi
requisitado;
Quando uma requisição é recebida, é emitido um evento para
que seja executado o callback.
52. var http = require('http');
var server = http.createServer(function(request, response){
response.writeHead(200, {"Content-Type": "text/html"});
response.write("<h1>Hello World!</h1>");
response.end();
});
server.listen(3000, function(){
console.log(’Servidor Hello World rodando!’);
});
Notificar quando servidor está de pé, mudamos a linha
server.listen para receber como parâmetro uma função que
faz esse aviso.
53. var http = require('http');
var server = http.createServer(function(request, response){
response.writeHead(200, {"Content-Type": "text/html"});
response.write("<h1>Hello World!</h1>");
response.end();
});
server.listen(3000);
Os parâmetros da requisição http podem ser obtidos através
da variável request:
• request.headers;
• request.body;
Já os dados do cabeçalho HTML podem ser atribuídos usando
o parâmetro response:
• response.writeHead(200, {"Content-Type": “text/html"});
• response.write("<h1>Hello World!</h1>");
54. Trabalhando com Rotas
var http = require(’http’);
var server = http.createServer(function(request, response){
response.writeHead(200, {"Content-Type": "text/html"});
if(request.url == "/"){
response.write("<h1>Página principal</h1>");
}else if(request.url == "/bemvindo"){
response.write("<h1>Bem-vindo :)</h1>");
}else{
response.write("<h1>Página não encontrada :(</h1>");
}
response.end();
});
server.listen(3000, function(){
console.log(’Servidor rodando!’);
});
55. Separando o HTML do
JavaScript
var http = require('http');
var fs = require('fs');
var server = http.createServer(function(request, response){
fs.readFile(__dirname + '/index.html', function(erro, html){
response.writeHeader(200, {'Content-Type': 'text/html'});
response.write(html);
response.end();
});
});
server.listen(3000, function(){
console.log('Servidor Rodando…');
});
<!DOCTYPE html>
<html>
<head>
<title>The winter is coming!</title>
</head>
<body>
<h1>Bem vindo ao Norte!</h1>
</body>
</html>
index.html
exercicio_html_javascript.js
57. Implementar um Roteador de
URLs
• Crie 3 arquivos HTML simples: inverno.html, verao.html e erro.html;
• Coloque qualquer conteúdo para cada página HTML;
• Ao digitar no browser o path: /inverno deve renderizar inverno.html;
• Ao digitar no browser o path: /verao deve renderizar verao.html;
• Ao digitar qualquer path diferente de /verao e /inverno deve
renderizar erro.html;
• A leitura dos arquivos HTML deve ser assíncrona;
• A rota principal "/" deve renderizar inverno.html;
59. É um framework web light-weight criado em 2009
que ajuda na organização de sua aplicação web, na
arquitetura MVC no lado do servidor;
express
60. O Express é uma estrutura web de roteamento e
middlewares que tem uma funcionalidade mínima
por si só;
Um aplicativo do Express é essencialmente uma
série de chamadas de funções de middleware.
express
61. Funções de Middleware são funções que tem
acesso:
• Ao objeto de solicitação (req);
• O objeto de resposta (res);
• E a próxima função de middleware no ciclo
solicitação-resposta do aplicativo (next).
express
62. O método HTTP para o qual a função de middleware é
aplicada.
Caminho (rota) para o qual a função de middleware é
aplicada.
A função de middleware.
Argumento de retorno de chamada para a função de
middleware, chamado de "next" por convenção.
Argumento de resposta HTTP para a função de
middleware, chamado de "res" por convenção.
Argumento de solicitação HTTP para a função de
middleware, chamado de "req" por convenção
express
63. O método HTTP para o qual a função de middleware é
aplicada.
Caminho (rota) para o qual a função de middleware é
aplicada.
A função de middleware.
Argumento de retorno de chamada para a função de
middleware, chamado de "next" por convenção.
Argumento de resposta HTTP para a função de
middleware, chamado de "res" por convenção.
Argumento de solicitação HTTP para a função de
middleware, chamado de "req" por convenção
express
64. O método HTTP para o qual a função de middleware é
aplicada.
Caminho (rota) para o qual a função de middleware é
aplicada.
A função de middleware.
Argumento de retorno de chamada para a função de
middleware, chamado de "next" por convenção.
Argumento de resposta HTTP para a função de
middleware, chamado de "res" por convenção.
Argumento de solicitação HTTP para a função de
middleware, chamado de "req" por convenção
express
65. O método HTTP para o qual a função de middleware é
aplicada.
Caminho (rota) para o qual a função de middleware é
aplicada.
A função de middleware.
Argumento de retorno de chamada para a função de
middleware, chamado de "next" por convenção.
Argumento de resposta HTTP para a função de
middleware, chamado de "res" por convenção.
Argumento de solicitação HTTP para a função de
middleware, chamado de "req" por convenção
express
66. O método HTTP para o qual a função de middleware é
aplicada.
Caminho (rota) para o qual a função de middleware é
aplicada.
A função de middleware.
Argumento de retorno de chamada para a função de
middleware, chamado de "next" por convenção.
Argumento de resposta HTTP para a função de
middleware, chamado de "res" por convenção.
Argumento de solicitação HTTP para a função de
middleware, chamado de "req" por convenção
express
67. O método HTTP para o qual a função de middleware é
aplicada.
Caminho (rota) para o qual a função de middleware é
aplicada.
A função de middleware.
Argumento de retorno de chamada para a função de
middleware, chamado de "next" por convenção.
Argumento de resposta HTTP para a função de
middleware, chamado de "res" por convenção.
Argumento de solicitação HTTP para a função de
middleware, chamado de "req" por convenção
express
68. O método HTTP para o qual a função de middleware é
aplicada.
Caminho (rota) para o qual a função de middleware é
aplicada.
A função de middleware.
Argumento de retorno de chamada para a função de
middleware, chamado de "next" por convenção.
Argumento de resposta HTTP para a função de
middleware, chamado de "res" por convenção.
Argumento de solicitação HTTP para a função de
middleware, chamado de "req" por convenção
express
69. Funções de middleware podem executar as seguintes
tarefas:
• Executar qualquer código;
• Fazer mudanças nos objetos de solicitação e resposta;
• Encerrar o ciclo de solicitação-resposta;
• Chamar a próxima função de middleware na pilha;
• Se a atual função de middleware não terminar o ciclo
de solicitação-resposta, ela precisa chamar next().
express
70. Crie uma pasta para colocar o novo exemplo;
Em seguida no terminal/linha de comando navegue até a
pasta e instale o express:
express
$ npm install express --save
71. Express Hello World
var express = require('express'),
http = require('http');
var hostname = 'localhost';
var port = 3000;
var app = express();
app.use(function (req, res, next) {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end('<html><body><h1>Hello World</h1></body></html>');
});
var server = http.createServer(app);
server.listen(port, hostname, function(){
console.log(`Server running at http://${hostname}:${port}/`);
});
express
$ node intro-express.js
Crie um arquivo chamado intro-express.js
72. Para entregar arquivos estáticos como imagens,
arquivos CSS, e arquivos JavaScript, use a função de
middleware express.static;
Passe o nome do diretório que contém os ativos
estáticos para a função de middleware express.static
para iniciar a entregar os arquivos diretamente;
Por exemplo, use o código a seguir para entregar
imagens, arquivos CSS, e arquivos JavaScript em um
diretório chamado public.
express
73. Agora, é possível carregar os arquivos que estão no
diretório public:
express
app.use(express.static('public'));
http://localhost:3000/images/kitten.jpg
http://localhost:3000/css/style.css
http://localhost:3000/js/app.js
http://localhost:3000/images/bg.png
http://localhost:3000/hello.html
74. Serving Static Content
Crie uma pasta chamada public e coloque dentro dois
arquivos html quaisquer;
var express = require('express');
var hostname = 'localhost';
var port = 3000;
var app = express();
app.use(express.static(__dirname + '/public'));
app.listen(port, hostname, function(){
console.log(`Server running at http://${hostname}:${port}/`);
});
express
76. Representational State Transfer (REST) or RESTful
web services é uma maneira simples de organizar
interações em sistemas independentes.
Proporcionando interoperabilidade entre o sistema
e os diversos dispositivos com acesso a Internet.
77. Os serviços da Web compatíveis com REST
permitem que os sistemas solicitantes acessem e
manipulem representações textuais de recursos
da Web usando um conjunto uniforme e predefinido
de operações stateless.
78. Os princípios fundamentais do REST envolvem separar sua
API em recursos lógicos.
Esses recursos são manipulados usando solicitações
HTTP nas quais o método (GET, POST, PUT, PATCH ou
DELETE) tem um significado específico.
Recursos devem ser substantivos (não verbos!) que fazem
sentido do ponto de vista do quem vai “consumir” a AP
79. Depois da definição dos recursos, é necessário identificar
quais ações se aplicam a eles e como serão mapeados para
a API.
Princípios RESTful fornecem estratégias para lidar com
ações CRUD usando métodos HTTP mapeados, tal como:
• GET /tickets Retorna a lista de bilhetes
• GET /tickets/12 Retorna um bilhete específico
• POST /tickets Cria um novo bilhete
• PUT /tickets/12 Atualiza o bilhete #12
• PATCH /tickets/12 Atualiza parcialmente o bilhete #12
• DELETE /tickets/12 Apaga o bilhete #12
80. A grande vantagem em REST é que se está aproveitando
métodos HTTP existentes para implementar funcionalidades
significativas em apenas um único endpoint /tickets;
Não existem convenções de nomenclatura a seguir e a
estrutura de URL é limpa e clara.
RESPOSTAS SEMPRE EM JSON!!!!
83. O Roteamento refere-se à determinação de como um
aplicativo responde a uma solicitação do cliente por um
endpoint específico;
A solicitação é compostas por uma URI (ou caminho) e um
método de solicitação HTTP específico (GET, POST, e assim
por diante);
Cada rota pode ter uma ou mais funções de manipulação,
que são executadas quando a rota é correspondida.
84. A definição de rotas aceita a seguinte estrutura:
Onde:
app é uma instância do express;
METHOD é um método de solicitação HTTP;
PATH é um caminho no servidor;
HANDLER é a função executada quando a rota é
correspondida.
app.METHOD(PATH, HANDLER)
85. app.get('/', function (req, res) {
res.send('Hello World!');
});
Responde uma requisição GET com Hello
World! na página inicial.
86. app.post('/', function (req, res) {
res.send('Got a POST request');
});
Responder a uma solicitação POST na rota raiz
(/) com a página inicial do aplicativo.
87. app.put('/user', function (req, res) {
res.send('Got a PUT request at /user');
});
Responder a uma solicitação PUT para a rota
/user.
88. app.delete('/user', function (req, res) {
res.send('Got a DELETE request at /user');
});
Responder a uma solicitação DELETE para a
rota /user.
91. var express = require('express');
var morgan = require('morgan');
var bodyParser = require('body-parser');
var hostname = 'localhost';
var port = 3000;
var app = express();
app.use(morgan('dev'));
app.use(bodyParser.json());
app.all('/books', function(req,res,next) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
next();
});
app.get('/books', function(req,res,next){
res.end('Will send all the books to you!');
});
app.get('/books/:bookId', function(req,res,next){
res.end('Will send details of the book: ' + req.params.bookId +' to you!');
});
. . .
app.listen(port, hostname, function(){
console.log(`Server running at http://${hostname}:${port}/`);
});
93. Use a classe express.Router para criar manipuladores
de rota modulares e montáveis.
Uma instância de Router é um middleware e sistema de
roteamento completo;
Por essa razão, é frequentemente tratado como um “mini-
aplicativo”
94. var express = require('express');
var router = express.Router();
router.use(function timeLog(req, res, next) {
console.log('Time: ', Date.now());
next();
});
router.get('/', function(req, res) {
res.send('Winter is Comming Home page');
});
router.get('/about', function(req, res) {
res.send('Tratar com Jon Snow');
});
module.exports = router;
Crie um arquivo de roteador com um arquivo
chamado winter.js no diretório do aplicativo, com o
seguinte conteúdo:
95. var express = require('express');
var hostname = 'localhost';
var port = 3000;
var app = express();
var winter = require('./winter');
app.use('/winters', winter);
app.listen(port, hostname, function(){
console.log(`Server running at http://${hostname}:${port}/`);
});
Crie um arquivo de roteador com um arquivo
chamado winter-server.js no diretório do aplicativo, com
o seguinte conteúdo:
99. Express Generator
Usado criar rapidamente uma estrutura básica de projeto;
Instale o express generator com o comando a seguir:
$ npm install express-generator -g
103. Nesta tarefa você continuará a exploração de módulos Node, Express e API REST.
Você deve:
Criar um módulo usando o Express Router para suportar as rotas para os waters
REST API.
Criar um módulo usando o Express Router para suportar as rotas para os
temperatures REST API.
Criar um módulo usando o Express Router para suportar as rotas para os energy
REST API.
http://localhost:3000/waters
http://localhost:3000/temperatures
http://localhost:3000/energy
É necessário suportar as operações GET, PUT, POST e DELETE em cada um dos
três endpoints, incluindo o suporte ao uso de parâmetros de rota para identificar um
registro específico.
106. Cada paradigma apresentado ataca
problemas diferentes e sua escolha
não é uma decisão puramente
preferencial, mas de necessidade do
projeto, tangendo aspectos
arquiteturais e mais abstratos
110. O MongoDB é um banco de dados baseado em
documento com alta performance e
disponibilidade e de fácil escalabilidade
111. Document: informação completa e “autocontida”;
JSON document:
{“name”: “Uthapizza”,
”description”: “A unique combination . . .”}
Collection: coleção de documentos;
Database: conjunto de coleções.
database
112. O conceito de documento
Um documento pode ser armazenado em diferentes
formatos hierárquicos como XML ou JSON com os dados
associados a uma estrutura de chave e valor.
É através de uma chave específica do documento que
temos acesso ao valor associado.
113. O conceito de documento
O MongoDB armazena seus documentos no formato BSON
(Binary JSON), muito parecido com JSON. Comparemos a
estrutura desses dois formatos:
// JSON
{
"nome" : "Jon Snow"
}
// BSON
{
"_id" : ObjectId("5303e0649fd1396")
"nome" : "Jon Snow"
}
114. Diferença entre BSON e JSON
É a quantidade dos tipos de dados suportados em cada
uma deles:
JSON: 6 tipos (Array, Boolean, null, Number, Object e
String)
BSON: +15 tipos
116. ObjectId
Todo documento criado recebe automaticamente a chave _id
contendo como valor padrão um objeto do tipo ObjectId.
• São pequenos;
• Provavelmente únicos;
• Rápidos para gerar e ordenados;
• Consistem de 12 bytes;
• Os 4 primeiros são um timestamp que reflete o momento
da criação.
119. Criando e Rodando o Banco
Uma forma testar a instalação do MongoDB é coma cliente
de linha de comando: o mongo shell
Abra uma nova janela do terminal (sem fechar) e execute o
seguinte comando:
$ mongod --dbpath <path>
$ mongo
121. Criando uma nova base de
dados
No terminal executando o “mongo shell” rode o comando:
Em execute o comando db para verificar qual base de
dados está sendo usada
> db
things
> use things
122. Criando uma nova coleção
No terminal executando o “mongo shell” rode o comando:
Se uma coleção não existe, o MongoDB cria a
coleção quando ele salva os dados pela primeira vez.
> db.myNewCollection.insertOne( { x: 1 } )
> db.myNewCollection2.createIndex( { y: 1 } )
123. MongoDB CRUD (Create)
MongoDB fornece os seguintes métodos para inserir
documentos em uma coleção:
db.collection.insertOne()
db.collection.insertMany()
125. MongoDB CRUD (Update)
MongoDB fornece os seguintes métodos para atualizar
documentos de uma coleção:
db.collection.updateOne()
db.collection.updateMany()
db.collection.replaceOne()
126. MongoDB CRUD (Delete)
O MongoDB fornece os seguintes métodos para excluir
documentos de uma coleção:
db.collection.deleteOne()
db.collection.deleteMany()
128. É preciso que a aplicação seja capaz de se conectar e realizar
operações no banco de dados;
Para isso MongoDB possui um driver nativo, criado especialmente
para o Node.js;
Sua instalação é feita através do npm como qualquer outro módulo
do Node.js:
https://github.com/mongodb/node-mongodb-native
npm install mongodb --save
129. Conectando ao mongoDB
var MongoClient = require('mongodb').MongoClient
, co = require('co')
, assert = require('assert');
// 1. Connect to MongoDB instance running on localhost
// Connection URL
var url = 'mongodb://localhost:27017/test';
co(function*() {
const db = yield MongoClient.connect(url);
console.log("Connected successfully to server");
yield insertDocuments(db, null);
yield findDocuments(db, null);
yield indexCollection(db, null);
yield aggregateDocuments(db, null);
db.close();
}).catch(err => console.log(err));
133. Exercício
Crie uma nova base de dados para o seu projeto;
A base deve conter no mínimo 5 coleções;
cada coleção deve representar o conjunto de informações
gerados por um sensor diferente (ex: sensor que monitora a
água da casa, a energia…);
Popule as coleções com dados “fake";
Faça consultas para extrair informações importantes da
base de dados.
134. Exercício
Crie um novo módulo (chamado operations.js) para o Node
contendo algumas operações comuns de MongoDB (CRUD);
Use o módulo na sua aplicação e comunique-se com o
servidor MongoDB (o módulo deve ser reaproveitável para
ser utilizado por qualquer novo “tipo” que for criado).
var assert = require('assert');
exports.insertDocument = function(db, document, collection, callback) {
// Get the documents collection
var coll = db.collection(collection);
// Insert some documents
coll.insert(document, function(err, result) {
assert.equal(err, null);
console.log("Inserted " + result.result.n + " documents into the document collection "
+ collection);
callback(result);
});
};
136. var assert = require('assert');
exports.insertDocument = function(db, document, collection, callback) {
// Get the documents collection
var coll = db.collection(collection);
// Insert some documents
coll.insert(document, function(err, result) {
assert.equal(err, null);
console.log("Inserted " + result.result.n + " documents into the document collection "
+ collection);
callback(result);
});
};
exports.findDocuments = function(db, collection, callback) {
// Get the documents collection
var coll = db.collection(collection);
// Find some documents
coll.find({}).toArray(function(err, docs) {
assert.equal(err, null);
callback(docs);
});
};
exports.removeDocument = function(db, document, collection, callback) {
// Get the documents collection
var coll = db.collection(collection);
// Delete the document
coll.deleteOne(document, function(err, result) {
assert.equal(err, null);
console.log("Removed the document " + document);
callback(result);
137. // Find some documents
coll.find({}).toArray(function(err, docs) {
assert.equal(err, null);
callback(docs);
});
};
exports.removeDocument = function(db, document, collection, callback) {
// Get the documents collection
var coll = db.collection(collection);
// Delete the document
coll.deleteOne(document, function(err, result) {
assert.equal(err, null);
console.log("Removed the document " + document);
callback(result);
});
};
exports.updateDocument = function(db, document, update, collection, callback) {
// Get the documents collection
var coll = db.collection(collection);
// Update document
coll.updateOne(document
, { $set: update }, null, function(err, result) {
assert.equal(err, null);
console.log("Updated the document with " + update);
callback(result);
});
};
138. var MongoClient = require('mongodb').MongoClient,
assert = require('assert');
var dboper = require('./operations');
var url = 'mongodb://localhost:27017/conFusion';
MongoClient.connect(url, function (err, db) {
assert.equal(null, err);
console.log("Connected correctly to server");
dboper.insertDocument(db, { name: "Vadonut", description: "Test" },
"dishes", function (result) {
console.log(result.ops);
dboper.findDocuments(db, "dishes", function (docs) {
console.log(docs);
dboper.updateDocument(db, { name: "Vadonut" },
{ description: "Updated Test" },
"dishes", function (result) {
console.log(result.result);
dboper.findDocuments(db, "dishes", function (docs) {
console.log(docs)
db.dropCollection("dishes", function (result) {
console.log(result);
db.close();
});
});
});
});
});
});
139. mongooseLet's face it, writing MongoDB validation, casting and business logic boilerplate
is a drag. That's why we wrote Mongoose.
140. O Mongoose é um módulo focado para a criação de
models, isso significa que com ele criaremos objetos
persistentes modelando seus atributos através do objeto
mongoose.Schema.
mongoose
142. mongoose
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
// create a schema
var thingSchema = new Schema({
name: {
type: String,
required: true,
unique: true
},
description: {
type: String,
required: true
}
}, {
timestamps: true
});
var things = mongoose.model('thing', thingSchema);
// make this available to our Node applications
module.exports = things;
143. mongoose var mongoose = require('mongoose'),
assert = require('assert');
var things = require('./things');
// Connection URL
var url = 'mongodb://localhost:27017/db_things';
mongoose.connect(url);
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function () {
console.log("Connected correctly to server");
// create a new user
var newThing = things({
name: 'Cadeira',
description: 'Cadeira Inteligente'
});
// save the user
newThing.save(function (err) {
if (err) throw err;
console.log('thing created!');
things.find({}, function (err, things) {
if (err) throw err;
console.log(things);
db.close();
// });
});
});
});
144. Schemas “Composto"
mongoose
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var commentSchema = new Schema({
rating: {
type: Number,
min: 1,
max: 5,
required: true
},
comment: {
type: String,
required: true
},
author: {
type: String,
required: true
}
}, {
timestamps: true
});
. . .
. . .
var thingSchema = new Schema({
name:{
type:String,
required:true,
unique:true
},
description:{
type:String,
required:true
},
comments:[commentSchema]
}, {
timestamps:true
});
var Things = mongoose.model('thing', thingSchema);
module.exports = Things;
145. mongoose var mongoose = require('mongoose');
var assert = require('assert');
var Things = require('./models/things-2.js');
var url = 'mongodb://localhost:27017/conFusion';
mongoose.connect(url);
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function(){
console.log("Connected correctly to server");
// create a new user
var newThing = Things({
name: 'Cadeira Legal',
description: 'cadeira mágica',
comments: [
{
rating: 3,
comment: 'This is insane',
author: 'Matt Daemon'
}
]
});
newThing.save(function(err, thing){
if (err) throw err;
console.log('Thing created!');
console.log(thing);
var id = thing._id;
setTimeout(function(){
Things.findByIdAndUpdate(id, {
$set:{
description: 'udpated test'
}
148. • Usando o express-generator crie um novo projeto de sua
escolha;
• Nesse projeto você deve criar 3 schemas do mongoose,
sendo que pelo menos um deles será utilizado como "sub
schema” do outro;
• Crie um controller para cada um dos schemas, cada
controle deve conter operações de CRUD dos schemas;
• Crie um arquivo javascript para chamar e testar os
controllers;
152. REST API
Toda requisição precisa ser decodificada e em seguida
mapeada de acordo com sua “natureza”:
Router().route(’/uri’)
.get(
)
.post (
)
Mongoose Schema + MongoDB
Things.find({},
);
Things.create(
);
153. REST API
Toda requisição precisa ser decodificada e em seguida
mapeada de acordo com sua “natureza”:
155. Crie a pasta models e dentro dela o schema books.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
// add the Currency type to the Mongoose Schema types
require('mongoose-currency').loadType(mongoose);
var Currency = mongoose.Types.Currency;
var commentSchema = new Schema({
rating: { type: Number, min: 1, max: 5, required: true },
comment: { type: String, required: true },
author: {type: String, required: true}
},
{ timestamps: true}
);
var bookSchema = new Schema({
name:{ type:String, required:true, unique:true },
image:{ type:String, required:true },
category:{ type:String, required:true },
label: { type: String, default: '' },
price: { type:Currency },
description:{ type:String, required:true },
comments:[commentSchema]
},
{ timestamps:true }
);
var Books = mongoose.model('Book', bookSchema);
module.exports = Books;
156. Dentro da pasta routes crie o arquivo bookRouter.js
var express = require('express');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var Books = require('../models/books');
var bookRouter = express.Router();
bookRouter.use(bodyParser.json());
bookRouter.route('/')
.get(function (req, res, next) {
Books.find({}, function (err, book) {
if (err) throw err;
res.json(book);
});
})
.post(function (req, res, next) {
Books.create(req.body, function (err, book) {
if (err) throw err;
console.log('Book created!');
var id = book._id;
res.writeHead(200, {
'Content-Type': 'text/plain'
});
res.end('Added the book with id: ' + id);
});
})
.delete(function (req, res, next) {
Books.remove({}, function (err, resp) {
if (err) throw err;
res.json(resp);
157. .delete(function (req, res, next) {
Books.remove({}, function (err, resp) {
if (err) throw err;
res.json(resp);
});
});
bookRouter.route('/:bookId')
.get(function (req, res, next) {
Books.findById(req.params.bookId, function (err, book) {
if (err) throw err;
res.json(book);
});
})
.put(function (req, res, next) {
Books.findByIdAndUpdate(req.params.bookId, {
$set: req.body
}, {
new: true
}, function (err, book) {
if (err) throw err;
res.json(book);
});
})
.delete(function (req, res, next) {
Books.findByIdAndRemove(req.params.bookId, function (err, resp) { if (err) throw err;
res.json(resp);
});
});
bookRouter.route('/:bookId/comments')
.get(function (req, res, next) {
Books.findById(req.params.bookId, function (err, book) {
if (err) throw err;
res.json(book.comments);
});
})
158. bookRouter.route('/:bookId/comments')
.get(function (req, res, next) {
Books.findById(req.params.bookId, function (err, book) {
if (err) throw err;
res.json(book.comments);
});
})
.post(function (req, res, next) {
Books.findById(req.params.bookId, function (err, book) {
if (err) throw err;
book.comments.push(req.body);
book.save(function (err, book) {
if (err) throw err;
console.log('Updated Comments!');
res.json(book);
});
});
})
.delete(function (req, res, next) {
Books.findById(req.params.bookId, function (err, book) {
if (err) throw err;
for (var i = (book.comments.length - 1); i >= 0; i--) {
book.comments.id(book.comments[i]._id).remove();
}
book.save(function (err, result) {
if (err) throw err;
res.writeHead(200, {
'Content-Type': 'text/plain'
});
res.end('Deleted all comments!');
});
});
});
bookRouter.route('/:bookId/comments/:commentId')
.get(function (req, res, next) {
Books.findById(req.params.bookId, function (err, book) {
if (err) throw err;
159. bookRouter.route('/:bookId/comments/:commentId')
.get(function (req, res, next) {
Books.findById(req.params.bookId, function (err, book) {
if (err) throw err;
res.json(book.comments.id(req.params.commentId));
});
})
.put(function (req, res, next) {
// We delete the existing commment and insert the updated
// comment as a new comment
Books.findById(req.params.bookId, function (err, book) {
if (err) throw err;
book.comments.id(req.params.commentId).remove();
book.comments.push(req.body);
book.save(function (err, book) {
if (err) throw err;
console.log('Updated Comments!');
res.json(book);
});
});
})
.delete(function (req, res, next) {
Books.findById(req.params.bookId, function (err, book) {
book.comments.id(req.params.commentId).remove();
book.save(function (err, resp) {
if (err) throw err;
res.json(resp);
});
});
});
module.exports = bookRouter;
160. var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var index = require('./routes/index');
var users = require('./routes/users');
var bookRouter = require('./routes/bookRouter');
var mongoose = require('mongoose');
var url = 'mongodb://localhost:27017/books';
mongoose.connect(url);
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function () {
// we're connected!
console.log("Connected correctly to server");
});
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
Ajuste o arquivo app.js criado pelo express-generator
161. // view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', index);
app.use('/books', bookRouter);
app.use('/users', users);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
166. Client Serverrequest a protected resource
request username and password
send username and password
returns requested resource
167. Express and Basic
Authentication
function auth (req, res, next) {
console.log(req.headers);
var authHeader = req.headers.authorization;
if (!authHeader) {
var err = new Error('You are not authenticated!');
err.status = 401;
next(err);
return;
}
var auth = new Buffer(authHeader.split(' ')[1], 'base64').toString().split(':');
var user = auth[0];
var pass = auth[1];
if (user == 'admin' && pass == 'password') {
next(); // authorized
} else {
var err = new Error('You are not authenticated!');
err.status = 401;
next(err);
}
}
app.use(auth);
168. var express = require('express');
var morgan = require('morgan');
var hostname = 'localhost';
var port = 3000;
var app = express();
app.use(morgan('dev'));
function auth (req, res, next) {
console.log(req.headers);
var authHeader = req.headers.authorization;
if (!authHeader) {
var err = new Error('You are not authenticated!');
err.status = 401;
next(err);
return;
}
var auth = new Buffer(authHeader.split(' ')[1], 'base64').toString().split(':');
var user = auth[0];
var pass = auth[1];
if (user == 'admin' && pass == 'password') {
next(); // authorized
} else {
var err = new Error('You are not authenticated!');
err.status = 401;
next(err);
}
}
Express and Basic Authentication
169. app.use(morgan('dev'));
function auth (req, res, next) {
console.log(req.headers);
var authHeader = req.headers.authorization;
if (!authHeader) {
var err = new Error('You are not authenticated!');
err.status = 401;
next(err);
return;
}
var auth = new Buffer(authHeader.split(' ')[1], 'base64').toString().split(':');
var user = auth[0];
var pass = auth[1];
if (user == 'admin' && pass == 'password') {
next(); // authorized
} else {
var err = new Error('You are not authenticated!');
err.status = 401;
next(err);
}
}
app.use(auth);
app.use(express.static(__dirname + '/public'));
app.use(function(err,req,res,next) {
res.writeHead(err.status || 500, {
'WWW-Authenticate': 'Basic',
'Content-Type': 'text/plain'
});
res.end(err.message);
});
app.listen(port, hostname, function(){
console.log(`Server running at http://${hostname}:${port}/`);
});
170. Exercício
Agora continuando o exemplo, continue o exercício de
criação da REST API colocando o controle de acesso aos
métodos dos routers.
172. User Authentication with
Passport
Passport (http://passportjs.og) é uma solução não
obstrusiva de autenti- cação especí ca para o Node.js que
dá suporte a vários provedores como o Facebook, Twiiter,
Google entre outros
173. app.post('/login',
passport.authenticate('local', { successRedirect: '/',
failureRedirect: '/login' }));
Apesar das complexidades envolvidas na autenticação, o código
não precisa ser complicado
app.post('/login',
passport.authenticate('local'),
function(req, res) {
// If this function gets called, authentication was successful.
// `req.user` contains the authenticated user.
res.redirect('/users/' + req.user.username);
});
Os pedidos de autenticação são tão simples como chamar
passport.authenticate () e especificar qual estratégia empregar.
Se a autenticação falhar, o Passport responderá com um status 401
não autorizado e todos os manipuladores de rotas adicionais não
serão invocado
174. app.post('/login',
passport.authenticate('local', { successRedirect: '/',
failureRedirect: '/login' }));
Um redirecionamento geralmente é emitido após a autenticação
de um pedido.
Nesse caso, as opções de redirecionamento substituem o
comportamento padrão. Após a autenticação bem-sucedida,
o usuário será redirecionado para a página inicial. Se a
autenticação falhar, o usuário será redirecionado de volta
para a página de login para outra tentativa.
175. - app
------ models
---------- user.js <!-- our user model -->
------ routes.js <!-- all the routes for our application -->
- config
------ auth.js <!-- will hold all our client secret keys (facebook, twitter, google) -->
------ database.js <!-- will hold our database connection settings -->
------ passport.js <!-- configuring the strategies for passport -->
- views
------ index.ejs <!-- show our home page with login links -->
------ login.ejs <!-- show our login form -->
------ signup.ejs <!-- show our signup form -->
------ profile.ejs <!-- after a user logs in, they will see their profile -->
- package.json <!-- handle our npm packages -->
- server.js <!-- setup our application -->
Primeiro vamos criar um novo projeto com a
seguinte estrutura:
183. // server.js
var express = require('express');
var port = process.env.PORT || 8080;
var mongoose = require('mongoose');
var passport = require('passport');
var flash = require('connect-flash');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session')
var configDB = require('./config/database.js');
var app = express();
mongoose.connect(configDB.url);
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.set('view engine', 'ejs');
app.use(session({secret: 'winteriscomming'}))
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
//ORDEM IMPORTA!!!
require('./config/passport')(passport);
require('./app/routes.js')(app, passport);
app.listen(port);
console.log('The magic happens on port ' + port);
184. // config/database.js
module.exports = {
'url' : 'mongodb://localhost/passport'
};
https://goo.gl/EQPD2Z
Crie o arquivo database.js com a URL do seu banco de dados
Faça o download das views e copie para a pasta views
186. Entre no site "Facebook Developers" e crie a sua aplicação.
Defina a sua callback URL para:
http://localhost:8080/auth/facebook/callback
196. • Crie um novo projeto completo com:
• Livros, DVDs, CDs e Autor;
• Cada uma das 3 primeiras entidade possui um relacionamento com
Autor (cada uma possui um Autor);
• Crie os métodos REST para o CRUD das 4 entidades;
• Utilizar o MongoDB e autenticação com o Facebook ou Google ou
Autenticação simples;
• Os métodos GET podem ser acessados sem que o usuário esteja
autenticado;
• Os métodos POST, UPDATE e DELETE só podem ser acessados
por usuários autenticados;
https://goo.gl/npBz5q