O Mongoose atua como uma biblioteca de Modelagem de Dados de Objeto (ODM) para MongoDB e Node.js. Ele gerencia o relacionamenot entre os dados, fornece validação de esquema e é utilizado para traduzir entre objetos no código e a representação desses objetos no MongoDB.
Instalação do Pacote
Para iniciar a integração, é necessário instalar a dependência via npm:
npm install mongoose
Configuração da Conexão com o Banco de Dados
A prática recomendada envolve o uso de variáveis de ambiente para gerenciar credenciais sensíveis. No arquivo .env, definimos as strings de conexão:
# Exemplo de string para MongoDB Atlas
MONGODB_URI=mongodb+srv://user:password@cluster.mongodb.net/database_name?retryWrites=true&w=majority
# Exemplo para instância local
DATABASE_LOCAL=mongodb://localhost:27017/meu_app
No arquivo principal do servidor (server.js), estabelecemos a conexão assíncrona:
const mongoose = require('mongoose');
const dotenv = require('dotenv');
dotenv.config({ path: './config.env' });
const uri = process.env.MONGODB_URI;
mongoose.connect(uri, {
useNewUrlParser: true,
useUnifiedTopology: true
}).then(() => {
console.log('Conexão com o MongoDB estabelecida com sucesso.');
}).catch(err => {
console.error('Erro ao conectar ao banco de dados:', err);
});
Definição do Modelo de Dados
O Mongoose utiliza Schemas para definir a estrutura dos documentos. Abaixo, um exemplo de modelo para um catálogo de produtos:
const mongoose = require('mongoose');
const itemSchema = new mongoose.Schema({
nome: {
type: String,
required: [true, 'O nome do item é obrigatório'],
unique: true,
trim: true
},
preco: {
type: Number,
required: [true, 'O preço deve ser informado']
},
disponivel: {
type: Boolean,
default: true
},
dataRegistro: {
type: Date,
default: Date.now
}
});
const Item = mongoose.model('Item', itemSchema);
module.exports = Item;
Implementação dos Controladores CRUD
Os controladores gerenciam a lógica de negócio e interagem com o modelo para realizar as operações fundamentais.
Criação (Create)
Utilizamos o método create para persistir um novo documento enviado pelo corpo da requisição:
exports.salvarItem = async (req, res) => {
try {
const novoItem = await Item.create(req.body);
res.status(201).json({
status: 'sucesso',
data: { item: novoItem }
});
} catch (erro) {
res.status(400).json({
status: 'falha',
mensagem: erro.message
});
}
};
Leitura (Read)
Podemos buscar todos os registros ou um documento específico pelo seu ID:
exports.listarTodos = async (req, res) => {
try {
const lista = await Item.find();
res.status(200).json({
status: 'sucesso',
resultados: lista.length,
data: { itens: lista }
});
} catch (erro) {
res.status(404).json({ status: 'erro', mensagem: erro });
}
};
exports.buscarPorId = async (req, res) => {
try {
const registro = await Item.findById(req.params.id);
res.status(200).json({
status: 'sucesso',
data: { item: registro }
});
} catch (erro) {
res.status(404).json({ status: 'falha', mensagem: 'Item não encontrado' });
}
};
Atualização (Update)
O método findByIdAndUpdate permite atualizar campos específicos. O parâmetro new: true garante o retorno do documento já modificado:
exports.modificarItem = async (req, res) => {
try {
const itemAtualizado = await Item.findByIdAndUpdate(req.params.id, req.body, {
new: true,
runValidators: true
});
res.status(200).json({
status: 'sucesso',
data: { item: itemAtualizado }
});
} catch (erro) {
res.status(400).json({ status: 'falha', mensagem: erro });
}
};
Exclusão (Delete)
Para remover um documento de forma definitiva:
exports.deletarItem = async (req, res) => {
try {
await Item.findByIdAndDelete(req.params.id);
res.status(204).json({
status: 'sucesso',
data: null
});
} catch (erro) {
res.status(404).json({ status: 'falha', mensagem: erro });
}
};
Estrutura Arquitetural
Para manter a escalabilidade, o projeto deve ser organizado seguindo o padrão de separação de responsabilidades:
- Models: Definição dos Schemas e regras de validação de dados.
- Controllers: Lógica de manipulação dos modelos e controle de fluxo das requisições.
- Routes: Mapeamento dos endpoints HTTP para as funções dos controladores.
- App.js: Configuração de middlewares e inicialização do framework Express.
- Server.js: Ponto de entrada da aplicação e conexão com o banco de dados.