---
term: 'Modelado de Datos'
seoTitle: '¿Qué es el Modelado de Datos? Relaciones, Pointers y Relations'
headline: '¿Qué es el modelado de datos?'
slug: modelado-de-datos
category: database
shortDefinition: 'El modelado de datos es un proceso que mapea entidades, atributos y relaciones antes de decidir cómo la base de datos los almacenará.'
relatedTerms:
  - database-schema
  - relational-queries-document-databases
  - n-plus-one-query-problem
  - auto-generated-database-apis
contrastsWith:
  - database-schema
faq:
  - question: '¿Qué es el modelado de datos?'
    answer: 'El proceso de mapear la información de una aplicación — sus entidades, sus atributos y las relaciones entre ellos — en un diseño que una base de datos pueda almacenar. Suele avanzar por tres niveles de detalle: un modelo conceptual que nombra las entidades, un modelo lógico que agrega atributos y claves, y un modelo físico que se compromete con tablas, columnas e índices en un motor específico.'
  - question: '¿Cuáles son los tres tipos de modelos de datos?'
    answer: 'Conceptual, lógico y físico — el mismo diseño con zoom creciente. El conceptual responde "qué existe y cómo se relaciona" para los stakeholders de negocio. El lógico agrega atributos, tipos y claves sin atarse a una tecnología. El físico se compromete con un motor real: tablas o colecciones, índices, constraints. Cada nivel es el anterior más decisiones.'
  - question: '¿Qué es una relación uno-a-muchos?'
    answer: 'Un registro padre que se relaciona con muchos hijos, donde cada hijo pertenece exactamente a un padre — un cliente y sus pedidos, un autor y sus libros. Es la relación más común en cualquier esquema. Las bases relacionales la implementan con una clave foránea en el lado de muchos; las bases de documentos usan un array embebido para conjuntos pequeños y acotados, o un pointer al padre para todo lo demás.'
  - question: '¿Qué es una relación muchos-a-muchos y por qué necesita una tabla de unión?'
    answer: 'Ambos lados se relacionan con muchos del otro — estudiantes y cursos, libros y géneros. Una sola columna de clave foránea solo puede apuntar a una fila, así que las bases relacionales descomponen el muchos-a-muchos en dos uno-a-muchos a través de una tabla de unión que guarda ambas claves (y a menudo atributos de la relación, como la fecha de inscripción). Las bases de documentos se saltan la unión: arrays de referencias, o un tipo relation dedicado, llevan la arista directamente.'
  - question: '¿Cómo distingo uno-a-muchos de muchos-a-muchos?'
    answer: 'Haz la pregunta de pertenencia en ambas direcciones. "¿Puede un autor tener muchos libros?" Sí. "¿Puede un libro tener muchos autores?" Si no — uno-a-muchos, clave foránea en el libro. Si sí — muchos-a-muchos, tabla de unión o relation. Equivocarse aquí es el error de modelado clásico: un muchos-a-muchos modelado como uno-a-muchos duplica filas o pierde aristas en silencio.'
  - question: '¿Qué es la cardinalidad en un diagrama ER?'
    answer: 'Cuántas instancias de una entidad pueden relacionarse con instancias de otra — uno-a-uno, uno-a-muchos, muchos-a-muchos. Los diagramas la expresan en una de tres notaciones: números y letras sobre las líneas de conexión, símbolos de pata de gallo (una barra para uno, un tridente de tres puntas para muchos), o rangos de multiplicidad como 1 y asterisco. La misma semántica, distintas convenciones de dibujo.'
  - question: '¿Cómo modelan relaciones las bases de documentos sin claves foráneas?'
    answer: 'Con tres herramientas: embeber (anidar los datos relacionados dentro del documento padre — correcto cuando se leen juntos, tienen un solo dueño y están acotados), pointers o referencias (guardar el ID del documento relacionado como campo tipado — correcto para ciclos de vida independientes y alta cardinalidad), y objetos relation o arrays de IDs para muchos-a-muchos. La regla guía pasa de la normalización a los patrones de acceso: los datos que se leen juntos deben vivir juntos.'
  - question: '¿Cuáles son los errores más comunes de modelado de datos?'
    answer: 'Un top cinco estable: modelar muchos-a-muchos como uno-a-muchos; olvidar los índices en campos de clave foránea y de pointer (cada join y cada lookup lo pagan); arrays embebidos sin límite en esquemas de documentos; desnormalización prematura antes de que alguna query pruebe ser lenta; y modelar solo desde las entidades sin listar las queries — los patrones de acceso — que el modelo debe servir.'
codeLanguages: [javascript, dart, swift, kotlin]
externalAuthorities:
  - name: 'MongoDB — Embedding vs. References'
    url: 'https://www.mongodb.com/docs/manual/data-modeling/concepts/embedding-vs-references/'
  - name: 'Many-to-many data model (Wikipedia)'
    url: 'https://en.wikipedia.org/wiki/Many-to-many_(data_model)'
  - name: 'Entity–relationship model (Wikipedia)'
    url: 'https://en.wikipedia.org/wiki/Entity%E2%80%93relationship_model'
  - name: 'SDK relational data guide'
    url: 'https://docs.parseplatform.org/js/guide/#relational-data'
cta:
  title: 'Modélalo una vez, consúltalo en todas partes'
  text: 'En Back4app, el modelo es el backend: clases en el dashboard, Pointers para uno-a-muchos, Relations para muchos-a-muchos — y cada arista que declaras es consultable al instante a través de las APIs REST, GraphQL y SDKs generados automáticamente, con include() integrado.'
  linkText: 'Empieza gratis'
  linkUrl: 'https://www.back4app.com/signup'
author: 'Back4app Engineering'
publishedDate: '2026-09-01'
translationKey: data-modeling
---

**El modelado de datos es un proceso que mapea entidades, atributos y relaciones antes de decidir cómo la base de datos los almacenará.** Las entidades son la parte fácil — todo producto conoce sus usuarios, pedidos y posts. El oficio está en las *relaciones*: qué registros apuntan a cuáles, cuántos, y dónde vive físicamente esa arista. Acierta las aristas y las queries se escriben solas; equivócate y cada feature pelea contra el esquema.

## Puntos clave

| Pregunta | Respuesta |
| --- | --- |
| Los tres niveles | Conceptual (qué) → lógico (estructura) → físico (motor) |
| Las tres aristas | Uno-a-uno · uno-a-muchos · muchos-a-muchos |
| Herramientas relacionales | Claves foráneas; tablas de unión para muchos-a-muchos |
| Herramientas de documentos | Embeber, Pointers (referencias), Relations/arrays de IDs |
| La regla moderna | Modela para los patrones de acceso — lo que se lee junto vive junto |

## Las mismas relaciones, en ambos mundos

Primero el mundo relacional — la clave foránea carga el uno-a-muchos, y el muchos-a-muchos debe descomponerse a través de una tabla de unión:

```sql
-- 1:N — la clave foránea vive en el lado de "muchos"
CREATE TABLE books (
  id        bigint PRIMARY KEY,
  title     text   NOT NULL,
  author_id bigint NOT NULL REFERENCES authors(id) ON DELETE CASCADE
);

-- M:N — ninguna FK sola puede expresarlo; la tabla de unión guarda ambas claves
CREATE TABLE book_genres (
  book_id  bigint REFERENCES books(id),
  genre_id bigint REFERENCES genres(id),
  added_at timestamptz DEFAULT now(),     -- las uniones pueden llevar atributos
  PRIMARY KEY (book_id, genre_id)         -- clave compuesta: una arista, una vez
);
```

Mundo de documentos, el mismo modelo: la arista uno-a-muchos es un **Pointer** tipado, la muchos-a-muchos es una **Relation** — sin tabla de unión que inventar, y la arista se declara en el código de la aplicación:

**JavaScript:**

```javascript
// JavaScript / Node.js — Back4app JS SDK
// One-to-many: a Pointer. Many-to-many: a Relation.
const author = await new Parse.Query('Author').get(authorId);

const book = new Parse.Object('Book');
book.set('title', 'Dune');
book.set('author', author);              // Pointer — typed one-to-many edge
await book.save();

const genres = book.relation('genres');  // Relation — many-to-many, unbounded
genres.add([sciFi, classics]);
await book.save();
```

**Flutter:**

```dart
// Flutter / Dart — Back4app Flutter SDK
// One-to-many: a Pointer. Many-to-many: a Relation.
final book = ParseObject('Book')
  ..set('title', 'Dune')
  ..set('author', author.toPointer()); // Pointer — typed one-to-many edge
await book.save();

book.addRelation('genres', [sciFi, classics]); // Relation — many-to-many
await book.save();
```

**Swift:**

```swift
// iOS / Swift — Back4app Swift SDK
// One-to-many: a Pointer. Many-to-many: a Relation.
var book = Book()
book.title = "Dune"
book.author = try author.toPointer()   // Pointer — typed one-to-many edge
let saved = try await book.save()

let relation = try saved.relation("genres")
try await relation.add([sciFi, classics]).save() // Relation — many-to-many
```

**Kotlin:**

```kotlin
// Android / Kotlin — Back4app Android SDK
// One-to-many: a Pointer. Many-to-many: a Relation.
val book = ParseObject("Book").apply {
  put("title", "Dune")
  put("author", author)                 // Pointer — typed one-to-many edge
}
book.save()

val genres = book.getRelation<ParseObject>("genres") // Relation — many-to-many
genres.add(sciFi)
genres.add(classics)
book.save()
```

## Conceptual vs. lógico vs. físico: los tres niveles

```mermaid
flowchart LR
  accTitle: Modelos de datos conceptual, lógico y físico
  accDescr: Un modelo conceptual nombra entidades y relaciones para la discusión de negocio; el modelo lógico agrega atributos, tipos y claves independientes de la tecnología; el modelo físico se compromete con tablas o colecciones, índices y constraints en un motor de base de datos específico.
  C["Conceptual<br/>Autor —escribe→ Libro<br/>(qué existe, para humanos)"]
  L["Lógico<br/>+ atributos, tipos, claves<br/>(estructura, agnóstica del motor)"]
  P["Físico<br/>tablas/colecciones, índices,<br/>constraints en un motor"]
  C --> L --> P
```

| Dimensión | Conceptual | Lógico | Físico |
| --- | --- | --- | --- |
| Pregunta que responde | Qué existe, cómo se relaciona | Qué campos, qué claves | Cómo se almacena, qué tan rápido |
| Audiencia | Todos | Diseñadores | Ingenieros + el motor |
| Contiene | Entidades, relaciones | + atributos, tipos, cardinalidad | + índices, constraints, particiones |
| Cambia cuando | El negocio cambia | Los requisitos se refinan | El motor o la escala cambian |

La disciplina que los niveles imponen: no discutas sobre índices mientras el equipo todavía no se pone de acuerdo en qué es un "pedido".

## Cada relación, cada implementación

La tabla que la SERP nunca construyó — cada tipo de arista con su implementación en ambos mundos:

| Relación | Ejemplo | Implementación relacional | Implementación en documentos |
| --- | --- | --- | --- |
| Uno-a-uno | Usuario ↔ perfil | FK con UNIQUE, o la misma fila | Embébelo — casi siempre |
| Uno-a-pocos | Persona → direcciones | Tabla hija + FK | Array embebido (acotado) |
| Uno-a-muchos | Autor → libros | FK en el lado de muchos | **Pointer** en el lado de muchos |
| Uno-a-enormes | Dispositivo → eventos | FK + particionado | Pointer en el *hijo*; nunca un array |
| Muchos-a-muchos | Libros ↔ géneros | Tabla de unión, PK compuesta | **Relation** o arrays de pointers |
| Auto-referencial | Empleado → gerente | FK a su propia tabla | Pointer a su propia clase |

Notación de cardinalidad, para leer diagramas: la pata de gallo dibuja una barra para "uno" y un tridente de tres puntas para "muchos"; la [tradición ER](https://en.wikipedia.org/wiki/Entity%E2%80%93relationship_model) escribe 1 y N sobre las líneas; UML escribe multiplicidades como `1` y `*`. Tres dialectos, una sola gramática.

## ¿Normalizar, desnormalizar o embeber?

El modelado relacional parte de la **normalización** — separa los datos para que cada hecho viva una sola vez, protegiendo las escrituras de anomalías. El modelado analítico y el de documentos la doblan a propósito: la **desnormalización** duplica campos calientes de lectura para matar joins, y **embeber** es el primo nativo de documentos de la desnormalización. El [checklist de embeber vs. referenciar](https://www.mongodb.com/docs/manual/data-modeling/concepts/embedding-vs-references/) se comprime en tres preguntas: ¿se leen juntos? ¿pertenecen a un solo padre? ¿tienen tamaño acotado? Tres síes embeben; cualquier no, referencia. Y por encima de todo, la regla moderna que las guías generalistas se saltan: **lista primero las queries**. Un modelo es correcto cuando los patrones de acceso que debe servir son baratos — las entidades por sí solas no pueden decírtelo.

## Casos de uso comunes

- **Diseñar un backend nuevo.** La pasada clásica: nombra las entidades, dibuja las aristas, elige implementaciones según la tabla de arriba — antes de la primera línea de código.
- **El patrón de unión con atributos.** Inscripciones, membresías, líneas de pedido — cuando la *arista misma* tiene datos (fecha, cantidad, rol), la unión (o una clase-arista con dos pointers) es una entidad de primera clase.
- **Desenredar un esquema que creció.** Los síntomas mapean a aristas: filas duplicadas revelan un muchos-a-muchos mal modelado; documentos inflados revelan un embed sin límite.
- **Migrar entre mundos.** Relacional→documentos significa volver a decidir cada FK como embeber vs. pointer; la tabla de arriba es el diccionario de traducción.
- **Feeds de AI y analítica.** Los warehouses quieren las aristas explícitas y estables — la deuda de modelado sale a la luz el día que intentas exportar.

## ¿Cómo deberías modelar cada arista? Matriz de decisión

| Elige… | Cuando… | Cuidado con… |
| --- | --- | --- |
| Embeber | Se leen juntos, con un solo dueño, acotados | El crecimiento: los "pocos" de hoy son los miles de mañana |
| Pointer / FK | Ciclo de vida independiente, alta cardinalidad | Indéxalo — cada lookup y cada include lo pagan |
| Relation / unión | Muchos-a-muchos, o la arista lleva datos | La dirección de la query: sabe desde qué lado vas a preguntar |
| Duplicar (desnormalizar) | Un campo caliente de lectura cruza una arista | El fan-out de updates — la duplicación es una deuda con intereses |

## Limitaciones y trade-offs

- **Los modelos congelan supuestos.** Las decisiones de cardinalidad ("un usuario tiene una dirección") se vuelven esquema; baratas de cambiar en papel, caras después del lanzamiento — modela para la cardinalidad de mañana.
- **Ambos mundos castigan la arista sin índice.** Las columnas FK y los campos pointer son rutas de join; olvidar sus índices es el bug de performance silencioso más común.
- **Embeber cambia integridad por localidad.** Ningún motor garantiza que una copia embebida se mantenga consistente con su fuente — esa ahora es tu lógica de updates.
- **Las uniones multiplican joins; las relations los esconden.** Cada lectura muchos-a-muchos cruza el almacén de aristas — presupuesta la ruta de la consulta, estés en el mundo que estés.
- **Modelar por patrones de acceso también cuesta.** Optimizar para las queries de hoy puede casar el esquema con el producto de hoy; conserva el modelo conceptual como la verdad neutral de fondo.

## El modelado de datos en Back4app

Back4app es una plataforma open-source de Backend as a Service (BaaS) que combina base de datos gestionada, APIs REST y GraphQL generadas automáticamente, autenticación, almacenamiento de archivos y funciones serverless con Cloud Code. Su vocabulario de modelado es la columna de documentos de las tablas de arriba, elevada a primera clase: los **[Pointers](https://docs.parseplatform.org/js/guide/#relational-data)** son aristas uno-a-muchos tipadas, las **Relations** llevan el muchos-a-muchos sin una tabla de unión hecha a mano, y los arrays cubren los pocos-acotados. Cada arista que declaras es inmediatamente recorrible — `include()` camina los pointers en una sola solicitud, GraphQL anida relations en una sola query — y el esquema se mantiene visible y editable en el dashboard, así el modelo físico nunca se pierde de vista del equipo que diseñó el conceptual.
