Relaciones
Overview
Sección titulada «Overview»Las relaciones definen cómo las colecciones están conectadas a nivel de base de datos. Permiten a Rebase:
- Renderizar campos selectores de relación en formularios de entidad
- Resolver entidades relacionadas al mostrar previsualizaciones
- Generar restricciones de clave foránea en el esquema Drizzle
- Soportar comportamientos de eliminación/actualización en cascada
Las relaciones se pueden definir directamente dentro de la propiedad, o explícitamente en el array relations de una colección:
1. Relaciones en Línea (Recomendado)
Sección titulada «1. Relaciones en Línea (Recomendado)»Puedes definir la relación directamente en la propiedad. El framework las extrae automáticamente al array relations[] de la colección en el momento de la normalización, por lo que ya no necesitas una entrada relations[] separada para las propiedades.
const postsCollection: EntityCollection = { slug: "posts", name: "Posts", table: "posts", properties: { title: { type: "string", name: "Title" }, content: { type: "string", name: "Content", multiline: true }, author: { type: "relation", name: "Author", target: () => usersCollection, cardinality: "one", direction: "owning", localKey: "author_id" } }};2. Array de Relaciones Explícito
Sección titulada «2. Array de Relaciones Explícito»Para casos de uso avanzados o cuando una relación no se mapea directamente a un campo de formulario, puedes definirla en el array relations:
const postsCollection: EntityCollection = { slug: "posts", name: "Posts", table: "posts", properties: { title: { type: "string", name: "Title" }, content: { type: "string", name: "Content", multiline: true }, author: { type: "relation", name: "Author", relationName: "author" } }, relations: [ { relationName: "author", target: () => usersCollection, cardinality: "one", localKey: "author_id" } ]};Tipos de Relación
Sección titulada «Tipos de Relación»Uno a Uno / Muchos a Uno
Sección titulada «Uno a Uno / Muchos a Uno»Una clave foránea en esta tabla apunta a la clave primaria de otra tabla.
relations: [ { relationName: "author", target: () => usersCollection, cardinality: "one", // This entity has ONE author direction: "owning", // The FK is on THIS table localKey: "author_id" // Column on the posts table }]Esto crea: posts.author_id → users.id
Uno a Muchos (Inversa)
Sección titulada «Uno a Muchos (Inversa)»La clave foránea está en la tabla objetivo, apuntando de vuelta a esta entidad.
// On the Users collection:relations: [ { relationName: "posts", target: () => postsCollection, cardinality: "many", // This user has MANY posts direction: "inverse", // The FK is on the TARGET table foreignKeyOnTarget: "author_id" // Column on the posts table }]Muchos a Muchos (Tabla de Unión)
Sección titulada «Muchos a Muchos (Tabla de Unión)»Dos colecciones conectadas a través de una tabla de unión intermedia.
// On the Users collection:relations: [ { relationName: "roles", target: () => rolesCollection, cardinality: "many", direction: "owning", through: { table: "user_roles", // Junction table name sourceColumn: "user_id", // FK to this collection targetColumn: "role_id" // FK to target collection } }]Esto crea:
CREATE TABLE user_roles ( user_id INTEGER REFERENCES users(id), role_id INTEGER REFERENCES roles(id), PRIMARY KEY (user_id, role_id));Propiedades de Relación
Sección titulada «Propiedades de Relación»Para renderizar un campo de relación en un formulario, añade una propiedad con type: "relation":
properties: { author: { type: "relation", name: "Author", target: () => usersCollection, // Target collection widget: "select" // "select" (dropdown) or "dialog" (full picker) }}
Al renderizar una previsualización (como en una celda de tabla o un chip de referencia), Rebase maneja la hidratación automáticamente:

Uniones Multi-salto
Sección titulada «Uniones Multi-salto»Para relaciones complejas que atraviesan múltiples tablas, usa joinPath:
// Users → Permissions through Rolesrelations: [ { relationName: "permissions", target: () => permissionsCollection, cardinality: "many", joinPath: [ { table: "user_roles", on: { from: "id", to: "user_id" } }, { table: "roles", on: { from: "role_id", to: "id" } }, { table: "role_permissions", on: { from: "id", to: "role_id" } }, { table: "permissions", on: { from: "permission_id", to: "id" } } ] }]Uniones de Clave Compuesta
Sección titulada «Uniones de Clave Compuesta»joinPath: [ { table: "customers", on: { from: ["company_code", "region_id"], // Multiple columns to: ["code", "region_id"] } }]Reglas de Cascada
Sección titulada «Reglas de Cascada»Controla qué sucede cuando las entidades relacionadas son actualizadas o eliminadas:
relations: [ { relationName: "author", target: () => usersCollection, cardinality: "one", localKey: "author_id", onDelete: "cascade", // Delete posts when user is deleted onUpdate: "cascade" // Update FK when user ID changes }]| Acción | Comportamiento |
|---|---|
"cascade" | Propagar el cambio a las filas relacionadas |
"restrict" | Prevenir la operación si existen filas relacionadas |
"no action" | Igual que restrict (posponer a la verificación de restricción) |
"set null" | Establecer la columna FK a NULL |
"set default" | Establecer la columna FK a su valor predeterminado |
Obtención de Relaciones en el SDK
Sección titulada «Obtención de Relaciones en el SDK»Al consultar datos a través del SDK del Cliente Rebase, las relaciones no se incluyen por defecto. Usa el método include() para solicitar entidades relacionadas junto con los datos primarios.
Incluir relaciones específicas
Sección titulada «Incluir relaciones específicas»const { data } = await client.data.articles .include("author", "categories") .find();Incluir todas las relaciones
Sección titulada «Incluir todas las relaciones»const { data } = await client.data.articles .include("*") .find();Uso de la sintaxis de parámetros
Sección titulada «Uso de la sintaxis de parámetros»const { data } = await client.data.articles.find({ include: ["author", "categories"]});Estructura de la respuesta
Sección titulada «Estructura de la respuesta»Cuando se incluye, la respuesta contiene tanto la clave foránea escalar como el objeto de relación hidratado:
const { data } = await client.data.articles .include("author") .find();
for (const article of data) { // Scalar FK — always present article.values.author_id; // "uuid-1234"
// Hydrated relation — only present when included article.values.author?.name; // "Jane Doe"}Los nombres de relación pasados a
include()deben coincidir con elrelationNamedefinido en el arrayrelationsde la colección.
Para la referencia completa del constructor de consultas (filtrado, ordenación, paginación, en tiempo real), consulta la documentación del SDK del Cliente.
Interfaz Completa de Relación
Sección titulada «Interfaz Completa de Relación»interface Relation { relationName?: string; target: () => EntityCollection; cardinality: "one" | "many"; direction?: "owning" | "inverse"; inverseRelationName?: string; localKey?: string; foreignKeyOnTarget?: string; through?: { table: string; sourceColumn: string; targetColumn: string; }; joinPath?: JoinStep[]; onUpdate?: "cascade" | "restrict" | "no action" | "set null" | "set default"; onDelete?: "cascade" | "restrict" | "no action" | "set null" | "set default"; overrides?: Partial<EntityCollection>; validation?: { required?: boolean };}Próximos Pasos
Sección titulada «Próximos Pasos»- Reglas de Seguridad — Seguridad a Nivel de Fila
- Propiedades — Referencia de tipos de propiedad