馃摑 Modelado de datos: documentos y colecciones

Modelado de datos en MongoDB

馃摑 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 Schema para 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 createdAt y updatedAt a todos los documentos.
  • Usa ObjectId como 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

  1. Define tus consultas m谩s comunes.
  2. Embeber datos si siempre se usan juntos.
  3. Referenciar si los datos son grandes o compartidos.
  4. Combina ambos enfoques si es necesario (patr贸n mixto).
  5. Evita crecer documentos sin l铆mite → usa colecciones separadas.

Publicar un comentario

0 Comentarios