Olá, dev! Seja bem-vindo ao Dia 03 da sua trilha para a certificação MongoDB Associate Developer. Hoje estudaremos minuciosamente as operações de modificação (Update) e exclusão (Delete) de documentos, com foco especial na atomicidade e no manuseio eficiente de coleções e arrays.
1. Métodos de Atualização: `updateOne()`, `updateMany()` e `replaceOne()`
No MongoDB, atualizações são divididas por escopo e intenção:
db.collection.updateOne(filter, update, options): Modifica o primeiro documento que atende aos critérios do filtro.db.collection.updateMany(filter, update, options): Modifica todos os documentos que atendem aos critérios do filtro.db.collection.replaceOne(filter, replacement, options): Substitui todo o documento mantendo apenas o campo_idimutável. Não aceita operadores de atualização como$set.
2. Operadores de Modificação de Campos
A. `$set` e `$unset`
O operador $set substitui o valor de um campo. Se o campo não existir, ele é criado automaticamente. O operador $unset remove completamente um campo do documento.
// Adiciona ou atualiza o campo cargo e remove o campo temporario
db.developers.updateOne(
{ email: "dev@exemplo.com" },
{
$set: { cargo: "Senior Backend Developer", nivel: "Pleno" },
$unset: { campoTemporario: "" }
}
)
B. `$inc`, `$mul`, `$min` e `$max`
$inc: Incrementa ou decrementa (se passar valor negativo) um campo numérico de forma atômica. Ideal para contadores concorrentes.$mul: Multiplica o valor numérico de um campo pelo fator especificado.$min/$max: Atualiza o campo apenas se o novo valor for menor que o valor atual (para$min) ou maior (para$max).
// Incrementa tentativas em 1 e atualiza o maiorScore apenas se 950 for maior que o valor atual
db.developers.updateOne(
{ _id: ObjectId("64f8a12b9c3e2f1a8b4d5e6f") },
{
$inc: { "estatisticas.tentativasSimulado": 1 },
$max: { "estatisticas.maiorScore": 950 }
}
)
C. `$rename` e `$currentDate`
$rename altera o nome do campo. $currentDate define um campo para a data/hora atual (tipo Date ou Timestamp).
db.developers.updateOne(
{ email: "dev@exemplo.com" },
{
$rename: { "dataMatricula": "dataInscricao" },
$currentDate: { ultimaAtualizacao: true }
}
)
3. Manipulação Avançada de Arrays em Documentos
Arrays no MongoDB possuem operadores altamente otimizados para evitar a leitura e reescrita completa do documento no lado da aplicação.
A. `$push` com Modificadores (`$each`, `$slice`, `$sort`, `$position`)
O $push adiciona elementos ao final do array. Ao combinar com identificadores adicionais:
// Adiciona múltiplos itens, ordena em ordem decrescente e retém apenas os 5 maiores valores
db.developers.updateOne(
{ email: "dev@exemplo.com" },
{
$push: {
notasSimulados: {
$each: [92, 88, 96],
$sort: -1,
$slice: 5
}
}
}
)
B. `$addToSet`, `$pop` e `$pull`
$addToSet: Adiciona elementos ao array apenas se o valor ainda não existir no array (comportamento de conjunto/Set único).$pop: Remove o primeiro elemento ({ $pop: { array: -1 } }) ou o último elemento ({ $pop: { array: 1 } }).$pull: Remove todos os itens do array que satisfazem uma condição.
// Garante que a habilidade "Go" seja adicionada sem duplicatas e remove a habilidade descontinuada "Perl"
db.developers.updateOne(
{ email: "dev@exemplo.com" },
{
$addToSet: { habilidades: "Go" },
$pull: { habilidades: "Perl" }
}
)
C. Operador Posicional `$`
Permite atualizar o primeiro elemento do array que corresponda aos critérios de busca da consulta sem precisar saber o índice exato.
// Atualiza o status do curso "MongoDB Basics" para "Concluído"
db.developers.updateOne(
{ "cursos.nome": "MongoDB Basics" },
{ $set: { "cursos.$.status": "Concluído" } }
)
4. O Comportamento Upsert (`upsert: true`)
Quando a opção { upsert: true } é informada:
- Se um documento corresponder ao filtro, a atualização é realizada normalmente.
- Se nenhum documento for encontrado, o MongoDB cria um novo documento combinando os campos do filtro de busca com os campos do operador de atualização.
O Operador `$setOnInsert`
Define campos que devem ser gravados somente se a operação resultar em uma nova inserção (Upsert). Caso o documento já exista, o bloco $setOnInsert é ignorado.
db.developers.updateOne(
{ email: "novo.aluno@empresa.com" },
{
$set: { ativo: true },
$setOnInsert: {
dataCriacaoConta: new Date(),
pontosIniciais: 100
}
},
{ upsert: true }
)
5. Operações de Remoção e Performance
deleteOne(filter): Apaga o primeiro documento correspondente.deleteMany(filter): Apaga todos os documentos correspondentes.
Se o objetivo for apagar todos os documentos de uma coleção, utilizar
db.collection.drop() é drasticamente mais rápido do que db.collection.deleteMany({}).Isso ocorre porque
deleteMany({}) remove os documentos um por um e atualiza os índices no arquivo do WiredTiger e gera logs no oplog, enquanto drop() simplesmente remove a coleção, suas tabelas no sistema de arquivos e todos os seus índices associados instantaneamente.
6. Questões no Estilo Exame de Certificação
Questão 1: Qual a combinação correta de modificadores com o operador $push para garantir que um array não ultrapasse o limite de 10 elementos mantendo apenas os mais recentes?
A) $push: { historico: { $each: [novoItem], $limit: 10 } }
B) $push: { historico: { $each: [novoItem], $slice: -10 } }
C) $push: { historico: { $each: [novoItem], $trim: 10 } }
D) $push: { historico: [novoItem], $slice: 10 }
Resposta Correta: B. O modificador $slice: -10 mantém apenas os últimos 10 elementos do array durante o $push com $each.
Questão 2: Um desenvolvedor deseja atualizar o campo ultimaVisualizacao de um documento se ele existir, mas caso o documento precise ser criado via upsert, ele quer também definir o campo dataCriacao. Qual operador atinge esse objetivo?
A) `$init`
B) `$setOnInsert`
C) `$onCreate`
D) `$upsertOnly`
Resposta Correta: B) `$setOnInsert`. Este operador especifica os valores que serão inseridos exclusivamente se o `upsert` criar um novo documento.