W3docs

Consultas MongoDB em Python: Filtros, Operadores e Projeção

Aprenda a consultar o MongoDB com Python e pymongo — filtre documentos, use operadores de comparação e lógicos, projete campos e pagine resultados.

Este capítulo explica como construir consultas no MongoDB usando o driver pymongo do Python. Você aprenderá a filtrar documentos com correspondências exatas e operadores de comparação, combinar condições com operadores lógicos, selecionar apenas os campos necessários com projeção, e paginar resultados com skip() e limit().

Se você ainda não configurou uma conexão, consulte MongoDB Get Started e MongoDB Create Collection primeiro.

Configuração dos Dados de Exemplo

Todos os exemplos deste capítulo utilizam a mesma coleção customers. Execute este trecho uma vez para populá-la:

import pymongo

client = pymongo.MongoClient("mongodb://localhost:27017/")
db = client["mystore"]
col = db["customers"]

# Drop and re-create so examples are repeatable
col.drop()
col.insert_many([
    {"name": "Alice", "age": 30, "city": "London",   "score": 88},
    {"name": "Bob",   "age": 25, "city": "New York",  "score": 74},
    {"name": "Carol", "age": 35, "city": "London",   "score": 91},
    {"name": "Dave",  "age": 28, "city": "Berlin",    "score": 65},
    {"name": "Eve",   "age": 22, "city": "New York",  "score": 77},
])
print("Sample data inserted.")

Consultando Todos os Documentos

Chamar find() com um filtro vazio ({}) retorna todos os documentos da coleção:

for doc in col.find({}):
    print(doc)
# {'_id': ..., 'name': 'Alice', 'age': 30, 'city': 'London',   'score': 88}
# {'_id': ..., 'name': 'Bob',   'age': 25, 'city': 'New York',  'score': 74}
# ...

Use find_one() quando precisar apenas do primeiro documento correspondente:

doc = col.find_one({"city": "London"})
print(doc)
# {'_id': ..., 'name': 'Alice', 'age': 30, 'city': 'London', 'score': 88}

find_one() retorna None se nenhum documento corresponder — verifique sempre isso antes de acessar os campos.

Filtros de Correspondência Exata

Passe um dicionário para find() para corresponder documentos em que um campo seja igual a um valor específico:

# All customers in London
results = col.find({"city": "London"})
for doc in results:
    print(doc["name"], doc["city"])
# Alice London
# Carol London

Múltiplas chaves no mesmo dicionário de filtro funcionam como um AND implícito — ambas as condições devem ser verdadeiras:

# Customers in London AND older than 30
results = col.find({"city": "London", "age": {"$gt": 30}})
for doc in results:
    print(doc["name"], doc["age"])
# Carol 35

Operadores de Comparação

Os operadores de comparação do MongoDB permitem corresponder documentos em que um campo esteja dentro de um intervalo ou conjunto. Todos os operadores são prefixados com $.

OperadorSignificadoExemplo de filtro
$eqIgual a{"age": {"$eq": 30}}
$neDiferente de{"city": {"$ne": "London"}}
$gtMaior que{"score": {"$gt": 80}}
$gteMaior ou igual a{"score": {"$gte": 80}}
$ltMenor que{"age": {"$lt": 28}}
$lteMenor ou igual a{"age": {"$lte": 28}}
$inEm uma lista{"city": {"$in": ["London", "Berlin"]}}
$ninNão está em uma lista{"city": {"$nin": ["London"]}}

Exemplo — clientes com pontuação acima de 80:

results = col.find({"score": {"$gt": 80}})
for doc in results:
    print(doc["name"], doc["score"])
# Alice 88
# Carol 91

Exemplo — clientes com idade entre 25 e 30 (inclusive):

results = col.find({"age": {"$gte": 25, "$lte": 30}})
for doc in results:
    print(doc["name"], doc["age"])
# Alice 30
# Bob   25
# Dave  28

Você pode empilhar múltiplos operadores no mesmo campo dentro de um único dicionário, como mostrado acima.

Exemplo — clientes em Londres ou Berlim:

results = col.find({"city": {"$in": ["London", "Berlin"]}})
for doc in results:
    print(doc["name"], doc["city"])
# Alice London
# Carol London
# Dave  Berlin

Operadores Lógicos

Use $and, $or e $nor quando precisar combinar condições de maneiras que as chaves simples de dicionário não conseguem expressar.

$or — pelo menos uma condição deve corresponder

# Customers younger than 25 OR with a score above 90
results = col.find({"$or": [{"age": {"$lt": 25}}, {"score": {"$gt": 90}}]})
for doc in results:
    print(doc["name"], doc["age"], doc["score"])
# Carol 35 91
# Eve   22 77

$and — use ao aplicar dois operadores diferentes ao mesmo campo

O AND implícito (múltiplas chaves) não funciona quando você precisa de dois operadores $ no mesmo campo. Use $and em vez disso:

# Customers whose score is > 65 AND < 90
# (cannot use {"score": {"$gt": 65}, "score": {"$lt": 90}} — duplicate key)
results = col.find({"$and": [{"score": {"$gt": 65}}, {"score": {"$lt": 90}}]})
for doc in results:
    print(doc["name"], doc["score"])
# Alice 88
# Bob   74
# Eve   77

$nor — nenhuma das condições deve corresponder

# Customers who are NOT in London AND do NOT have score > 80
results = col.find({"$nor": [{"city": "London"}, {"score": {"$gt": 80}}]})
for doc in results:
    print(doc["name"], doc["city"], doc["score"])
# Bob  New York 74
# Dave Berlin   65
# Eve  New York 77

$not — negar uma expressão de campo único

$not envolve uma única expressão de operador e retorna documentos em que a condição é falsa ou o campo não existe:

# Customers who do NOT have a score greater than 80
results = col.find({"score": {"$not": {"$gt": 80}}})
for doc in results:
    print(doc["name"], doc["score"])
# Bob  74
# Dave 65
# Eve  77

Filtros com Expressões Regulares

Use o operador $regex (ou passe um padrão re compilado) para fazer correspondência de substring ou padrão em campos string:

import re

# Customers whose name starts with a vowel
results = col.find({"name": {"$regex": "^[AEIOU]", "$options": "i"}})
for doc in results:
    print(doc["name"])
# Alice
# Eve

$options: "i" torna a correspondência insensível a maiúsculas e minúsculas. Evite padrões com curinga no início, como .*text, em coleções grandes — eles não podem usar um índice e realizarão uma varredura completa da coleção.

Projeção — Retornando Apenas Campos Específicos

Por padrão, find() retorna todos os campos do documento, incluindo _id. Use um segundo argumento (a projeção) para incluir ou excluir campos.

Incluir campos específicos

Passe 1 para cada campo desejado. Somente esses campos (mais _id) são retornados:

# Return only name and score
results = col.find({}, {"name": 1, "score": 1})
for doc in results:
    print(doc)
# {'_id': ..., 'name': 'Alice', 'score': 88}
# {'_id': ..., 'name': 'Bob',   'score': 74}
# ...

Excluir campos específicos

Passe 0 para cada campo que deseja ocultar. Todos os outros campos são retornados:

# Hide _id and city
results = col.find({}, {"_id": 0, "city": 0})
for doc in results:
    print(doc)
# {'name': 'Alice', 'age': 30, 'score': 88}
# {'name': 'Bob',   'age': 25, 'score': 74}
# ...

Você não pode misturar 1 e 0 na mesma projeção (exceto para _id, que sempre pode ser definido como 0 junto com inclusões).

Ordenando Resultados

Encadeie .sort() no cursor para ordenar os resultados. Use pymongo.ASCENDING (1) ou pymongo.DESCENDING (-1):

import pymongo

# Sort by score descending
results = col.find({}, {"_id": 0, "name": 1, "score": 1}).sort("score", pymongo.DESCENDING)
for doc in results:
    print(doc["name"], doc["score"])
# Carol 91
# Alice 88
# Eve   77
# Bob   74
# Dave  65

Passe uma lista de tuplas (campo, direção) para ordenar por múltiplos campos:

# Sort by city ascending, then by age descending within each city
results = col.find({}, {"_id": 0, "name": 1, "city": 1, "age": 1}).sort(
    [("city", pymongo.ASCENDING), ("age", pymongo.DESCENDING)]
)
for doc in results:
    print(doc["city"], doc["name"], doc["age"])
# Berlin  Dave  28
# London  Carol 35
# London  Alice 30
# New York Bob   25   <- Bob (25) vs Eve (22): descending so 25 first
# New York Eve   22

Consulte MongoDB Sort para uma análise mais aprofundada das opções de ordenação.

Limitando e Paginando Resultados

limit()

limit(n) interrompe o cursor após retornar n documentos:

# Top 3 by score
results = col.find({}, {"_id": 0, "name": 1, "score": 1}).sort("score", -1).limit(3)
for doc in results:
    print(doc["name"], doc["score"])
# Carol 91
# Alice 88
# Eve   77

skip() para paginação

Combine skip() e limit() para implementar uma navegação simples página a página:

page_size = 2
page = 1  # zero-indexed

results = (
    col.find({}, {"_id": 0, "name": 1, "score": 1})
       .sort("score", -1)
       .skip(page * page_size)
       .limit(page_size)
)
for doc in results:
    print(doc["name"], doc["score"])
# Eve  77   (page 1, items 3–4 of the sorted list)
# Bob  74

Para coleções grandes, prefira a paginação baseada em intervalo — filtre pelo último _id visto ou por um timestamp — porque skip() ainda varre os documentos ignorados internamente.

Consulte MongoDB Limit para mais detalhes.

Contando Documentos

Use count_documents() com o mesmo dicionário de filtro para contar sem buscar dados:

total = col.count_documents({})
london = col.count_documents({"city": "London"})
print(f"Total: {total}, In London: {london}")
# Total: 5, In London: 2

Evite o cursor.count() obsoleto — ele foi removido no PyMongo 4.

Armadilhas Comuns

Os cursores do PyMongo são esgotados após a iteração. Uma vez que você percorre um cursor, ele fica vazio. Armazene os resultados em uma lista se precisar iterar mais de uma vez:

docs = list(col.find({"city": "London"}))
print(len(docs))   # 2
print(docs[0]["name"])  # Alice

_id é um ObjectId, não uma string. Se você armazenar um _id como string e depois tentar consultá-lo, a consulta não retornará nada. Importe ObjectId de bson para converter:

from bson import ObjectId

doc = col.find_one({"_id": ObjectId("665000000000000000000001")})

As consultas diferenciam maiúsculas de minúsculas por padrão. {"city": "london"} não corresponderá a documentos armazenados como "London". Use $regex com $options: "i" para correspondência insensível a maiúsculas, ou normalize os valores no momento da inserção.

Próximos Passos

Was this page helpful?