📝 Modelado de datos: documentos y colecciones
MongoDB no usa tablas ni filas como los sistemas SQL, sino documentos JSON dentro de colecciones. Aquí aprenderás cómo decidir **qué datos van juntos en un mismo documento** y **cuándo separarlos en distintas colecciones**.
📚 Conceptos clave
- Un documento es una estructura JSON (BSON internamente) — contiene pares clave:valor.
- Una colección agrupa documentos del mismo tipo o propósito.
- No hay esquema rígido, pero puedes definir
JSON Schemapara validar estructura. - El diseño influye directamente en el rendimiento de lectura/escritura.
👉 En MongoDB, **diseñas según cómo consultas los datos, no según las relaciones.**
1️⃣ Principios básicos del modelado
- Modela según consultas frecuentes: qué datos necesitas juntos.
- Piensa en documentos, no en tablas.
- Embebe (embed) datos que se usan siempre junto al padre.
- Referencia (reference) datos independientes o muy grandes.
Regla rápida: “Si los datos se consultan juntos, guárdalos juntos.”
2️⃣ Ejemplo: tienda online — productos, pedidos y usuarios
En SQL tendrías tablas con claves foráneas; en MongoDB puedes hacerlo así:
// Producto
{
_id: ObjectId("..."),
name: "Auriculares Bluetooth",
sku: "AUR-01",
price: 49.90,
categories: ["audio", "tecnología"],
stock: 120
}
// Usuario
{
_id: ObjectId("..."),
name: "Laura García",
email: "laura@gmail.com",
passwordHash: "...",
address: {
calle: "Gran Vía 10",
ciudad: "Madrid",
cp: "28013"
}
}
// Pedido con items embebidos
{
_id: ObjectId("..."),
userId: ObjectId("..."),
createdAt: ISODate("2025-11-13T10:00:00Z"),
total: 99.80,
items: [
{ productId: ObjectId("..."), name: "Auriculares Bluetooth", qty: 2, price: 49.90 }
],
status: "pending"
}
Aquí el pedido referencia al usuario (userId), pero embeber el detalle de cada producto dentro del pedido evita tener que hacer varias consultas cuando lo visualizas.
3️⃣ Cuándo embeber documentos
- El subdocumento pertenece exclusivamente al padre.
- Se consulta y modifica junto con el documento principal.
- El tamaño total del documento no supera los 16 MB (límite de BSON).
// Ejemplo: comentarios embebidos en un post
{
_id: ObjectId("..."),
titulo: "Novedades MongoDB 7.0",
contenido: "Detalles y nuevas funciones...",
comentarios: [
{ autor: "Ana", texto: "Excelente post!", fecha: new Date() },
{ autor: "Carlos", texto: "Muy útil, gracias!", fecha: new Date() }
]
}
✅ Ventaja: consultas más rápidas — todo está en un único documento.
⚠️ Desventaja: si hay demasiados subdocumentos, el documento puede crecer mucho.
4️⃣ Cuándo referenciar
- El subdocumento se comparte entre varios documentos (ej. un producto aparece en muchos pedidos).
- Se actualiza por separado o con frecuencia.
- Su tamaño es grande o crece indefinidamente.
// Ejemplo: relación usuario → pedidos
{
_id: ObjectId("..."),
name: "Laura",
email: "laura@gmail.com"
}
{
_id: ObjectId("..."),
userId: ObjectId("..."), // referencia
items: [ ... ],
total: 99.80
}
Luego puedes combinar ambas colecciones con $lookup (join equivalente) si necesitas unir datos.
// Unir pedidos con datos de usuario
db.orders.aggregate([
{
$lookup: {
from: "usuarios",
localField: "userId",
foreignField: "_id",
as: "usuario"
}
},
{ $unwind: "$usuario" }
])
5️⃣ Patrón mixto (embed + reference)
Es común mezclar ambos enfoques.
Ejemplo: un pedido guarda los datos resumidos del usuario
(nombre, email) embebidos, pero también su userId para futuras consultas.
{
_id: ObjectId("..."),
userId: ObjectId("..."),
user: { name: "Laura García", email: "laura@gmail.com" },
items: [ { productId: ObjectId("..."), name: "Auriculares", qty: 2 } ],
total: 99.80
}
✅ Permite mostrar el pedido directamente sin hacer joins. 🔄 Si el usuario cambia su nombre, el pedido histórico sigue mostrando el nombre original.
6️⃣ Ejemplo práctico — diseño completo para tienda online
- users: datos personales + direcciones embebidas
- products: catálogo general
- orders: referencia al usuario + productos embebidos con datos de precio en el momento del pedido
- reviews: colección separada (crece mucho)
// users
{
name: "Laura",
email: "laura@gmail.com",
addresses: [
{ calle: "Gran Vía 10", ciudad: "Madrid", cp: "28013" }
]
}
// products
{
name: "Auriculares",
sku: "AUR-01",
price: 49.90
}
// orders
{
userId: ObjectId("..."),
items: [
{ productId: ObjectId("..."), name: "Auriculares", price: 49.90, qty: 2 }
],
total: 99.80
}
// reviews
{
productId: ObjectId("..."),
userId: ObjectId("..."),
rating: 5,
text: "Excelente calidad"
}
7️⃣ Patrones de modelado comunes en MongoDB
- One-to-One: datos complementarios → embebidos o colecciones separadas según tamaño.
- One-to-Many: pocos elementos → embebidos; muchos → referencias.
- Many-to-Many: usa arrays de referencias o colección intermedia.
- Subset pattern: almacenar solo parte de los datos (por ejemplo, 5 últimos comentarios) y el resto en otra colección.
- Extended reference pattern: guardar en el documento los campos más usados del documento referenciado.
8️⃣ Buenas prácticas
- Evita documentos mayores a 16 MB (usa referencias o particiona datos).
- Agrega
createdAtyupdatedAta todos los documentos. - Usa
ObjectIdcomo ID por defecto. - Piensa en tus consultas más comunes antes de diseñar las relaciones.
- Prefiere embebido para datos estáticos y de lectura frecuente.
- Prefiere referencia para datos compartidos o que cambian a menudo.
9️⃣ Ejemplo con Mongoose (estructura del modelo)
const mongoose = require("mongoose"); const ProductSchema = new mongoose.Schema({ name: String, sku: { type: String, unique: true }, price: Number, stock: Number }); const OrderSchema = new mongoose.Schema({ userId: mongoose.Schema.Types.ObjectId, items: [{ productId: mongoose.Schema.Types.ObjectId, name: String, price: Number, qty: Number }], total: Number, createdAt: { type: Date, default: Date.now } }); const Product = mongoose.model("Product", ProductSchema); const Order = mongoose.model("Order", OrderSchema);
🔁 Resumen rápido
- Define tus consultas más comunes.
- Embeber datos si siempre se usan juntos.
- Referenciar si los datos son grandes o compartidos.
- Combina ambos enfoques si es necesario (patrón mixto).
- Evita crecer documentos sin límite → usa colecciones separadas.
0 Comentarios
Si desea contactar comigo, lo puede hacer atravez deste formulario gracias