- União de coleções por período
Para consultar documentos espalhados por várias coleções — por exemplo, uma coleção por trimestre — utilize $unionWith combinado com $set para identificar a origem de cada grupo.
db.vendas_2023_q1.aggregate([
{ $set: { origem: "2023_q1" } },
{
$unionWith: {
coll: "vendas_2023_q2",
pipeline: [{ $set: { origem: "2023_q2" } }]
}
}
])
- Agrupamento por múltiplos campos
No estágio $group, atribua aliases para cada chave do documento _id. Quando precisar referenciar o resultado em um novo $group, use a notação $_id.alias.
db.vendas_2023.aggregate([
{ $set: { origem: "2023" } },
{
$unionWith: {
coll: "vendas_2022",
pipeline: [{ $set: { origem: "2022" } }]
}
},
{
$match: {
codigo_loja: "L00002",
categoria: { $in: [1, 2, 3] },
data_registro: { $gte: "2023-01-01", $lte: "2023-10-13" }
}
},
{
$project: {
data_registro: 1,
ano: { $substr: ["$data_registro", 0, 4] },
quantidade: 1,
previsto: 1,
duracao: 1
}
},
{
$group: {
_id: { data_registro: "$data_registro", ano: "$ano" },
total_quantidade: { $sum: "$quantidade" },
total_previsto: { $sum: "$previsto" },
media_duracao: { $avg: "$duracao" }
}
},
{
$group: {
_id: "$_id.ano",
total_quantidade: { $sum: "$total_quantidade" },
total_previsto: { $sum: "$total_previsto" },
media_duracao: { $avg: "$media_duracao" }
}
},
{
$project: {
total_quantidade: 1,
media_duracao: { $round: [{ $divide: ["$media_duracao", 60] }, 2] },
taxa_conversao: {
$round: [
{ $divide: ["$total_quantidade", { $add: ["$total_quantidade", "$total_previsto"] }] },
4
]
}
}
},
{ $sort: { _id: 1 } }
])
- Múltiplos estágios
$groupno mesmo pipeline
É comum encadear vários $group quando se precisa de granularidades diferentes. $match e $project podem aparecer em qualquer posição do pipeline.
db.vendas_2023.aggregate([
{ $set: { origem: "2023" } },
{
$unionWith: {
coll: "vendas_2022",
pipeline: [{ $set: { origem: "2022" } }]
}
},
{
$match: {
codigo_loja: "L001",
categoria: { $in: [2, 3, 4] },
data_registro: { $gte: "2023-01-01", $lte: "2023-10-13" }
}
},
{
$project: {
data_registro: 1,
semana_iso: {
$isoWeek: {
date: { $dateFromString: { dateString: "$data_registro" } },
timezone: "America/Sao_Paulo"
}
},
quantidade: 1,
custo: 1
}
},
{
$group: {
_id: { data_registro: "$data_registro", semana_iso: "$semana_iso" },
total_dia: { $sum: "$quantidade" }
}
},
{
$group: {
_id: "$_id.semana_iso",
total_semana: { $sum: "$total_dia" },
media_diaria: { $avg: "$total_dia" }
}
},
{
$project: {
_id: 1,
total_semana: 1,
media_diaria: { $round: ["$media_diaria", 0] }
}
},
{ $sort: { _id: 1 } }
])
- Desmembramento de arrays com
$unwind
Use $unwind para transformar cada elemento de um array em um documento separado. Os campos internos são acessados com $nomeArray.campo.
db.vendas_2023.aggregate([
{ $set: { origem: "2023" } },
{
$unionWith: {
coll: "vendas_2022",
pipeline: [{ $set: { origem: "2022" } }]
}
},
{
$match: {
codigo_produto: "P001",
data_registro: { $gte: "2022-12-02", $lte: "2023-10-08" }
}
},
{ $unwind: "$detalhes_estadia" },
{
$group: {
_id: "$detalhes_estadia.faixa_tempo",
total_ocorrencias: { $sum: "$detalhes_estadia.ocorrencias" }
}
},
{ $project: { _id: 1, total_ocorrencias: 1 } },
{ $sort: { _id: 1 } }
])
- Acesso a propriedades de objetos
Para ler um atributo de um objeto, utilize a notação de ponto: $nomeObjeto.atributo.
db.vendas_2023.aggregate([
{
$match: {
codigo_produto: "P001",
data_registro: { $gte: "2023-01-01", $lte: "2023-03-13" }
}
},
{
$group: {
_id: "$data_registro",
um: { $sum: "$classificacao.um" },
dois: { $sum: "$classificacao.dois" },
tres: { $sum: "$classificacao.tres" },
quatro_ou_mais: { $sum: "$classificacao.quatro_ou_mais" }
}
},
{ $sort: { _id: 1 } }
])
Ordenação por múltiplos campos:
{ $sort: { codigo_produto: 1, mes: 1 } }
- Acumuladores após
$group
$max: maior valor$min: menor valor$sum: soma$avg: média$first: primeiro documento do grupo$last: último documento do grupo
// Maior valor
{ $group: { _id: null, ultima_atualizacao: { $max: "$data_atualizacao" } } }
// Primeiro documento de cada dia
db.vendas.aggregate([
{
$match: {
codigo_cidade: "320100",
data_hora: {
$gte: "2023-05-01T00:00:00",
$lte: "2023-07-13T23:59:59"
}
}
},
{ $sort: { data_hora: -1 } },
{
$group: {
_id: { dia: { $substr: ["$data_hora", 0, 10] } },
valor: { $first: "$valor" }
}
},
{
$project: {
_id: "$_id.dia",
valor: 1
}
},
{ $sort: { _id: 1 } }
])
$sort pode ser utilizado várias vezes e em qualquer ponto do pipeline.
- Operadores lógicos:
$not,$and,$ore$nor
$not: negação$and: conjunção$or: disjunção$nor: nenhuma das condições é verdadeira
// $not
db.usuarios.find({ idade: { $ne: 18 } })
db.usuarios.find({ idade: { $not: { $eq: 18 } } })
// $or
{
$or: [
{ origem: { $in: ["2"] } },
{ destino: { $in: ["2"] } }
]
}
// $nor
{
$nor: [
{ origem: { $in: ["18", "19", "20", "21"] } },
{ destino: { $in: ["18", "19", "20", "21"] } }
]
}
// Combinação em $match
{
$match: {
data: { $gte: "2023-08-05", $lte: "2023-09-28" },
loja: "L00001",
$or: [
{ origem: { $in: ["2"] } },
{ destino: { $in: ["2"] } }
],
$nor: [
{ origem: { $in: ["18", "19", "20", "21"] } },
{ destino: { $in: ["18", "19", "20", "21"] } }
],
sexo: { $in: [0, 1] }
}
}
- Condicional com
$cond
Sintaxe:
{ $cond: { if: <expressao-booleana>, then: <caso-positivo>, else: <caso-negativo> } }
Se a expressão for verdadeira, retorna then; caso contrário, retorna else.
db.produtos.aggregate([
{
$project: {
item: 1,
desconto: {
$cond: {
if: { $gte: ["$estoque", 250] },
then: 30,
else: 20
}
}
}
}
])
// Resultado:
// { _id: 1, item: "abc1", desconto: 30 }
// { _id: 2, item: "abc2", desconto: 20 }
// { _id: 3, item: "xyz1", desconto: 30 }
- Operadores aritméticos
$add: adição$subtract: subtração$multiply: multiplicação$divide: divisão$mod: módulo (resto)
taxa_conversao: {
$round: [
{ $divide: ["$quantidade", { $add: ["$quantidade", "$previsao"] }] },
4
]
}
indice: {
$round: [
{ $divide: ["$total_quantidade", { $multiply: [56, 5] }] },
2
]
}
$strLenCP
Retorna a quantidade de caracteres Unicode (UTF-8) de uma string, contando cada caractere como uma unidade.
{ $strLenCP: "Hello World!" } // 12
{ $strLenCP: "" } // 0
{ $strLenCP: "寿司" } // 2
$sizepara arrays
db.colecao.find({ tags: { $size: 2 } })
- Atualização de campos
Atualizando um elemanto de array com base em uma condição:
db.colecao.update(
{
codigo: "P00001",
tipo: { $in: [0] },
data_registro: { $gte: "2023-10-07" },
"itens.categoria": 6
},
{ $set: { "itens.$.quantidade": 33 } }
)
Atualizando um atributo de objeto:
db.colecao.update(
{
codigo: "P00001",
tipo: { $in: [0] },
data_registro: { $gte: "2023-10-07" }
},
{ $set: { "classificacao.um": 121 } }
)
- Expressões regulares com
$regex
// Começa com P00001
db.colecao.aggregate([
{ $match: { codigo: { $regex: /^P00001/ } } }
])
// Termina com S00401
db.colecao.aggregate([
{ $match: { codigo: { $regex: /S00401$/ } } }
])
// Ignorando maiúsculas/minúsculas
db.colecao.aggregate([
{ $match: { codigo: { $regex: /^P00001/i } } }
])
- Contagem de valores distintos por grupo
Para contar quantos valores distintos de um campo existem em cada grupo, utilize $addToSet para criar um conjunto sem repetições e depois $size para obter a cardinalidade.
db.vendas_2024_3.aggregate([
{ $unwind: "$transacoes" },
{
$project: {
origem: "$transacoes.origem",
local: "$transacoes.local_id",
destino: "$transacoes.destino",
cliente: "$cliente_id",
data: "$data"
}
},
{
$match: {
data: { $gte: "2024-03-14", $lte: "2024-04-05" },
destino: { $in: ["unkn", "101", "102", "103", "104", "105"] },
local: { $in: ["unkn", "101", "102", "103", "104", "105"] },
origem: "101"
}
},
{
$group: {
_id: { origem: "$origem", local: "$local", destino: "$destino" },
clientes_unicos: { $addToSet: "$cliente" }
}
},
{
$project: {
_id: 0,
origem: "$_id.origem",
local: "$_id.local",
destino: "$_id.destino",
total_distintos: { $size: "$clientes_unicos" }
}
}
])
A abordagem com $addToSet remove duplicidades antes da contagem, diferente de { $sum: 1 }, que contaria linhas repetidas.