Primeros pasos con MongoDB
Aprende a instalar MongoDB, conectarte con PyMongo y realizar operaciones CRUD básicas en Python con ejemplos claros y funcionales.
Este capítulo presenta MongoDB y muestra cómo usarlo desde Python con el driver PyMongo. Al finalizar, tendrás MongoDB instalado, una conexión funcionando y una idea clara de cómo insertar, consultar, actualizar y eliminar documentos.
¿Qué es MongoDB?
MongoDB es una base de datos de documentos — un tipo de base de datos NoSQL que almacena registros como documentos similares a JSON en lugar de filas y columnas. Cada documento es un objeto autocontenido que puede tener campos anidados y arrays, lo que lo convierte en una opción natural para datos que no encajan bien en un esquema fijo.
Características principales:
- Esquema flexible. Dos documentos de la misma colección pueden tener campos completamente distintos.
- Lenguaje de consulta potente. Filtra, proyecta, ordena, limita y agrega con una sola llamada al driver.
- Escalabilidad horizontal. El sharding integrado y los replica sets manejan grandes volúmenes de datos y alta disponibilidad.
- Nativo en JSON. Los documentos se almacenan como BSON (Binary JSON), por lo que los diccionarios de Python se corresponden directamente con documentos de MongoDB.
Cuándo elegir MongoDB sobre una base de datos relacional
| Situación | ¿Buena opción? |
|---|---|
| Estructura de datos cambiante rápidamente (prototipos, APIs) | Sí |
| Datos jerárquicos / anidados | Sí |
Consultas complejas con JOIN entre múltiples tablas | Preferir SQL |
Transacciones ACID estrictas entre muchas tablas | Preferir SQL |
| Búsqueda de texto completo a escala | Combinar con Elasticsearch |
Instalar MongoDB
Opción 1 — Instalación local
Descarga el MongoDB Community Server desde mongodb.com/try/download/community, elige tu sistema operativo y sigue el instalador. Luego inicia el servidor:
# macOS / Linux
mongod --dbpath /data/db
# Windows (PowerShell, run as Administrator)
mongod --dbpath "C:\data\db"Verifica que MongoDB esté en ejecución abriendo una segunda terminal y ejecutando:
mongosh --eval "db.adminCommand('ping')"Salida esperada:
{ ok: 1 }Opción 2 — Docker (la más rápida para desarrollo)
Si tienes Docker instalado, puedes omitir la instalación local por completo:
docker run -d --name mongo -p 27017:27017 mongo:7Esto descarga la imagen oficial de MongoDB 7 y expone el puerto 27017 en tu máquina. Detenla con docker stop mongo.
Opción 3 — MongoDB Atlas (nube)
Atlas es el servicio cloud totalmente gestionado de MongoDB con un nivel gratuito. Tras registrarte, copia la cadena de conexión desde el panel de control — tiene este aspecto:
mongodb+srv://username:[email protected]/Puedes usar ese URI en cualquier lugar donde veas mongodb://localhost:27017/ en este capítulo.
Instalar el driver PyMongo
PyMongo es el driver oficial de Python para MongoDB. Instálalo con pip:
pip install pymongoPara usar MongoDB Atlas, instala también los extras que incluyen el resolutor DNS:
pip install "pymongo[srv]"Verifica la instalación:
import pymongo
print(pymongo.version)
# e.g. 4.7.3Conectarse a MongoDB
MongoClient es el punto de entrada para todas las operaciones del driver. Crea un cliente por aplicación y reutilízalo — el cliente gestiona un pool de conexiones interno.
from pymongo import MongoClient
# Local server with default host and port
client = MongoClient("mongodb://localhost:27017/")
# Verify connectivity (raises ConnectionFailure if the server is unreachable)
client.admin.command("ping")
print("Connected successfully")En código de producción, maneja siempre los errores de conexión de forma explícita:
from pymongo import MongoClient
from pymongo.errors import ConnectionFailure
client = MongoClient("mongodb://localhost:27017/", serverSelectionTimeoutMS=3000)
try:
client.admin.command("ping")
print("Connected to MongoDB")
except ConnectionFailure as e:
print("Connection failed:", e)Formato de la cadena de conexión
mongodb://[username:password@]host[:port][/database][?options]Opciones comunes:
| Opción | Ejemplo | Propósito |
|---|---|---|
authSource | authSource=admin | Base de datos usada para autenticación |
replicaSet | replicaSet=rs0 | Conectarse a un replica set |
tls=true | tls=true | Habilitar TLS/SSL |
serverSelectionTimeoutMS | serverSelectionTimeoutMS=5000 | Tiempo de espera para la selección del servidor |
Bases de datos y colecciones
MongoDB organiza los datos en una jerarquía de dos niveles:
- Una base de datos agrupa colecciones relacionadas (similar a un esquema o base de datos en SQL).
- Una colección contiene documentos (similar a una tabla SQL, pero sin esquema fijo).
Ambas se crean de forma perezosa — existen a partir del momento en que insertas el primer documento. Nunca ejecutas CREATE DATABASE ni CREATE TABLE.
from pymongo import MongoClient
client = MongoClient("mongodb://localhost:27017/")
# Reference a database (not yet created on disk)
db = client["mystore"]
# Reference a collection inside it (also not yet on disk)
products = db["products"]
# The database and collection are created when the first document is insertedOperaciones CRUD básicas
Los siguientes ejemplos se basan entre sí. Ejecútalos en orden si los estás siguiendo de forma interactiva.
Crear — insertar documentos
Usa insert_one() para un solo documento e insert_many() para un lote:
from pymongo import MongoClient
client = MongoClient("mongodb://localhost:27017/")
db = client["mystore"]
products = db["products"]
# Insert a single document
result = products.insert_one({
"name": "Laptop",
"brand": "Acme",
"price": 999.99,
"in_stock": True
})
print("Inserted id:", result.inserted_id)
# Insert multiple documents at once
new_products = [
{"name": "Mouse", "brand": "Acme", "price": 29.99, "in_stock": True},
{"name": "Keyboard", "brand": "Acme", "price": 79.99, "in_stock": False},
{"name": "Monitor", "brand": "Zeta", "price": 349.99, "in_stock": True},
]
batch_result = products.insert_many(new_products)
print("Inserted ids:", batch_result.inserted_ids)MongoDB añade automáticamente un campo _id (de tipo ObjectId) a cada documento si no lo proporcionas. Este campo es la clave primaria y siempre es único dentro de una colección.
Leer — consultar documentos
find_one() devuelve el primer documento que coincide (o None). find() devuelve un cursor sobre el que puedes iterar.
# Retrieve one document (no filter = the first document in natural order)
doc = products.find_one()
print(doc)
# Retrieve all documents in the collection
for p in products.find():
print(p["name"], "-", p["price"])
# Filter: products that are in stock
for p in products.find({"in_stock": True}):
print(p["name"])
# Projection: return only name and price (exclude _id)
for p in products.find({}, {"_id": 0, "name": 1, "price": 1}):
print(p)Operadores de consulta
El lenguaje de consulta de MongoDB usa operadores con el prefijo $:
# Products cheaper than £100
cheap = products.find({"price": {"$lt": 100}})
# In-stock products from brand "Acme" or "Zeta"
multi = products.find({
"in_stock": True,
"brand": {"$in": ["Acme", "Zeta"]}
})
# Price between 50 and 500 (inclusive)
range_q = products.find({"price": {"$gte": 50, "$lte": 500}})Operadores de comparación comunes:
| Operador | Significado |
|---|---|
$eq | Igual (por defecto al usar {"field": value}) |
$ne | Distinto |
$gt / $gte | Mayor que / mayor o igual que |
$lt / $lte | Menor que / menor o igual que |
$in | El valor está en una lista |
$nin | El valor no está en una lista |
Actualizar — modificar documentos
update_one() modifica el primer documento que coincide. update_many() modifica todas las coincidencias. Usa siempre el operador $set para cambiar campos específicos — sin él, reemplazas el documento completo.
# Update a single document: change the price of "Mouse"
update_result = products.update_one(
{"name": "Mouse"}, # filter
{"$set": {"price": 24.99}} # update
)
print("Matched:", update_result.matched_count,
"Modified:", update_result.modified_count)
# Mark all Acme products as in stock
products.update_many(
{"brand": "Acme"},
{"$set": {"in_stock": True}}
)
# Increment a field value
products.update_one(
{"name": "Laptop"},
{"$inc": {"price": -50}} # reduce price by 50
)Operadores de actualización comunes:
| Operador | Efecto |
|---|---|
$set | Establece uno o más campos |
$unset | Elimina un campo |
$inc | Incrementa un campo numérico |
$push | Añade un valor a un campo array |
$pull | Elimina un valor de un campo array |
Eliminar — borrar documentos
delete_one() elimina el primer documento que coincide. delete_many() elimina todas las coincidencias.
# Remove a single document
del_result = products.delete_one({"name": "Keyboard"})
print("Deleted count:", del_result.deleted_count)
# Remove all out-of-stock items
products.delete_many({"in_stock": False})
# Confirm what is left
print("Remaining products:")
for p in products.find({}, {"_id": 0, "name": 1}):
print(" -", p["name"])Errores comunes
La creación perezosa puede ocultar errores tipográficos
Como MongoDB crea bases de datos y colecciones bajo demanda, un error tipográfico crea silenciosamente una segunda base de datos vacía en lugar de lanzar un error:
# Intended: client["mystore"] Actual: client["mystoree"]
db = client["mystoree"] # no error, but your data goes to the wrong databaseSolución: define los nombres de la base de datos y la colección como constantes a nivel de módulo:
DB_NAME = "mystore"
COL_NAME = "products"
db = client[DB_NAME]
products = db[COL_NAME]Los errores de conexión solo aparecen en la primera operación
MongoClient() tiene éxito incluso cuando MongoDB no está en ejecución. El error aparece únicamente al realizar una solicitud real. Usa serverSelectionTimeoutMS y una comprobación ping al inicio (como se muestra en la sección de conexión anterior) para detectar fallos rápidamente.
La ausencia de $set reemplaza el documento completo
# WRONG — replaces the whole document with just {"price": 24.99}
products.update_one({"name": "Mouse"}, {"price": 24.99})
# CORRECT — only changes the price field
products.update_one({"name": "Mouse"}, {"$set": {"price": 24.99}})find() devuelve un cursor, no una lista
Un cursor es perezoso — los documentos se obtienen del servidor solo cuando iteras sobre él. Si necesitas una lista simple, conviértelo explícitamente:
all_products = list(products.find())Ten cuidado con colecciones grandes: cargar todo en memoria a la vez puede agotar la RAM.
Qué viene a continuación
Este capítulo cubrió los aspectos esenciales. El resto de la serie Python MongoDB profundiza en cada tema:
- MongoDB Create Database — cómo funciona la creación perezosa y cómo verificar que una base de datos existe.
- MongoDB Create Collection — opciones de creación de colecciones y esquemas de validación.
- MongoDB Insert —
insert_one(),insert_many()y cómo manejar errores de clave duplicada. - MongoDB Find — proyecciones, cursores y ordenación.
- MongoDB Query — referencia completa de operadores de consulta.
- MongoDB Update —
update_one(),update_many(),upserty operadores de array. - MongoDB Delete — patrones de eliminación seguros y
drop(). - MongoDB Sort — ordenación por un campo y por múltiples campos.
- MongoDB Limit — paginación con
limit()yskip(). - MongoDB Drop Collection — eliminar una colección por completo.