Bases de Datos5 de enero de 2026• 12 min lectura
MongoDB: Modelado de datos y optimización de consultas
#mongodb#nosql#database#performance
MongoDB: Modelado de datos y optimización de consultas
MongoDB ofrece flexibilidad en el modelado de datos, pero esta libertad requiere decisiones arquitectónicas importantes.
Principios de modelado
Embedding vs Referencing
Embedding - Documentos anidados:
// Bueno cuando: Relación 1-a-pocos, datos que se consultan juntos
{
_id: ObjectId("..."),
nombre: "Juan Pérez",
direcciones: [
{
calle: "Av. Principal 123",
ciudad: "Buenos Aires",
tipo: "casa"
},
{
calle: "Calle Trabajo 456",
ciudad: "Buenos Aires",
tipo: "trabajo"
}
]
}
Referencing - Referencias entre documentos:
// Bueno cuando: Relación muchos-a-muchos, datos que crecen sin límite
// Usuario
{
_id: ObjectId("user1"),
nombre: "Juan Pérez",
ordenes: [
ObjectId("order1"),
ObjectId("order2")
]
}
// Orden
{
_id: ObjectId("order1"),
usuario_id: ObjectId("user1"),
total: 1500,
items: [...]
}
Índices efectivos
Índices compuestos
// Crear índice compuesto para consultas frecuentes
db.usuarios.createIndex({ ciudad: 1, edad: -1 });
// Consulta optimizada
db.usuarios.find({ ciudad: "Buenos Aires", edad: { $gte: 25 } })
.sort({ edad: -1 });
Índices de texto
// Índice de texto para búsquedas
db.productos.createIndex({
nombre: "text",
descripcion: "text"
});
// Búsqueda de texto
db.productos.find({
$text: { $search: "laptop gaming" }
});
Aggregation Pipeline
// Pipeline complejo para análisis de ventas
db.ventas.aggregate([
// Stage 1: Filtrar por fecha
{
$match: {
fecha: {
$gte: ISODate("2026-01-01"),
$lt: ISODate("2026-02-01")
}
}
},
// Stage 2: Agrupar por producto
{
$group: {
_id: "$producto_id",
total_vendido: { $sum: "$cantidad" },
ingresos: { $sum: "$total" },
promedio: { $avg: "$total" }
}
},
// Stage 3: Ordenar por ingresos
{
$sort: { ingresos: -1 }
},
// Stage 4: Limitar a top 10
{
$limit: 10
},
// Stage 5: Lookup para datos del producto
{
$lookup: {
from: "productos",
localField: "_id",
foreignField: "_id",
as: "producto_info"
}
}
]);
Optimización de consultas
1. Usa explain() para analizar performance
db.usuarios.find({ edad: { $gt: 25 } }).explain("executionStats");
2. Proyección para reducir datos transferidos
// Solo traer campos necesarios
db.usuarios.find(
{ ciudad: "Buenos Aires" },
{ nombre: 1, email: 1, _id: 0 }
);
3. Paginación eficiente
// Evitar skip() para grandes datasets
const lastId = ObjectId("...");
db.productos
.find({ _id: { $gt: lastId } })
.sort({ _id: 1 })
.limit(20);
Patrones avanzados
Bucketing Pattern
// Para series temporales
{
sensor_id: "sensor_1",
fecha: ISODate("2026-01-20"),
lecturas: [
{ timestamp: ISODate("2026-01-20T10:00:00Z"), temp: 23.5 },
{ timestamp: ISODate("2026-01-20T10:01:00Z"), temp: 23.6 },
// ... más lecturas del mismo día
],
estadisticas: {
min: 22.1,
max: 24.8,
avg: 23.4
}
}
Computed Pattern
// Precalcular valores frecuentes
{
_id: ObjectId("..."),
titulo: "Producto X",
precio: 100,
cantidad_reviews: 50, // Calculado
rating_promedio: 4.5, // Calculado
ultima_actualizacion: ISODate("...")
}
Mejores prácticas
- Desnormaliza con propósito - Solo cuando mejore performance
- Monitorea tamaño de documentos - Límite de 16MB
- Usa esquemas flexibles inteligentemente - No significa sin estructura
- Implementa validación - JSON Schema validation
- Planifica sharding - Antes de escalar horizontalmente
Conclusión
MongoDB es poderoso cuando se modela correctamente. La clave está en entender tus patrones de acceso a datos y diseñar el esquema en consecuencia.