Volver a MongoDB Básico
Patrones de Diseño de Esquema en MongoDB
Documentos Embebidos vs Referencias
// ✅ EMBEBER cuando: se leen juntos, el hijo no tiene vida independiente
{
_id: ObjectId(),
nombre: "Alicia",
direccion: { // siempre se lee con el usuario
calle: "Av. Reforma 123",
ciudad: "Ciudad de México",
cp: "06600"
}
}
// ✅ REFERENCIAR cuando: entidades grandes, actualizaciones independientes, muchos-a-muchos
{
_id: ObjectId("id_pedido"),
clienteId: ObjectId("id_cliente"), // referencia
items: [
{ productoId: ObjectId("id_prod"), cantidad: 2, precio: 29.99 }
]
}
El Límite de 16MB por Documento
// ❌ Anti-patrón: array sin límite
{
_id: ObjectId("user_id"),
nombre: "Alicia",
publicaciones: [ ... ] // crece sin fin → supera 16MB
}
// ✅ Usar referencias
db.publicaciones.find({ usuarioId: ObjectId("user_id") })
Patrón Bucket (Series Temporales)
// ✅ Agrupar lecturas por hora en lugar de un doc por lectura
{
_id: { dispositivoId: "sensor-1", hora: ISODate("2024-01-01T10:00Z") },
dispositivoId: "sensor-1",
hora: ISODate("2024-01-01T10:00Z"),
conteo: 60,
lecturas: [
{ ts: ISODate("2024-01-01T10:00:05Z"), temp: 22.1 },
{ ts: ISODate("2024-01-01T10:00:10Z"), temp: 22.3 }
]
}
Patrón Outlier
// Usuarios con millones de seguidores se manejan diferente
{
_id: ObjectId("usuario_normal"),
nombre: "Usuario Regular",
seguidores: [ id1, id2, id3 ] // embebido (pocos)
}
{
_id: ObjectId("celebridad_id"),
nombre: "Celebridad",
seguidores: [ id1, id2, ... ], // lista parcial
tiene_extras: true // bandera → revisar colección overflow
}
Versionado de Esquema
{
_id: ObjectId(),
version_esquema: 2,
// v1: nombre completo como string
// v2: nombre separado en nombre.primero + nombre.apellido
nombre: { primero: "Alicia", apellido: "García" }
}
// La aplicación maneja ambas versiones durante la migración
function obtenerNombre(usuario) {
if (usuario.version_esquema >= 2) {
return `${usuario.nombre.primero} ${usuario.nombre.apellido}`;
}
return usuario.nombre_completo; // v1
}
Reglas de Validación
db.createCollection("usuarios", {
validator: {
$jsonSchema: {
bsonType: "object",
required: ["nombre", "email"],
properties: {
nombre: {
bsonType: "string",
minLength: 2,
maxLength: 100
},
email: {
bsonType: "string",
pattern: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
},
edad: {
bsonType: "int",
minimum: 0,
maximum: 150
}
}
}
},
validationAction: "error"
})
Tabla de Decisiones de Diseño
| Pregunta | Embeber | Referenciar |
|---|---|---|
| ¿Se leen juntos? | ✅ | ❌ |
| ¿Se actualizan por separado? | ❌ | ✅ |
| ¿Uno a pocos? | ✅ | ❌ |
| ¿Uno a millones? | ❌ | ✅ |
| ¿Tamaño acotado? | ✅ | ❌ |