W3docs

Ordenar en MongoDB

Aprende a ordenar resultados de consultas MongoDB en Python con el método sort() de PyMongo — ascendente, descendente, multiclave, con limit y filtros.

Este capítulo explica cómo ordenar los resultados de consultas MongoDB en Python usando el controlador pymongo. Aprenderás a ordenar por un solo campo de forma ascendente o descendente, ordenar por varios campos a la vez, combinar el ordenamiento con filtros y límites, y entender cuándo un índice hace que el ordenamiento sea rápido.

Requisitos previos

Debes estar familiarizado con la conexión a MongoDB y la consulta de documentos. Si aún no lo has hecho, lee primero MongoDB Find y MongoDB Query.

Los ejemplos a continuación asumen una colección llamada products en una base de datos llamada store. Puedes insertar los documentos de muestra usados en esta página con:

import pymongo

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

# Insert sample data (skip if already inserted)
col.drop()
col.insert_many([
    {"name": "Keyboard", "category": "Electronics", "price": 49.99, "stock": 120},
    {"name": "Mouse",    "category": "Electronics", "price": 29.99, "stock": 85},
    {"name": "Desk",     "category": "Furniture",   "price": 249.99, "stock": 30},
    {"name": "Chair",    "category": "Furniture",   "price": 189.99, "stock": 45},
    {"name": "Monitor",  "category": "Electronics", "price": 319.99, "stock": 60},
    {"name": "Lamp",     "category": "Furniture",   "price": 39.99,  "stock": 200},
])
print("Sample data inserted.")

El método sort()

El método sort() se llama sobre un cursor (el objeto devuelto por find()) e indica a MongoDB en qué orden devolver los documentos. Su firma es:

cursor.sort(key_or_list, direction=None)
  • key_or_list — un nombre de campo (string) al ordenar por un solo campo, o una lista de tuplas (field, direction) al ordenar por varios campos.
  • directionpymongo.ASCENDING (valor 1) o pymongo.DESCENDING (valor -1). Requerido cuando key_or_list es un string simple; omítelo al usar la forma de lista.

Usar las constantes con nombre (pymongo.ASCENDING / pymongo.DESCENDING) en lugar de enteros literales hace que el código sea más fácil de leer y evita errores de tipo off-by-one.

Ordenar de forma ascendente

Pasa pymongo.ASCENDING como segundo argumento para ordenar del valor más bajo al más alto:

import pymongo

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

results = col.find({}, {"_id": 0, "name": 1, "price": 1}).sort("price", pymongo.ASCENDING)

for doc in results:
    print(doc)

Salida esperada (más barato primero):

{'name': 'Mouse', 'price': 29.99}
{'name': 'Lamp', 'price': 39.99}
{'name': 'Keyboard', 'price': 49.99}
{'name': 'Chair', 'price': 189.99}
{'name': 'Desk', 'price': 249.99}
{'name': 'Monitor', 'price': 319.99}

La proyección {"_id": 0, "name": 1, "price": 1} limita los campos devueltos a name y price, lo que mantiene la salida concisa. Las proyecciones se tratan en MongoDB Find.

Ordenar de forma descendente

Pasa pymongo.DESCENDING para invertir el orden (del más alto al más bajo):

import pymongo

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

results = col.find({}, {"_id": 0, "name": 1, "price": 1}).sort("price", pymongo.DESCENDING)

for doc in results:
    print(doc)

Salida esperada (más caro primero):

{'name': 'Monitor', 'price': 319.99}
{'name': 'Desk', 'price': 249.99}
{'name': 'Chair', 'price': 189.99}
{'name': 'Keyboard', 'price': 49.99}
{'name': 'Lamp', 'price': 39.99}
{'name': 'Mouse', 'price': 29.99}

Ordenar por varios campos

Cuando deseas ordenar por más de un campo — por ejemplo, primero por categoría y luego por precio dentro de cada categoría — pasa una lista de tuplas (field, direction):

import pymongo

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

results = col.find({}, {"_id": 0, "name": 1, "category": 1, "price": 1}).sort([
    ("category", pymongo.ASCENDING),
    ("price",    pymongo.ASCENDING),
])

for doc in results:
    print(doc)

Salida esperada (categorías de A a Z, más barato primero dentro de cada categoría):

{'name': 'Mouse', 'category': 'Electronics', 'price': 29.99}
{'name': 'Keyboard', 'category': 'Electronics', 'price': 49.99}
{'name': 'Monitor', 'category': 'Electronics', 'price': 319.99}
{'name': 'Lamp', 'category': 'Furniture', 'price': 39.99}
{'name': 'Chair', 'category': 'Furniture', 'price': 189.99}
{'name': 'Desk', 'category': 'Furniture', 'price': 249.99}

Los campos de ordenamiento se aplican de izquierda a derecha: MongoDB primero ordena todos los documentos por category, luego resuelve los empates dentro del mismo valor de categoría por price.

Combinar sort() con filtros

sort() funciona con cualquier filtro de consulta. El filtro selecciona qué documentos coinciden; sort() luego ordena solo esos documentos coincidentes:

import pymongo

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

# Find Electronics only, sorted cheapest first
query  = {"category": "Electronics"}
fields = {"_id": 0, "name": 1, "price": 1}

results = col.find(query, fields).sort("price", pymongo.ASCENDING)

for doc in results:
    print(doc)

Salida esperada:

{'name': 'Mouse', 'price': 29.99}
{'name': 'Keyboard', 'price': 49.99}
{'name': 'Monitor', 'price': 319.99}

Consulta MongoDB Query para más opciones de filtrado, como consultas de rango ($gt, $lt) y coincidencia de patrones.

Combinar sort() con limit()

Encadena limit() después de sort() para obtener los N documentos superiores (o inferiores). El orden de encadenamiento no importa — MongoDB siempre aplica el ordenamiento antes del límite:

import pymongo

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

# Top 3 most expensive products
results = col.find({}, {"_id": 0, "name": 1, "price": 1}) \
             .sort("price", pymongo.DESCENDING) \
             .limit(3)

for doc in results:
    print(doc)

Salida esperada:

{'name': 'Monitor', 'price': 319.99}
{'name': 'Desk', 'price': 249.99}
{'name': 'Chair', 'price': 189.99}

Lee MongoDB Limit para más información sobre cómo controlar el número de documentos devueltos.

Rendimiento: usa un índice para colecciones grandes

Para colecciones pequeñas, MongoDB ordena los resultados en memoria. En una colección grande, un ordenamiento en memoria puede ser lento y — si supera los 100 MB — MongoDB devolverá un error. Crear un índice en el campo de ordenamiento permite a MongoDB devolver datos preordenados sin escanear toda la colección:

import pymongo

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

# Create a single-field index on price (ascending)
col.create_index([("price", pymongo.ASCENDING)])

# Queries that sort by price now use the index automatically
results = col.find({}, {"_id": 0, "name": 1, "price": 1}).sort("price", pymongo.ASCENDING)

for doc in results:
    print(doc)

Para ordenamientos de varios campos, crea un índice compuesto cuyos campos y direcciones coincidan con tu ordenamiento:

col.create_index([
    ("category", pymongo.ASCENDING),
    ("price",    pymongo.ASCENDING),
])

Solo necesitas crear cada índice una vez. Las llamadas repetidas a create_index() con la misma clave son seguras — PyMongo comprueba si el índice ya existe.

Almacenar la cadena de conexión de forma segura

Los ejemplos anteriores codifican la cadena de conexión directamente por simplicidad. En una aplicación real, guárdala en una variable de entorno:

import os
import pymongo

client = pymongo.MongoClient(os.environ["MONGODB_URI"])

Establece la variable en tu shell (export MONGODB_URI="mongodb://localhost:27017/") o usa un archivo .env con una biblioteca como python-dotenv.

Resumen

ObjetivoPatrón de código
Ordenar ascendente.sort("field", pymongo.ASCENDING)
Ordenar descendente.sort("field", pymongo.DESCENDING)
Ordenar por varios campos.sort([("f1", pymongo.ASCENDING), ("f2", pymongo.DESCENDING)])
Top N resultados.sort(...).limit(N)
Ordenamiento rápido en datos grandesCrea un índice en el campo de ordenamiento

Capítulos relacionados en esta serie:

Was this page helpful?