Implementação de Operações CRUD com Mongoose no Node.js

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.

Tags: Node.js mongodb mongoose backend javascript

Publicado em 9-20 00:34