Sitemap

Cheat Sheet: MongoDB Associate Developer (Java) Certification

8 min readJul 14, 2026

--

Resumo prático dos tópicos cobrados na certificação, pensado para consulta rápida

1. Modelo de documentos e BSON

MongoDB guarda dados como documentos BSON dentro de coleções. Cada documento é um conjunto de pares chave-valor, e o valor pode ser um escalar, um array ou outro documento (aninhamento).

Diferente de uma tabela relacional, documentos de uma mesma coleção não precisam ter o mesmo formato. Isso é o chamado schema flexível: dá pra evoluir o modelo sem migração custosa, misturar formatos diferentes na mesma coleção, e ainda assim aplicar regras de validação quando fizer sentido.

Get Murilo Luzzi’s stories in your inbox

Join Medium for free to get updates from this writer.

Tipos BSON principais:

  • Texto → string
  • Número decimal simples→ double
  • Número decimal preciso (ex. operações bancárias)→ decimal128
  • Inteiro 32 bits → int
  • Inteiro 64 bits → long
  • Documento aninhado → object
  • Lista → array
  • Booleano → bool
  • Data → date
  • Identificador único → objectId
  • Nulo → null
  • Binário → binData
  • Regex → regex
  • Timestamp interno → timestamp
  • Min/Max key → minKey / maxKey

Dica: a pergunta clássica é “esses 3 documentos de formatos diferentes podem coexistir na mesma coleção?” — a resposta quase sempre é sim, contanto que cada um tenha _id único. MongoDB não exige schema fixo.

2. Operadores

Comparação (usados em filtros)

  • {campo: valor} → igualdade implícita
  • $eq / $ne → igual / diferente
  • $gt / $gte → maior / maior ou igual
  • $lt / $lte → menor / menor ou igual
  • $in / $nin → está / não está em uma lista

Lógicos

  • $and → todas as condições verdadeiras (vírgula já é AND implícito)
  • $or → pelo menos uma condição verdadeira
  • $nor → nenhuma condição verdadeira
  • $not → inverte uma condição

Array e elemento

  • $exists → verifica se o campo existe
  • $type → verifica o tipo BSON do campo
  • $all → array contém todos os valores citados (ordem livre)
  • $size → array tem exatamente N elementos
  • $elemMatch → um único elemento do array satisfaz todas as condições

Dica: sem $elemMatch, {nota: {$gt: 80, $lt: 90}} pode ser satisfeito por elementos diferentes do array (um >80, outro <90). Com $elemMatch, precisa ser o mesmo elemento. É a pegadinha mais comum da prova.

Atualização (só dentro de update)

  • $set → define/cria valor de um campo
  • $unset → remove um campo
  • $inc → soma (ou subtrai, com negativo) um valor numérico
  • $setOnInsert → só aplica se a operação criar um documento novo (upsert)
  • $push → adiciona item ao final do array
  • $addToSet → adiciona ao array só se não existir (evita duplicata)
  • $pull → remove elementos que casam com uma condição
  • $pop → remove primeiro (-1) ou último (1) item do array

Projection

  • 1 inclui, 0 exclui.
  • Não dá pra misturar inclusão e exclusão — exceto _id, que pode ser 0 mesmo com outros campos em 1.
  • $slice limita quantos itens de um array retornar.

Estágios de aggregation

  • $match → filtra documentos (igual ao find)
  • $group → agrupa por uma chave e aplica acumuladores
  • $project / $set → molda/adiciona campos na saída
  • $sort / $limit → ordena / limita resultado
  • $unwind → "explode" um array em um documento por item
  • $lookup → join com outra coleção (left outer join)
  • $out → grava o resultado em uma coleção, substituindo o conteúdo existente — precisa ser o último estágio
  • $search → busca Atlas Search — precisa ser o primeiro estágio

Acumuladores do $group

$sum, $avg, $max, $min, $push (junta em array), $addToSet (junta valores únicos)

3. Comandos na prática (shell)

Inserir

db.pedidos.insertOne({ cliente: "Ana", total: 150 })

db.pedidos.insertMany([
{ cliente: "Ana", total: 150 },
{ cliente: "Bruno", total: 90 }
])

Buscar

// igualdade simples
db.pedidos.find({ cliente: "Ana" })

// comparação
db.pedidos.find({ total: { $gte: 100 } })

// valor dentro de um array
db.pedidos.find({ itens: "caneca" })

// $elemMatch: mesmo elemento satisfaz as duas condições
db.pedidos.find({
itens: { $elemMatch: { produto: "caneca", qtd: { $gt: 1 } } }
})

// lógico
db.pedidos.find({ $or: [{ status: "pendente" }, { total: { $gt: 500 } }] })

Atualizar

// $set em um campo específico
db.pedidos.updateOne({ _id: 1 }, { $set: { status: "pago" } })

// substitui o documento inteiro (sem operadores)
db.pedidos.replaceOne({ _id: 1 }, { cliente: "Ana", total: 200 })

// upsert: cria se não existir
db.pedidos.updateOne(
{ cliente: "Carla" },
{ $set: { total: 80 } },
{ upsert: true }
)

// vários documentos de uma vez
db.pedidos.updateMany({ total: { $lt: 50 } }, { $set: { promo: true } })

// busca, atualiza e já retorna o documento (evita condição de corrida)
db.pedidos.findAndModify({
query: { _id: 1 },
update: { $inc: { total: 10 } },
new: true
})

Deletar

// Deleta o primeiro documento encontrado que passa pelo filtro
db.pedidos.deleteOne({ _id: 1 })

// Deleta todos os documentos que passam pelo filtro
db.pedidos.deleteMany({ status: "cancelado" })

Ordenar, limitar e contar

// use _id como critério extra pra garantir ordem consistente
db.pedidos.find().sort({ total: -1, _id: 1 }).limit(3)

// countDocuments() substituiu deprecado count() e é muito preciso
db.pedidos.countDocuments({ status: "pago" })

Projeção

// inclui só os campos citados (+ _id, a menos que zere)
db.pedidos.find({ status: "pago" }, { cliente: 1, total: 1, _id: 0 })

// exclui campos específicos
db.pedidos.find({}, { endereco: 0 })

Índices

// índice simples
db.pedidos.createIndex({ cliente: 1 })

// único
db.pedidos.createIndex({ email: 1 }, { unique: true })

// composto - ordem recomendada: Equality, Sort, Range (regra "ESR")
db.pedidos.createIndex({ status: 1, total: -1, cliente: 1 })

// ver índices existentes
db.pedidos.getIndexes()

// checar se a query usa índice (IXSCAN) ou varre tudo (COLLSCAN)
db.pedidos.explain().find({ total: { $gt: 100 } })

// remover
db.pedidos.dropIndex("cliente_1")
db.pedidos.dropIndexes()

Lendo o explain(): o plano de execução mostra os estágios que a query passou. Os principais:

  • COLLSCAN → varreu a coleção inteira, sem usar índice (sinal de alerta de performance)
  • IXSCAN → usou um índice pra localizar os documentos (bom)
  • FETCH → precisou buscar o documento completo no disco/memória depois do índice
  • SORT → teve que ordenar os resultados em memória porque o índice não cobria a ordenação pedida

Dica: array indexado vira automaticamente um índice multikey — não precisa criar nada diferente, só indexar o campo normalmente. E: apagar um índice não apaga dados, só faz a query voltar a fazer COLLSCAN.

Aggregation

Pipeline é uma sequência de estágios — a saída de um vira a entrada do próximo.

// Esqueleto do Aggregation

db.collection.aggregate([
{
$stage1: {
// expressão 1,
// expressão 2
}
},
{
$stage2: {
// expressão 1
}
}
])
// $match + $group: filtra e depois soma por grupo
db.pedidos.aggregate([
{ $match: { status: "pago" } },
{ $group: { _id: "$cliente", totalGasto: { $sum: "$total" } } },
{ $sort: { totalGasto: -1 } },
{ $limit: 5 }
])

// $project / $set: reformata e cria campo calculado
db.pedidos.aggregate([
{ $match: { status: "pago" } },
{ $set: { totalComDesconto: { $multiply: ["$total", 0.9] } } },
{ $project: { cliente: 1, total: 1, totalComDesconto: 1, _id: 0 } }
])

// $count: retorna um único documento com a contagem
db.pedidos.aggregate([
{ $match: { status: "pendente" } },
{ $count: "totalPendentes" }
])

// $unwind: "explode" o array de itens em um documento por item
db.pedidos.aggregate([
{ $unwind: "$itens" },
{ $group: { _id: "$itens.produto", vendidos: { $sum: 1 } } }
])

// $lookup: join com a coleção "clientes" (left outer join)
// $lookup sempre retorna um array - $unwind é comum logo depois
db.pedidos.aggregate([
{
$lookup: {
from: "clientes",
localField: "clienteId",
foreignField: "_id",
as: "dadosCliente"
}
},
{ $unwind: "$dadosCliente" }
])

// $out: grava o resultado final em outra coleção (substitui se já existir)
db.pedidos.aggregate([
{ $match: { status: "pago" } },
{ $group: { _id: "$cliente", totalGasto: { $sum: "$total" } } },
{ $out: "resumo_clientes" }
])

Dica: a ordem dos estágios importa para o resultado (e para performance — $match cedo reduz o volume de dados nos estágios seguintes), mas não para a sintaxe: cada estágio é sempre um objeto independente dentro do array.

4. Java Driver

O que é o driver

O MongoDB Java Driver é a biblioteca oficial que traduz chamadas Java em comandos que o banco entende (protocolo de rede do MongoDB). A aplicação nunca fala direto com o banco — ela usa MongoClient, MongoDatabase e MongoCollection<Document> como camadas de abstração.

MongoClient mongoClient = MongoClients.create(connectionString);
MongoDatabase db = mongoClient.getDatabase("loja");
MongoCollection<Document> pedidos = db.getCollection("pedidos");

Componentes da URI de conexão

mongodb+srv://usuario:senha@cluster.mongodb.net/loja?retryWrites=true&w=majority
  • mongodb+srv:// → protocolo (+srv resolve o cluster via DNS, comum no Atlas)
  • usuario:senha → credenciais de autenticação
  • cluster.mongodb.net → host/cluster de destino
  • /loja → banco de dados padrão da conexão
  • ?retryWrites=true&w=majority → opções (retry automático, nível de confirmação de escrita)

Connection pooling

O driver não abre uma conexão nova a cada operação — ele mantém um pool de conexões já estabelecidas e reaproveitáveis. Isso reduz a latência (evita handshake TCP/TLS repetido) e permite lidar com múltiplas operações concorrentes de forma eficiente. O MongoClient deve ser criado uma única vez e reaproveitado durante todo o ciclo de vida da aplicação — nunca um MongoClient por requisição.

Insert

// um documento
pedidos.insertOne(new Document("cliente", "Ana").append("total", 150));

// vários documentos
List<Document> novos = List.of(
new Document("cliente", "Bruno").append("total", 90),
new Document("cliente", "Carla").append("total", 60)
);

InsertManyResult resultado = pedidos.insertMany(novos);
resultado.getInsertedIds().forEach((i, id) -> System.out.println(id));

Find

Os filtros usam a classe utilitária Filters (import static com.mongodb.client.model.Filters.*), que evita montar Document na mão.

// um único documento
Document doc = pedidos.find(eq("cliente", "Ana")).first();

// vários documentos, com cursor
try (MongoCursor<Document> cursor =
pedidos.find(and(gte("total", 100), eq("status", "pago"))).iterator()) {
while (cursor.hasNext()) {
System.out.println(cursor.next().toJson());
}
}

Update

Assim como Filters, existe a classe Updates (import static com.mongodb.client.model.Updates.*) para montar as operações de atualização.

// um documento
Bson filtro = eq("_id", 1);
Bson atualizacao = Updates.combine(Updates.set("status", "pago"), Updates.inc("total", 10));
pedidos.updateOne(filtro, atualizacao);

// vários documentos
pedidos.updateMany(lt("total", 50), Updates.set("promo", true));

Delete

// um documento
DeleteResult r1 = pedidos.deleteOne(eq("_id", 1));
System.out.println(r1.getDeletedCount());

// vários documentos
DeleteResult r2 = pedidos.deleteMany(eq("status", "cancelado"));
System.out.println(r2.getDeletedCount());

Aggregate

O pipeline é montado como uma List<Bson>, geralmente com a classe Aggregates (import static com.mongodb.client.model.Aggregates.*) combinada com Accumulators para os estágios de $group.

Bson match = Aggregates.match(eq("status", "pago"));
Bson group = Aggregates.group("$cliente", Accumulators.sum("totalGasto", "$total"));
Bson sort = Aggregates.sort(Sorts.descending("totalGasto"));

pedidos.aggregate(List.of(match, group, sort))
.forEach(d -> System.out.println(d.toJson()));

Dica: o driver Java tem versões “cruas” (passar Document/Bson montado manualmente) e versões com builders (Filters, Updates, Aggregates, Sorts, Projections). A prova costuma cobrar reconhecer a sintaxe correta dos builders — vale decorar os imports estáticos mais comuns.

5. Dicas rápidas para a prova

  • $elemMatch é o tópico mais cobrado dentro de arrays — sem ele, condições podem "vazar" entre elementos diferentes.
  • Projeção não mistura inclusão e exclusão, exceto _id.
  • $out precisa ser o último estágio e substitui a coleção de destino se ela já existir; use $merge se quiser só atualizar.
  • $search precisa ser o primeiro estágio do pipeline.
  • Índice composto: ordem dos campos segue a regra ESR (Equality, Sort, Range) para máxima eficiência.
  • Índice cobre a query (query covered) quando todos os campos pedidos — filtro, sort e projeção — estão no índice, evitando ida ao disco (PROJECTION_COVERED no explain()).
  • explain(): COLLSCAN = sem índice (ruim), IXSCAN = usando índice (bom).
  • Upsert só usa $setOnInsert quando de fato cria um documento novo; se o filtro já encontrar um documento, esse operador é ignorado.
  • findAndModify com new: true retorna o documento já atualizado; sem isso, retorna o estado anterior — importante em cenários de concorrência.
  • Array indexado = índice multikey automaticamente, sem sintaxe especial.

--

--