W3docs

MongoDB Find

Aprende a recuperar documentos de MongoDB con Python usando find_one(), find(), proyecciones, operadores de consulta, sort, skip y limit con PyMongo.

Este capítulo explica cómo recuperar documentos de una colección MongoDB usando el driver pymongo de Python. Aprenderás los métodos find_one() y find(), cómo filtrar resultados con operadores de consulta, cómo controlar qué campos se devuelven mediante proyecciones y cómo ordenar, omitir y limitar resultados.

Configuración inicial

Asegúrate de que pymongo esté instalado antes de ejecutar cualquier ejemplo:

pip install pymongo

Todos los ejemplos a continuación asumen un servidor MongoDB activo en mongodb://localhost:27017/. Para seguirlos en tu propia máquina, inicia MongoDB con mongod o usa un clúster gratuito en la nube (MongoDB Atlas).

Preparación de datos de muestra

Los ejemplos de este capítulo utilizan una colección customers que contiene estos cinco documentos. Ejecuta esto una vez para poblarla:

import pymongo

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

# Insert sample documents (skip if already inserted)
col.drop()  # start fresh
col.insert_many([
    {"name": "Alice",   "age": 28, "city": "London"},
    {"name": "Bob",     "age": 34, "city": "Paris"},
    {"name": "Carol",   "age": 22, "city": "London"},
    {"name": "David",   "age": 40, "city": "Berlin"},
    {"name": "Eve",     "age": 34, "city": "Paris"},
])
print("Sample data ready.")

Salida esperada:

Sample data ready.

PyMongo añade automáticamente un campo _id único (un bson.ObjectId) a cada documento que no tenga uno previamente.

Recuperar un único documento con find_one()

find_one() devuelve el primer documento que coincide con el filtro, o None si ninguno coincide. Es la opción correcta cuando esperas exactamente un resultado (por ejemplo, al buscar un usuario por correo electrónico).

# Retrieve the first document in the collection
doc = col.find_one()
print(doc)
# {'_id': ObjectId('...'), 'name': 'Alice', 'age': 28, 'city': 'London'}

Pasa un filtro para encontrar un documento específico:

# Find the customer named Bob
bob = col.find_one({"name": "Bob"})
print(bob)
# {'_id': ObjectId('...'), 'name': 'Bob', 'age': 34, 'city': 'Paris'}

Si ningún documento coincide, find_one() devuelve None, por lo que siempre debes protegerte contra esto:

result = col.find_one({"name": "Zara"})
if result is None:
    print("No document found.")

Recuperar múltiples documentos con find()

find() devuelve un cursor — un iterador perezoso sobre todos los documentos que coinciden. Nada se obtiene del servidor hasta que iteras.

Recuperar todos los documentos

# Iterate every document in the collection
for doc in col.find():
    print(doc["name"], doc["age"])

Salida esperada (el orden puede variar sin una ordenación explícita):

Alice 28
Bob 34
Carol 22
David 40
Eve 34

Filtrar con coincidencia exacta

Pasa un diccionario como primer argumento a find():

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

Proyecciones — elegir qué campos devolver

Por defecto, MongoDB devuelve todos los campos, incluido _id. Una proyección te permite incluir o excluir campos específicos, lo que reduce el tráfico de red y el uso de memoria.

Pasa la proyección como segundo argumento posicional (o argumento de palabra clave projection):

# Return only name and city; suppress _id
for doc in col.find({}, {"_id": 0, "name": 1, "city": 1}):
    print(doc)
# {'name': 'Alice', 'city': 'London'}
# {'name': 'Bob',   'city': 'Paris'}
# ...

Reglas para las proyecciones:

  • Usa 1 para incluir un campo, 0 para excluirlo.
  • No puedes mezclar inclusión y exclusión en la misma proyección, excepto para _id (que siempre puede establecerse explícitamente en 0).

Operadores de consulta

MongoDB proporciona un amplio conjunto de operadores para filtrar documentos. Pásalos dentro del diccionario de filtro.

Operadores de comparación

OperadorSignificadoEjemplo
$eqIgual (por defecto){"age": {"$eq": 34}}
$neDistinto{"city": {"$ne": "Paris"}}
$gtMayor que{"age": {"$gt": 30}}
$gteMayor o igual que{"age": {"$gte": 34}}
$ltMenor que{"age": {"$lt": 30}}
$lteMenor o igual que{"age": {"$lte": 28}}
$inValor en lista{"city": {"$in": ["London", "Berlin"]}}
$ninValor no en lista{"city": {"$nin": ["Paris"]}}

Ejemplo — clientes mayores de 30 años:

for doc in col.find({"age": {"$gt": 30}}, {"_id": 0, "name": 1, "age": 1}):
    print(doc)
# {'name': 'Bob',   'age': 34}
# {'name': 'David', 'age': 40}
# {'name': 'Eve',   'age': 34}

Ejemplo — clientes en Londres o Berlín:

for doc in col.find(
    {"city": {"$in": ["London", "Berlin"]}},
    {"_id": 0, "name": 1, "city": 1}
):
    print(doc)
# {'name': 'Alice', 'city': 'London'}
# {'name': 'Carol', 'city': 'London'}
# {'name': 'David', 'city': 'Berlin'}

Operadores lógicos

AND implícito — proporcionar múltiples claves en un único diccionario de filtro significa que todas las condiciones deben coincidir:

# Age > 30 AND city is Paris
for doc in col.find({"age": {"$gt": 30}, "city": "Paris"}, {"_id": 0}):
    print(doc)
# {'name': 'Bob', 'age': 34, 'city': 'Paris'}
# {'name': 'Eve', 'age': 34, 'city': 'Paris'}

$and es necesario cuando debes aplicar dos condiciones diferentes al mismo campo:

# Age between 28 (inclusive) and 40 (exclusive)
query = {"$and": [{"age": {"$gte": 28}}, {"age": {"$lt": 40}}]}
for doc in col.find(query, {"_id": 0, "name": 1, "age": 1}):
    print(doc)
# {'name': 'Alice', 'age': 28}
# {'name': 'Bob',   'age': 34}
# {'name': 'Eve',   'age': 34}

$or — al menos una condición debe coincidir:

# City is Berlin OR age is 22
for doc in col.find(
    {"$or": [{"city": "Berlin"}, {"age": 22}]},
    {"_id": 0, "name": 1}
):
    print(doc)
# {'name': 'Carol'}
# {'name': 'David'}

Coincidencia de patrones con $regex

Usa $regex para hacer coincidir campos de texto con una expresión regular:

# Names that start with the letter 'C' or 'E' (case-sensitive)
for doc in col.find({"name": {"$regex": "^[CE]"}}, {"_id": 0, "name": 1}):
    print(doc)
# {'name': 'Carol'}
# {'name': 'Eve'}

Para coincidencia sin distinguir mayúsculas, añade $options: "i":

for doc in col.find(
    {"city": {"$regex": "london", "$options": "i"}},
    {"_id": 0, "name": 1, "city": 1}
):
    print(doc)
# {'name': 'Alice', 'city': 'London'}
# {'name': 'Carol', 'city': 'London'}

Ordenar resultados

Encadena .sort() en el cursor. Pasa el nombre del campo y una constante de dirección:

  • pymongo.ASCENDING (o 1) — A → Z, de menor a mayor
  • pymongo.DESCENDING (o -1) — Z → A, de mayor a menor
# Sort by age ascending
for doc in col.find({}, {"_id": 0, "name": 1, "age": 1}).sort("age", pymongo.ASCENDING):
    print(doc)
# {'name': 'Carol', 'age': 22}
# {'name': 'Alice', 'age': 28}
# {'name': 'Bob',   'age': 34}
# {'name': 'Eve',   'age': 34}
# {'name': 'David', 'age': 40}

Ordena por múltiples campos pasando una lista de tuplas (campo, dirección):

# Sort by age descending, then by name ascending (tiebreak)
order = [("age", pymongo.DESCENDING), ("name", pymongo.ASCENDING)]
for doc in col.find({}, {"_id": 0, "name": 1, "age": 1}).sort(order):
    print(doc)
# {'name': 'David', 'age': 40}
# {'name': 'Bob',   'age': 34}
# {'name': 'Eve',   'age': 34}
# {'name': 'Alice', 'age': 28}
# {'name': 'Carol', 'age': 22}

Limitar resultados

.limit(n) limita el número de documentos devueltos. Es útil para mostrar los N mejores resultados.

# Top 3 youngest customers
for doc in col.find({}, {"_id": 0, "name": 1, "age": 1}).sort("age", 1).limit(3):
    print(doc)
# {'name': 'Carol', 'age': 22}
# {'name': 'Alice', 'age': 28}
# {'name': 'Bob',   'age': 34}

Omitir documentos (paginación)

.skip(n) omite los primeros n documentos. Combinado con .limit(), permite la paginación basada en páginas:

PAGE_SIZE = 2

def get_page(page_number):
    """Return one page of customers sorted by age (page_number is 0-indexed)."""
    return list(
        col.find({}, {"_id": 0, "name": 1, "age": 1})
           .sort("age", pymongo.ASCENDING)
           .skip(page_number * PAGE_SIZE)
           .limit(PAGE_SIZE)
    )

print(get_page(0))  # [{'name': 'Carol', 'age': 22}, {'name': 'Alice', 'age': 28}]
print(get_page(1))  # [{'name': 'Bob', 'age': 34},   {'name': 'Eve', 'age': 34}]
print(get_page(2))  # [{'name': 'David', 'age': 40}]

Para colecciones grandes, prefiere la paginación basada en cursor (filtrando por el último _id visto) en lugar de skip(), porque skip() debe escanear y descartar documentos, lo que se vuelve lento a medida que crece el desplazamiento.

Contar documentos coincidentes

Usa count_documents() con un filtro para contar coincidencias sin obtener los documentos:

london_count = col.count_documents({"city": "London"})
print(london_count)  # 2

total = col.count_documents({})
print(total)  # 5

Evita el método .count() más antiguo en los cursores — fue deprecado en PyMongo 3.7 y eliminado en PyMongo 4.

Comprobar si existe un documento

Cuando solo necesitas saber si al menos un documento coincide, usa find_one() (más eficiente que contar):

exists = col.find_one({"city": "Berlin"}) is not None
print(exists)  # True

Errores comunes

El cursor se agota después de una iteración. Si iteras el mismo cursor dos veces, el segundo bucle no produce nada. Llama a find() de nuevo o convierte a lista:

cursor = col.find({"city": "Paris"})
results = list(cursor)   # materialise once
print(len(results))      # 2
# Now you can iterate `results` as many times as you like

find_one() vs find() — elige el correcto. Si sabes que hay como máximo una coincidencia (por ejemplo, al consultar por un campo único como el correo electrónico), usa find_one(). Usar find() te obliga a iterar incluso cuando solo necesitas un resultado.

Filtro None vs diccionario vacío. Tanto find() como find({}) devuelven todos los documentos. Evita pasar None explícitamente — usa {} para mayor claridad.

Capítulos relacionados

  • MongoDB Insert — insertar documentos en una colección antes de consultarlos
  • MongoDB Query — cobertura más profunda de expresiones de consulta y patrones de filtrado
  • MongoDB Sort — cobertura dedicada a la ordenación por múltiples campos
  • MongoDB Limit — limit y su interacción con los índices
  • MongoDB Update — modificar documentos que hayas encontrado
  • MongoDB Delete — eliminar documentos que coincidan
Was this page helpful?