MongoDB: Operadores de consulta
Última atualização: 2026-08-26
Os operadores de consulta são o cerne das consultas no MongoDB — dominar mais de 30 operadores permite lidar com 90% dos cenários de consulta.
Este curso oferece uma visão geral sistemática sobre o uso, as combinações e as técnicas de otimização de desempenho de todos os operadores de consulta.
1. O que você vai aprender
- Operadores de comparação ($eq/$ne/$gt/$lt/$gte/$lte/$in/$nin)
- Operadores lógicos ($and/$or/$not/$nor)
- Operadores de elemento ($exists/$type)
- Operadores de matriz ($all/$size/$elemMatch)
- Operadores de avaliação ($regex/$expr/$mod)
- Combinação de operadores e seu impacto no desempenho
2. A história real de um analista de dados
(1) Problema: Consultas complexas exigem instruções if-else aninhadas
Diana é uma analista de dados de comércio eletrônico que precisa encontrar produtos que atendam aos seguintes critérios: “preço entre 100 e 500, estoque > 0, tags que incluam ‘bestseller’ ou ‘novo’ e avaliação >= 4”:
// ❌ Counterexample:Query everything first, then filter
const allProducts = await Product.find();
const filtered = allProducts.filter(p =>
p.price >= 100 && p.price <= 500 &&
p.stock > 0 &&
(p.tags.includes('bestseller') || p.tags.includes('new')) &&
p.rating >= 4
);
// 100,000 Data Points, Return only 100 items,But after checking all of them
(2) Soluções para operadores do MongoDB
// ✅ Correct Example:A single query,Combining Operators
const products = await Product.find({
price: { $gte: 100, $lte: 500 },
stock: { $gt: 0 },
tags: { $in: ['bestseller', 'new'] },
rating: { $gte: 4 }
});
// Database-Level Filtering,1 million -> 100 items,Performance ↑1000x
graph TB
A[Query Operators] --> B[Comparison Operators<br/>$eq/$gt/$lt]
A --> C[Logical Operators<br/>$and/$or/$not]
A --> D[Element Operators<br/>$exists/$type]
A --> E[Array Operators<br/>$all/$size/$elemMatch]
A --> F[Evaluation Operator<br/>$regex/$expr/$mod]
style B fill:#d4edda
style E fill:#d4edda
3. Operadores de comparação
Visão geral do conceito: Os operadores de comparação são a categoria mais básica e comumente utilizada de operadores de consulta, suportando operações como igualdade, desigualdade, maior que, menor que, intervalo e correspondência de múltiplos valores. Os oito operadores de comparação cobrem 90% dos cenários de consulta do dia a dia, sendo que $in e as consultas de intervalo (a combinação $gt/$gte/$lt/$lte) são as mais utilizadas.
Como funciona: Os operadores de comparação atuam em um único campo; o MongoDB os traduz em uma varredura de índice ou em uma varredura completa da tabela. $eq e $in são os que melhor se adaptam aos índices (suportando correspondências exatas ou varreduras com múltiplos valores); consultas de intervalo ($gt/$lt) também podem usar índices, mas a eficiência depende do tamanho do intervalo. $ne e $nin não são compatíveis com índices — pois os documentos que “não são iguais a um determinado valor” podem estar espalhados por todo o índice.
graph TB
A[Comparison Operators] --> B[Equivalence Class<br/>$eq / $ne]
A --> C[Scope Class<br/>$gt / $gte / $lt / $lte]
A --> D[Multi-valued types<br/>$in / $nin]
B --> B1[Index Friendliness: $eq ✅ / $ne ⚠️]
C --> C1[Index Friendliness: ✅ Range Scan]
D --> D1[Index Friendliness: $in ✅ / $nin ⚠️]
| Operador | Significado | SQL equivalente | Compatível com índices | Frequência de uso |
|---|---|---|---|---|
$eq |
Igual a | = value |
✅ | ⭐⭐⭐ (Padrão) |
$ne |
Diferente de | != value |
⚠️ | ⭐ |
$gt |
Maior que | > value |
✅ | ⭐⭐ |
$gte |
Maior ou igual a | >= value |
✅ | ⭐⭐⭐ |
$lt |
Menor que | < value |
✅ | ⭐⭐ |
$lte |
Menor ou igual a | <= value |
✅ | ⭐⭐⭐ |
$in |
Incluído na lista | IN (...) |
✅ | ⭐⭐⭐ |
$nin |
Não incluído | NOT IN (...) |
⚠️ | ⭐ |
(1) Lista completa
| Operador | Significado | Exemplo |
|---|---|---|
$eq |
é igual a | { price: { $eq: 599 } } |
$ne |
não é igual a | { status: { $ne: 'deleted' } } |
$gt |
Maior que | { age: { $gt: 18 } } |
$gte |
Maior ou igual a | { rating: { $gte: 4 } } |
$lt |
Menor que | { stock: { $lt: 10 } } |
$lte |
Menor ou igual a | { discount: { $lte: 0.5 } } |
$in |
Incluído na matriz | { category: { $in: ['A', 'B'] } } |
$nin |
Não incluído na matriz | { status: { $nin: ['deleted', 'banned'] } } |
▶ Exemplo 1: Operadores de comparação na prática
// === Price Range ===
db.products.find({
price: { $gte: 100, $lte: 500 } // 100 <= price <= 500
});
// === Multi-value matching ===
db.products.find({
category: { $in: ['Electronics', 'Books'] }
});
// === Exclude Specific Values ===
db.users.find({
role: { $nin: ['banned', 'deleted'] }
});
4. Operadores lógicos
Explicação do conceito: Os operadores lógicos combinam várias condições de consulta para implementar a lógica AND/OR/NOT. A lógica mais comum no MongoDB é o AND implícito — { a: 1, b: 2 } é equivalente a { $and: [{ a: 1 }, { b: 2 }] }. O $and explícito deve ser usado apenas quando houver “várias condições no mesmo campo” (por exemplo, { $and: [{ price: { $gte: 100 } }, { price: { $lte: 500 } }] }).
Como funciona: $and exige que todas as subcondições sejam satisfeitas simultaneamente; o otimizador do MongoDB priorizará a execução da condição mais seletiva. $or exige que qualquer uma das subcondições seja satisfeita; o MongoDB executa consultas para cada subcondição de forma independente e, em seguida, mescla os conjuntos de resultados — o que significa que é melhor ter um índice para cada subcondição em $or, caso contrário, várias varreduras completas da tabela serão acionadas.
graph TB
A[Logical Operators] --> B[Implicit AND<br/>{ a: 1, b: 2 }<br/>Most Commonly Used ⭐⭐⭐]
A --> C[$and<br/>Multiple Conditions for the Same Field]
A --> D[$or<br/>Any that satisfies ⭐⭐]
A --> E[$not<br/>Negate ⭐]
A --> F[$nor<br/>None of the conditions are met]
style B fill:#d4edda
| Operador | Significado | SQL equivalente | Observações |
|---|---|---|---|
| AND implícito | Separado por vírgulas | WHERE a=1 AND b=2 |
Notação mais comum |
$and |
E explícito | WHERE (a=1 AND b=2) |
Deve ser usado para várias condições no mesmo campo |
$or |
Qualquer uma que satisfaça | WHERE a=1 OR b=2 |
Cada subcondição deve ter um índice |
$not |
Não compatível | WHERE NOT (cond) |
Frequentemente usado em conjunto com $regex |
$nor |
Nenhum atendido | WHERE NOT (a=1 OR b=2) |
Subutilizado |
(1) Lista completa
| Operador | Significado |
|---|---|
$and |
Todos presentes |
$or |
Qualquer um que satisfaça |
$not |
Insatisfeito |
$nor |
Nenhum encontrado |
▶ Exemplo 2: Aplicação prática dos operadores lógicos
// === Implicit $and ===
db.products.find({
category: 'Electronics',
stock: { $gt: 0 }
// equivalent to { $and: [{ category: 'Electronics' }, { stock: { $gt: 0 } }] }
});
// === Explicit $and(Multiple Conditions for the Same Field)===
db.products.find({
$and: [
{ price: { $gte: 100 } },
{ price: { $lte: 500 } }
// Must use $and,Because you cannot specify multiple conditions for the same field directly
]
});
// === $or ===
db.products.find({
$or: [
{ category: 'Electronics' },
{ tags: 'bestseller' }
]
});
// === $nor(None of them match)===
db.products.find({
$nor: [
{ category: 'Books' },
{ stock: 0 }
]
});
// Return is neither Books Categories、Items Currently in Stock
// === Nested Logic ===
db.products.find({
$and: [
{ category: 'Electronics' },
{
$or: [
{ tags: 'bestseller' },
{ rating: { $gte: 4.5 } }
]
}
]
});
5. Operadores de elementos
Explicação do conceito: Os operadores de elementos verificam a existência e o tipo dos campos em um documento — $exists determina se um campo existe, e $type determina o tipo BSON de um campo. Esses dois operadores são essenciais para verificações de qualidade de dados e limpeza de dados incorretos: $exists pode identificar documentos com campos obrigatórios ausentes, e $type pode identificar campos com tipos incorretos (como price armazenado incorretamente como um string em vez de um number).
Como funciona: $exists: true identifica todos os documentos que contêm o campo especificado (incluindo documentos em que o valor do campo é nulo), enquanto $exists: false identifica documentos que não contêm esse campo. $type realiza a correspondência com base em códigos de tipo BSON ou nomes de tipo e suporta formatos de matriz (por exemplo, { price: { $type: ["number", "decimal"] } } corresponde a Double ou Decimal128).
| Operador | Significado | Cenários típicos |
|---|---|---|
$exists: true |
O campo existe | Encontrar produtos com o campo “desconto” |
$exists: false |
O campo não existe | Encontrar usuários sem endereço de e-mail |
$type: "string" |
O tipo do campo é string | Encontrar documentos nos quais “price” foi armazenado incorretamente como uma string |
$type: ["number", "decimal"] |
Um dos vários tipos | Encontre documentos em que price seja de qualquer tipo numérico |
(1) $exists verifica se um campo existe
// === Field exists ===
db.products.find({ discount: { $exists: true } });
// Have discount Products in the Field
// === Field does not exist ===
db.users.find({ lastLoginAt: { $exists: false } });
// Users who have never logged in
// === In conjunction with other conditions ===
db.products.find({
discount: { $exists: true, $ne: null }
});
// Have discount Let's not worry about that for now null
(2) $type: Verifique o tipo do campo
// === Type Code Reference ===
// 1: Double, 2: String, 3: Object, 4: Array
// 5: Binary, 7: ObjectId, 8: Boolean, 9: Date
// 10: Null, 16: Int32, 18: Long, 19: Decimal128
// === String Type ===
db.products.find({ sku: { $type: "string" } });
// === Numeric Types(Various)===
db.products.find({ price: { $type: ["number", "decimal"] } });
// Double or Decimal128
// === Practical Applications:Identify fields with type errors ===
db.products.find({ price: { $type: "string" } });
// Find price Documents in Which Fields Were Incorrectly Stored as Strings(Frequently Asked Questions About Data Migration)
▶ Exemplo 3: Operadores de elementos em ação
// === Find "dirty" data with missing fields ===
db.users.find({
$or: [
{ email: { $exists: false } },
{ username: { $exists: false } }
]
});
// === Type Correction ===
db.products.find({ price: { $type: "string" } }).forEach(doc => {
db.products.updateOne(
{ _id: doc._id },
{ $set: { price: NumberDecimal(doc.price) } }
);
});
6. Operadores de matriz
Explicação do conceito: Os operadores de matriz são a categoria mais específica de operadores de consulta do MongoDB, projetados especificamente para lidar com campos de matriz — $all corresponde a matrizes que contêm todos os elementos especificados, $size corresponde a matrizes de um comprimento específico e $elemMatch corresponde a um único elemento em uma matriz que satisfaça várias condições simultaneamente. Dentre eles, $elemMatch é o operador de matriz mais propenso a erros e também o mais importante.
Como funciona: Por padrão, as consultas de matriz do MongoDB utilizam a “correspondência de qualquer elemento” — { tags: "5g" } corresponde a documentos em que a matriz tags contém “5g”. No entanto, em consultas com múltiplas condições, { "reviews.rating": { $gte: 4 }, "reviews.content": /good/ } pode corresponder a documentos com elementos de matriz diferentes (um comentário tem uma avaliação alta, enquanto outro contém uma palavra-chave). $elemMatch resolve esse problema — ele garante que o mesmo elemento da matriz satisfaça todas as condições simultaneamente.
graph TB
A[Array Operators] --> B[$all<br/>Includes all specified elements]
A --> C[$size<br/>Exact Match for Array Length]
A --> D[$elemMatch<br/>Multi-Condition Matching for the Same Element<br/>⭐ Most important]
D --> D1[Dot notation<br/>Different elements may match]
D --> D2[$elemMatch<br/>The same element must match]
style D fill:#d4edda
style D2 fill:#d4edda
| Operador | Significado | Sintaxe | Observações |
|---|---|---|---|
$all |
Inclui todos os elementos especificados | { tags: { $all: ["5g", "amoled"] } } |
A ordem não importa |
$size |
Correspondência exata para o comprimento da matriz | { tags: { $size: 3 } } |
Não suporta intervalos; use $expr |
$elemMatch |
Correspondência de múltiplas condições para o mesmo elemento | { reviews: { $elemMatch: { ... } } } |
Diferença em relação à notação por pontos |
(1) $all corresponde a todos os elementos
// === Must include all specified elements(Order does not matter)===
db.products.find({ tags: { $all: ['5g', 'amoled'] } });
// Includes both 5g and amoled Products
// === equivalent to $and ===
db.products.find({
$and: [
{ tags: '5g' },
{ tags: 'amoled' }
]
});
(2) $size corresponde ao comprimento da matriz
// === Exact Match for Array Length ===
db.products.find({ tags: { $size: 3 } });
// The number of tags is exactly 3
// === Unsupported Ranges,Required $expr ===
db.products.find({
$expr: { $gt: [{ $size: "$tags" }, 3] }
});
// Number of tags > 3
(3) $elemMatch: Correspondência de elemento (Chave!)
// === Scene:Check the ratings in the reviews >= 4 and contains the keyword "good" Comments on ===
db.products.find({
reviews: {
$elemMatch: {
rating: { $gte: 4 },
content: /good/i
}
}
});
// ✅ Correct:A single comment meets both conditions at the same time
// === Counterexample:Do not use $elemMatch ===
db.products.find({
"reviews.rating": { $gte: 4 },
"reviews.content": /good/i
});
// ⚠️ Error:May match different comments(One comment, high rating,Another post containing the keyword)
▶ Exemplo 4: Operadores de matriz em ação
// === Scene:Student Course Registration System ===
db.students.insertMany([
{
name: "Alice",
courses: [
{ name: "Math", score: 85 },
{ name: "Physics", score: 92 },
{ name: "Chemistry", score: 78 }
]
},
// ...
]);
// Search:Selected Math And the score >= 90 students
db.students.find({
courses: {
$elemMatch: { name: "Math", score: { $gte: 90 } }
}
});
// Search:Selected 3 Students enrolled in courses at the undergraduate level or above
db.students.find({
$expr: { $gte: [{ $size: "$courses" }, 3] }
});
// Search:All course grades are >= 80 students
db.students.find({
courses: {
$not: {
$elemMatch: { score: { $lt: 80 } }
}
}
});
7. Operadores de avaliação
Explicação do conceito: Os operadores de avaliação oferecem recursos de consulta mais flexíveis — $regex suporta correspondência por expressões regulares (busca aproximada), $expr suporta comparações entre campos usando expressões agregadas e $mod suporta operações de módulo. Esses operadores são poderosos, mas apresentam baixo desempenho e devem ser usados como “último recurso” — métodos de consulta otimizados para indexação devem ter prioridade.
Como funciona: $regex Por padrão, a indexação não é suportada (exceto para consultas ancoradas por prefixo ^pattern), portanto, todos os documentos devem ser analisados para realizar a correspondência por expressão regular. $expr Ao usar expressões de pipeline de agregação, o resultado da expressão é calculado para cada documento antes da comparação, o que também resulta em baixo desempenho. Nenhuma dessas opções deve ser usada como condição principal para consultas de alta frequência.
| Operador | Significado | Adequado para índices | Desempenho | Casos de uso |
|---|---|---|---|---|
$regex |
Correspondência por expressão regular | ⚠️ Correspondência apenas por prefixo | Lenta | Pesquisa aproximada |
$expr |
Expressão agregada | ❌ | Muito lento | Comparação entre campos |
$mod |
Operação de módulo | ❌ | Lenta | Filtragem de módulo |
(1) $regex Expressão regular
// === Simple Regular Expressions ===
db.products.find({ title: /^iPhone/ });
// Title: "iPhone" Introduction
// === Case-insensitive ===
db.products.find({ title: { $regex: 'phone', $options: 'i' } });
// === Multimode Matching ===
db.products.find({
title: { $regex: 'phone|mobile', $options: 'i' }
});
// === Performance Optimization:Regular Expression Anchoring(Avoid ^.* Wildcard)===
// ✅ Fast: db.products.find({ title: /^iPhone/ })
// ⚠️ Slow: db.products.find({ title: /iPhone/ })
(2) $expr utiliza uma expressão agregada
// === Comparison Between Fields ===
db.products.find({
$expr: { $gt: ["$discount", "$price"] }
});
// discount > price(Outlier Data)
// === Comparing Array Lengths ===
db.products.find({
$expr: { $gte: [{ $size: "$tags" }, 5] }
});
// === String Operations ===
db.products.find({
$expr: { $eq: [{ $substr: ["$title", 0, 5] }, "Hello"] }
});
(3) $mod: Módulo
// === Field-value pairs N Removing the Mold ===
db.products.find({ price: { $mod: [100, 0] } });
// The price can be 100 Divisibility by an Integer
// === Price Comparison 100 Removing the Mold = 50 ===
db.products.find({ price: { $mod: [100, 50] } });
8. Treinamento prático abrangente
Explicação do conceito: Em cenários empresariais reais, as consultas raramente utilizam um único operador — elas geralmente são combinações de vários operadores. Os princípios fundamentais para consultas combinadas são: colocar as condições mais seletivas em primeiro lugar (para reduzir a quantidade de dados analisados pelas condições subsequentes), criar índices nos campos de todas as cláusulas $or e evitar o uso de expressões agregadas complexas em $expr.
Princípios de otimização de desempenho:
- As consultas de valor igual (
$eq/$in) apresentam a maior seletividade e devem ser colocadas em primeiro lugar no filtro. - As consultas de intervalo (
$gt/$lt) são as segundas mais seletivas e devem ser colocadas após as condições de igualdade. - Cada cláusula do
$ordeve ter suporte de índice independente $regexOs índices só podem ser usados para consultas baseadas em prefixos; em todos os outros casos, é realizada uma varredura completa da tabela.$exprTem o pior desempenho; use apenas como último recurso
graph TB
A[Comprehensive Query Optimization] --> B[1. Equivalence Filtering<br/>Highest selectivity]
A --> C[2. Range Filtering<br/>Selectivity is secondary]
A --> D[3. Logic Combinations<br/>$and/$or]
A --> E[4. Sort + Pagination<br/>sort + limit]
B --> B1[{ category: 'E' }<br/>Index Scan]
C --> C1[{ price: { $gte: 100 } }<br/>Range Scan]
D --> D1[Combination of Multiple Conditions<br/>Merge Result Sets]
E --> E1[Index Sorting<br/>Avoid Memory Sorting]
style B1 fill:#d4edda
| Estratégia de otimização | Método de consulta | Requisitos de indexação | Desempenho |
|---|---|---|---|
| Ideal | Classificação por valor igual + índice | Índice composto | O(log N) |
| Bom | Equivalência + Intervalo + Índice | Índice composto | O(log N + K) |
| Geral | $or + índices de cada cláusula | Vários índices independentes | O(K * log N) |
| Ruim | Ancoragem de prefixo com $regex | Índice de prefixo | O(log N + K) |
| Caso mais desfavorável | $expr / Classificação sem indexação | Nenhum | O(N log N) |
(1) Exemplos de consultas complexas
// === Scene:Advanced Search for E-commerce ===
// Price 100-1000、Electronics or Computers、Inventory > 0、
// Tags include 'bestseller' or 'new'、Rating >= 4、Have discount
db.products.find({
$and: [
{ price: { $gte: 100, $lte: 1000 } },
{
$or: [
{ category: 'Electronics' },
{ category: 'Computers' }
]
},
{ stock: { $gt: 0 } },
{ tags: { $in: ['bestseller', 'new'] } },
{ rating: { $gte: 4 } },
{ discount: { $exists: true, $ne: null } }
]
});
▶ Exemplo 5: Comparação de desempenho entre operadoras
// === Performance Testing:100 10,000 Documents ===
// ❌ Slow: Unindexed fields + $exists
db.users.find({ lastLoginAt: { $exists: true } });
// ~500ms(Full Table Scan)
// ✅ Fast: Index Field + Range Query
db.users.find({ age: { $gte: 18, $lt: 30 } });
// ~5ms(Index Scan)
// ❌ Slow: Regular expression not anchored
db.products.find({ title: /phone/i });
// ~300ms(Full Table Scan + Regular Expression Matching)
// ✅ Fast: Regular Expression Anchoring
db.products.find({ title: /^iPhone/ });
// ~10ms(Prefix Index)
❓ Perguntas Frequentes
P: Qual é a diferença entre $in e $or? R: $in é um sinônimo sintático e é equivalente a $or.
{ field: { $in: [A, B] } }é equivalente a{ $or: [{ field: A }, { field: B }] }. Ambos têm o mesmo desempenho, mas recomenda-se usar $in por ser mais conciso.
P: Qual é a diferença entre $elemMatch e a notação por ponto? R:
{ "a.b": 1, "a.c": 2 }pode corresponder a elementos diferentes da matriz para b e c;{ a: { $elemMatch: { b: 1, c: 2 } } }exige que o mesmo elemento satisfaça ambas as condições simultaneamente.
P: Por que as consultas com expressões regulares são lentas? R: Por padrão, as expressões regulares não podem usar índices (exceto para prefixos
^pattern). As expressões regulares sem âncora exigem a varredura de todos os documentos para realizar a correspondência, o que resulta em baixo desempenho.
P: Quando se deve usar $expr? R: Quando for necessário comparar campos ou usar funções agregadas (como $size, $substr ou $cond). No entanto, $expr apresenta baixo desempenho; portanto, use consultas comuns sempre que possível.
📖 Resumo
- Operadores de comparação: $eq/$ne/$gt/$lt/$gte/$lte/$in/$nin
- Operadores lógicos: $and (implícito) / $or / $not / $nor
- Operadores de elemento: $exists (campo existe) / $type (tipo do campo)
- Operadores de matriz: $all (contém todos) / $size (comprimento) / $elemMatch (corresponde a um elemento)
- Operadores de avaliação: $regex (expressão regular) / $expr (expressão agregada) / $mod (módulo)
- Otimização de desempenho: consultas em campos indexados / prefixos de expressões regulares / como evitar o uso de $expr
📝 Exercícios
- Pergunta básica (⭐): Pesquise produtos da categoria “Eletrônicos” com preços entre 100 e 500 e estoque maior que 0.
- Questão básica (⭐): Use $in para pesquisar produtos em várias categorias (Eletrônicos/Livros/Roupas).
- Problema avançado (⭐⭐): Use $elemMatch para encontrar produtos nos comentários que tenham uma “avaliação >= 4 e contenham a palavra-chave ‘bom’”.
- Problema avançado (⭐⭐): Use $expr para consultar produtos com mais de 3 tags e uma avaliação igual ou superior a 4.
- Questão de desafio (⭐⭐⭐): Crie consultas complexas (combinações de 5 ou mais operadores), incluindo AND/OR/NOT, $elemMatch e âncoras $regex, para testar diferenças de desempenho.