Aula 3 — Banco de Dados Orientado a Documentos

Fundamentos, modelagem, criação de banco, inserções, consultas ampliadas, atualizações, remoções, embedding, referência, agregações e índices em MongoDB.

Objetivos da aula

A proposta desta aula é unir conceito e prática, usando MongoDB para mostrar como a modelagem documental influencia diretamente a forma de consultar e manipular os dados.

Mapa da aula

Fundamentos

  • Documento
  • Coleção
  • JSON e BSON
  • Schema flexível

Modelagem

  • Agregados
  • Embedding
  • Referência
  • Duplicação controlada

Prática

  • Criação de banco
  • Inserção
  • Consultas
  • Update, delete e índice

O que é um banco orientado a documentos?

É um banco de dados não relacional que organiza a informação em documentos, agrupados em coleções.

Documento, coleção e tabela

Modelo relacional

  • Tabelas
  • Linhas
  • Colunas
  • Chaves estrangeiras
  • Joins

Modelo documental

  • Coleções
  • Documentos
  • Campos
  • Subdocumentos
  • Arrays
Um documento não é apenas uma linha com colunas. Ele pode armazenar estruturas completas dentro de si.

JSON e BSON

{ "nome": "Ana Souza", "curso": "ADS", "idade": 22, "ativo": true, "disciplinas": ["Banco de Dados", "MongoDB"] }

Estrutura típica de um documento

{ "_id": "64f1...", "nome": "Maria Souza", "email": "maria@email.com", "telefones": [ { "tipo": "celular", "numero": "11999999999" }, { "tipo": "trabalho", "numero": "1133333333" } ], "endereco": { "rua": "Rua A", "cidade": "Campinas", "uf": "SP" }, "preferencias": { "tema": "escuro", "notificacoes": true } }

Modelagem orientada por padrão de acesso

No modelo documental, a modelagem costuma ser guiada pelo padrão de leitura e pelo contexto de uso da aplicação.

Agregado e duplicação controlada

Um agregado é um conjunto de dados tratado como unidade lógica.

Em muitos casos, repetir alguns dados é aceitável para facilitar a leitura e preservar contexto histórico.

Embedding x referência

Embedding

  • Dados fortemente relacionados
  • Lidos juntos com frequência
  • Atualizados em conjunto
  • Favorece leitura

Referência

  • Dado compartilhado em muitos contextos
  • Atualização frequente e centralizada
  • Evita repetição excessiva
  • Favorece reuso

Exemplo: embedding

db.clientes.insertOne({ nome: "Paula Mendes", telefones: [ { tipo: "celular", numero: "11999999999" } ], endereco: { cidade: "Campinas", uf: "SP" } })

Exemplo: referência

db.cursos.insertOne({ _id: 10, nome: "Análise e Desenvolvimento de Sistemas" }) db.alunos.insertOne({ ra: "R010", nome: "Felipe Costa", curso_id: 10 })
Embedding favorece leitura em um único documento. Referência favorece reuso e atualização centralizada.

Primeiros comandos no MongoDB

use escola db.createCollection("alunos") show collections
Em muitos casos, a coleção também pode ser criada implicitamente na primeira inserção.

Inserção de um documento

db.alunos.insertOne({ ra: "R001", nome: "Ana Souza", curso: "ADS", idade: 22 })

Inserção com subdocumentos e arrays

db.alunos.insertOne({ ra: "R002", nome: "Carlos Lima", curso: "CC", idade: 24, endereco: { cidade: "Campinas", uf: "SP" }, disciplinas: ["MongoDB", "Python", "Estatística"] })

Inserção de vários documentos

db.alunos.insertMany([ { ra: "R003", nome: "Marina Alves", curso: "SI", idade: 21, endereco: { cidade: "Jundiaí", uf: "SP" }, disciplinas: ["Banco de Dados", "Java"] }, { ra: "R004", nome: "João Pedro", curso: "ADS", idade: 23, endereco: { cidade: "Itatiba", uf: "SP" }, disciplinas: ["MongoDB", "Redes"] } ])

Exercício inicial

Criação e inserção

Crie um banco e uma coleção chamada produtos. Depois, insira 3 documentos com:

Consulta básica

db.alunos.find() db.alunos.find().pretty()
A primeira consulta mostra a coleção completa. O método pretty() ajuda na visualização.

Consulta por igualdade

db.alunos.find({ curso: "ADS" }) db.alunos.find({ idade: 22 })

Consulta com múltiplos campos

db.alunos.find({ curso: "ADS", idade: 22 })
Quando vários campos aparecem no mesmo objeto, a lógica aplicada é um AND.

Operadores de comparação

db.alunos.find({ idade: { $gt: 21 } }) db.alunos.find({ idade: { $gte: 21 } }) db.alunos.find({ idade: { $lt: 23 } }) db.alunos.find({ idade: { $lte: 23 } }) db.alunos.find({ curso: { $ne: "ADS" } })

Intervalo e operador IN

db.alunos.find({ idade: { $gte: 20, $lte: 23 } }) db.alunos.find({ curso: { $in: ["ADS", "CC"] } }) db.alunos.find({ curso: { $nin: ["ADS", "CC"] } })

Operadores lógicos

db.alunos.find({ $and: [ { curso: "ADS" }, { idade: { $gt: 20 } } ] }) db.alunos.find({ $or: [ { curso: "ADS" }, { curso: "SI" } ] })

Projeção

db.alunos.find( { curso: "ADS" }, { nome: 1, curso: 1, _id: 0 } ) db.alunos.find( {}, { nome: 1, idade: 1, _id: 0 } )

Ordenação e limite

db.alunos.find().sort({ nome: 1 }) db.alunos.find().sort({ idade: -1 }) db.alunos.find().limit(3) db.alunos.find().sort({ idade: -1 }).limit(2)

Consultas em campos aninhados

db.alunos.find({ "endereco.cidade": "Campinas" }) db.alunos.find({ "endereco.uf": "SP" })

Consultas em arrays

db.alunos.find({ disciplinas: "MongoDB" }) db.alunos.find({ disciplinas: { $in: ["MongoDB", "Python"] } }) db.alunos.find({ disciplinas: { $size: 2 } })

Arrays de objetos e $elemMatch

db.clientes.insertOne({ nome: "Paula Mendes", contatos: [ { tipo: "celular", valor: "11999999999" }, { tipo: "email", valor: "paula@email.com" } ] }) db.clientes.find({ "contatos.tipo": "email" }) db.clientes.find({ contatos: { $elemMatch: { tipo: "email", valor: "paula@email.com" } } })

Existência, contagem e distinct

db.alunos.find({ telefone: { $exists: true } }) db.alunos.countDocuments() db.alunos.countDocuments({ curso: "ADS" }) db.alunos.distinct("curso")

Consulta completa

db.alunos.find( { curso: "ADS", idade: { $gte: 20 }, "endereco.uf": "SP", disciplinas: "MongoDB" }, { nome: 1, curso: 1, disciplinas: 1, _id: 0 } ).sort({ nome: 1 }).limit(5)

Atualização com updateOne

db.alunos.updateOne( { ra: "R001" }, { $set: { idade: 23 } } )

Atualização com updateMany

db.alunos.updateMany( { curso: "ADS" }, { $set: { turno: "Noturno" } } )

Operadores de atualização

db.produtos.updateOne( { nome: "Mouse" }, { $inc: { estoque: -1 } } ) db.produtos.updateOne( { nome: "Notebook" }, { $unset: { observacao: "" } } ) db.alunos.updateOne( { ra: "R001" }, { $push: { disciplinas: "Banco de Dados Não Relacionais" } } ) db.alunos.updateOne( { ra: "R001" }, { $pull: { disciplinas: "Lógica" } } )

Remoção

db.alunos.deleteOne({ ra: "R004" }) db.alunos.deleteMany({ curso: "SI" })
Remoções devem sempre ser feitas com filtros bem definidos.

Exercícios de consulta

Exercícios de modelagem

O que é agregação?

A agregação permite transformar e resumir dados em etapas, por meio de um pipeline.

Pipeline básico

db.produtos.aggregate([ { $match: { categoria: "Periféricos" } }, { $project: { nome: 1, preco: 1, _id: 0 } }, { $sort: { preco: -1 } } ])

Agrupando dados

db.produtos.aggregate([ { $group: { _id: "$categoria", totalProdutos: { $sum: 1 }, mediaPreco: { $avg: "$preco" } } } ])

Por que índices importam?

Índice simples e composto

db.alunos.createIndex({ ra: 1 }) db.produtos.createIndex({ categoria: 1 }) db.pedidos.createIndex({ status: 1, data: -1 })

Resumo da aula

Perguntas para revisão