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

PreguntaEmbeberReferenciar
¿Se leen juntos?
¿Se actualizan por separado?
¿Uno a pocos?
¿Uno a millones?
¿Tamaño acotado?