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.
Victor Hazin
Engenheiro deSoftware 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)
Presentation layer BusinessLogic layer Data Access layer
NodeJS
and
NodeJS Modules
Single page Apps
using Javascript Frameworks
(AngularJS)
MongoDB
JSON documents
REST API
serving JSON
“é uma plataformapara 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”
Configurando o ambientede
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.
npm
• Gerenciador depacotes 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).
node modules
Todo projetoNode.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).
CommonJS
• O Node.jsutiliza 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.jscarregamos 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!’);
1. Crie umapasta 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 umnovo 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
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
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.
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
varhttp = 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 HTMLdo
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
Implementar um Roteadorde
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;
É um frameworkweb 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 Middlewaresã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 HTTPpara 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 HTTPpara 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 HTTPpara 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 HTTPpara 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 HTTPpara 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 HTTPpara 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 HTTPpara 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 middlewarepodem 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 pastapara 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
varexpress = 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 arquivosestá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ívelcarregar 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
Crieuma 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
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 daWeb 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 fundamentaisdo 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çãodos 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 vantagemem 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!!!!
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 derotas 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.
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}/`);
});
Use a classe express.Router paracriar 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:
Express Generator
Usado criarrapidamente uma estrutura básica de projeto;
Instale o express generator com o comando a seguir:
$ npm install express-generator -g
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.
Cada paradigma apresentadoataca
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 completae “autocontida”;
JSON document:
{“name”: “Uthapizza”,
”description”: “A unique combination . . .”}
Collection: coleção de documentos;
Database: conjunto de coleções.
database
112.
O conceito dedocumento
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 dedocumento
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 BSONe 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
ObjectId
Todo documento criadorecebe 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.
Criando e Rodandoo 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 novabase 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 novacoleçã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)
MongoDBfornece os seguintes métodos para inserir
documentos em uma coleção:
db.collection.insertOne()
db.collection.insertMany()
MongoDB CRUD (Update)
MongoDBfornece os seguintes métodos para atualizar
documentos de uma coleção:
db.collection.updateOne()
db.collection.updateMany()
db.collection.replaceOne()
126.
MongoDB CRUD (Delete)
OMongoDB fornece os seguintes métodos para excluir
documentos de uma coleção:
db.collection.deleteOne()
db.collection.deleteMany()
128.
É preciso quea 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
varMongoClient = 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));
Exercício
Crie uma novabase 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 novomó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 somedocuments
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, writingMongoDB 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
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'
}
• Usando oexpress-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;
REST API
Toda requisiçãoprecisa 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çãoprecisa ser decodificada e em seguida
mapeada de acordo com sua “natureza”:
Crie a pastamodels 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 pastaroutes 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 enginesetup
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;
Client Serverrequest aprotected resource
request username and password
send username and password
returns requested resource
167.
Express and Basic
Authentication
functionauth (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 oexemplo, continue o exercício de
criação da REST API colocando o controle de acesso aos
métodos dos routers.
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:
// 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
• Crie umnovo 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