¿Cuándo conviene más una base de datos de documentos como MongoDB que una relacional, y cuándo te pasa factura?
Las bases de datos de documentos cambian joins y esquemas rígidos por estructuras embebidas optimizadas para lectura, ideal hasta que las relaciones de tus datos superan lo que cabe en un documento.
APRENDE HACIENDOPon a prueba tu intuición3 pasos
¿Cuándo conviene más una base de datos de documentos como MongoDB que una relacional, y cuándo te pasa factura?
Usa los ejemplos y la explicación de la lección para comprobar tu idea.
Reflexión personal. No se envía a ningún servicio de IA.#La disyuntiva central: ¿normalizas al escribir o desnormalizas al leer?
Una base de datos relacional y una de documentos son perfectamente capaces de guardar la misma información: la diferencia está en dónde pagas el costo de volver a juntar los datos relacionados. Un esquema relacional normaliza: un pedido vive en una tabla, sus líneas de detalle en otra, unidas por una clave foránea. Una base de documentos como MongoDB normalmente desnormaliza: un pedido y sus líneas viven en un mismo documento BSON, así que leer "dame el pedido #4471" es una sola consulta en vez de un join.
Esa única decisión de diseño explica casi todo lo demás que se dice de las bases de documentos: el esquema flexible, la lectura rápida cuando accedes al objeto completo, y el dolor cuando las relaciones resultan más enredadas de lo que parecían el primer día.
#Dónde una base de documentos gana de verdad
- Los datos son naturalmente jerárquicos. Un producto con variantes, un perfil de usuario con preferencias anidadas, una página de CMS con bloques y metadatos: todo esto encaja en un árbol mucho mejor que en una docena de tablas normalizadas.
- Las lecturas tienen forma de agregado. Si el 90% de tus consultas son "trae esta cosa con todo lo que necesita para renderizarse", embeber evita por completo los joins N+1: lees una vez y ya está.
- El esquema todavía se está moviendo. Al principio de la vida de un producto, o con datos genuinamente polimórficos (distintos "tipos" de documento en la misma colección con campos diferentes), un esquema forzado es una fricción que todavía no necesitas.
- Necesitas particionar cargas de escritura intensa horizontalmente sin rediseñar todo alrededor de claves foráneas: una shard key bien elegida te lleva ahí de forma más directa que particionar un esquema relacional.
#Dónde te pasa factura
- Relaciones muchos-a-muchos consultadas desde ambos lados. Si embebes una lista de etiquetas en cada artículo pero también quieres "todos los artículos de una etiqueta", ahora o duplicas datos en ambas direcciones o vuelves a las referencias y a
$lookup, el join de MongoDB, que no trae detrás las décadas de optimización de planificador de consultas que sí tiene un motor relacional. - Las transacciones multi-documento existen, pero no son el modo natural. Desde MongoDB 4.0 puedes envolver varios documentos (incluso entre shards desde 4.2) en una transacción ACID, pero cuesta más que escribir un solo documento, y el modelo de datos igual te empuja a desnormalizar precisamente para necesitarlas lo menos posible.
- Arreglos sin límite. Un documento tiene un techo duro de 16MB, y un arreglo que crece sin cota (comentarios en un post, eventos de un usuario) eventualmente lo va a alcanzar — y mucho antes de eso, ya va a hacer más lenta cada lectura y cada actualización en el lugar.
- No hay integridad referencial forzada. Si borras un cliente, cada pedido que embebió una copia vieja de su nombre no se entera. Las referencias huérfanas son parte de la vida y ahora las manejas en el código de la aplicación, no una restricción que la base de datos rechaza por ti.
- Analítica ad hoc. "Junta todo y córtalo de mil formas distintas" es exactamente para lo que se construyó un motor relacional y su optimizador. El pipeline de agregación de una base de documentos puede hacerlo, pero estás escribiendo a mano lo que un
JOINmásGROUP BYte da gratis.
#Un ejemplo concreto
Imagina una colección orders donde cada documento embebe sus líneas de detalle:
{_id: ObjectId("64f1a2b3c4d5e6f7a8b9c0d1"),customerId: ObjectId("64f1a2b3c4d5e6f7a8b9c0aa"),status: "fulfilled",createdAt: ISODate("2026-06-02T14:03:00Z"),items: [{ sku: "SKU-1001", name: "Teclado mecánico", qty: 1, priceCents: 8900 },{ sku: "SKU-2044", name: "Hub USB-C", qty: 2, priceCents: 2400 }]}
Leer un pedido es un solo findOne. Pero "ingresos totales por SKU en todos los pedidos de este mes" necesita que el pipeline de agregación desenrolle el arreglo embebido antes de poder agrupar:
db.orders.aggregate([{ $match: { createdAt: { $gte: ISODate("2026-06-01T00:00:00Z") } } },{ $unwind: "$items" },{ $group: {_id: "$items.sku",unitsSold: { $sum: "$items.qty" },revenueCents: { $sum: { $multiply: ["$items.qty", "$items.priceCents"] } }} },{ $sort: { revenueCents: -1 } }]);
Y si necesitas el correo actual del cliente en cada línea de pedido para un reporte —dato que vive en una colección customers separada porque los clientes se actualizan de forma independiente— recurres a $lookup, la etapa de join de MongoDB:
db.orders.aggregate([{ $match: { status: "fulfilled" } },{ $lookup: {from: "customers",localField: "customerId",foreignField: "_id",as: "customer"} },{ $unwind: "$customer" },{ $project: { _id: 1, "customer.email": 1, items: 1 } }]);
Esa consulta funciona, pero ahí está la señal: en el momento en que tu modelo de documentos necesita un $lookup para responder una pregunta habitual, estás pagando por el join que intentaste diseñar para evitar, solo que sin el optimizador consciente de índices que traería un motor relacional.
🧠 Check your understanding
0/2 · 0/2 answered1. Una app social guarda publicaciones con un arreglo embebido de comentarios. Los comentarios no tienen límite superior y la app empieza a mostrar lecturas lentas en publicaciones viejas con muchísimos comentarios. ¿Cuál es la causa más probable?
2. ¿Por qué una etapa `$lookup` en el pipeline de agregación de MongoDB normalmente no rinde tan bien como un JOIN en un motor relacional maduro, en igualdad de condiciones?