-
Notifications
You must be signed in to change notification settings - Fork 0
Relations
Carlos Lopez edited this page Jul 16, 2026
·
1 revision
Define y usa relaciones entre entidades.
import { defineRelations } from '@kettu/gitdb';
defineRelations(User, {
posts: {
type: 'many',
entity: Post,
foreignKey: 'userId'
}
});Un usuario tiene muchos posts.
defineRelations(Post, {
author: {
type: 'one',
entity: User,
foreignKey: 'userId'
}
});Muchos posts pertenecen a un usuario.
import { entity, uuid, text, defineRelations } from '@kettu/gitdb';
// Entidades
const User = entity('users', {
id: uuid().primary(),
name: text(),
email: text()
});
const Post = entity('posts', {
id: uuid().primary(),
userId: uuid(),
title: text(),
content: text()
});
const Comment = entity('comments', {
id: uuid().primary(),
postId: uuid(),
userId: uuid(),
text: text()
});
// Relaciones
defineRelations(User, {
posts: {
type: 'many',
entity: Post,
foreignKey: 'userId'
},
comments: {
type: 'many',
entity: Comment,
foreignKey: 'userId'
}
});
defineRelations(Post, {
author: {
type: 'one',
entity: User,
foreignKey: 'userId'
},
comments: {
type: 'many',
entity: Comment,
foreignKey: 'postId'
}
});
defineRelations(Comment, {
author: {
type: 'one',
entity: User,
foreignKey: 'userId'
},
post: {
type: 'one',
entity: Post,
foreignKey: 'postId'
}
});const user = await db
.select()
.from(User)
.where(eq('id', 'user-1'))
.include({
posts: true
});
// user.posts contiene todos los posts del usuarioconst user = await db
.select()
.from(User)
.where(eq('id', 'user-1'))
.include({
posts: true,
comments: true
});const user = await db
.select()
.from(User)
.where(eq('id', 'user-1'))
.include({
posts: {
include: {
comments: true
}
}
});
// Acceder a comments del post
user.posts.forEach(post => {
console.log(post.comments);
});const post = await db
.select()
.from(Post)
.where(eq('id', 'post-1'))
.include({
author: true // Carga el usuario que escribió el post
});
console.log(post.author.name);// Primero crear usuario
const userId = 'user-1';
await db.insert(User).values({
id: userId,
name: 'John Doe',
email: 'john@example.com'
});
// Luego crear posts con referencia
await db.insert(Post).values({
id: 'post-1',
userId: userId,
title: 'First Post',
content: '...'
});
await db.insert(Post).values({
id: 'post-2',
userId: userId,
title: 'Second Post',
content: '...'
});Al eliminar, cuida las relaciones:
// Opción 1: Eliminar primero los posts
await db.delete().from(Post).where(eq('userId', 'user-1'));
// Luego eliminar usuario
await db.delete().from(User).where(eq('id', 'user-1'));
// Opción 2: Soft delete (agregar campo deletedAt)
await db
.update(User)
.set({ deletedAt: new Date() })
.where(eq('id', 'user-1'));const userPosts = await db
.select()
.from(Post)
.where(eq('userId', 'user-1'));const userComments = await db
.select()
.from(Comment)
.where(eq('userId', 'user-1'));const posts = await db
.select()
.from(Post)
.include({
comments: true
});
posts.forEach(post => {
console.log(`Post "${post.title}" has ${post.comments.length} comments`);
});- Mantén IDs consistentes - Usa UUID o secuencias consistentes
- Define ambos lados - Si A → B, también define B ← A
- Lazy load cuando sea posible - No cargues relaciones innecesarias
- Maneja huérfanos - Cuando eliminas padre, ¿qué pasa con los hijos?
- Usa includeRelations - Carga relaciones en una sola query
- No hay cascada automática (debes manejar manualmente)
- No hay restricciones de integridad referencial (validar en app)
- Las relaciones se cargan en memoria (cuidado con grandes datasets)
- Query API - Operaciones CRUD
- Aggregations - COUNT, SUM, AVG