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


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”:

JAVASCRIPT
// ❌ 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

JAVASCRIPT
// ✅ 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

100%
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.

100%
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

JAVASCRIPT
// === 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.

100%
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

JAVASCRIPT
// === 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

JAVASCRIPT
// === 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

JAVASCRIPT
// === 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

JAVASCRIPT
// === 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.

100%
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

JAVASCRIPT
// === 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

JAVASCRIPT
// === 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!)

JAVASCRIPT
// === 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

JAVASCRIPT
// === 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

JAVASCRIPT
// === 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

JAVASCRIPT
// === 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

JAVASCRIPT
// === 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:

  1. As consultas de valor igual ($eq/$in) apresentam a maior seletividade e devem ser colocadas em primeiro lugar no filtro.
  2. As consultas de intervalo ($gt/$lt) são as segundas mais seletivas e devem ser colocadas após as condições de igualdade.
  3. Cada cláusula do $or deve ter suporte de índice independente
  4. $regex Os índices só podem ser usados para consultas baseadas em prefixos; em todos os outros casos, é realizada uma varredura completa da tabela.
  5. $expr Tem o pior desempenho; use apenas como último recurso
100%
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

JAVASCRIPT
// === 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

JAVASCRIPT
// === 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


📝 Exercícios

  1. Pergunta básica (⭐): Pesquise produtos da categoria “Eletrônicos” com preços entre 100 e 500 e estoque maior que 0.
  2. Questão básica (⭐): Use $in para pesquisar produtos em várias categorias (Eletrônicos/Livros/Roupas).
  3. Problema avançado (⭐⭐): Use $elemMatch para encontrar produtos nos comentários que tenham uma “avaliação >= 4 e contenham a palavra-chave ‘bom’”.
  4. Problema avançado (⭐⭐): Use $expr para consultar produtos com mais de 3 tags e uma avaliação igual ou superior a 4.
  5. 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.
Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%