Часто задаваемые вопросы по связям
Эта страница переведена PageTurner AI (бета). Не одобрена официально проектом. Нашли ошибку? Сообщить о проблеме →
Как создать самореферентную связь?
Самореферентные связи — это связи сущности с самой собой. Они полезны для хранения древовидных структур данных. Также шаблон "список смежности" реализуется через самореферентные связи. Например, для создания дерева категорий в приложении: Категории могут содержать вложенные категории, которые в свою очередь содержат другие категории и т.д. Здесь идеально подходят самореферентные связи. По сути, это обычные связи, где целевой сущностью является сама сущность. Пример:
import {
Entity,
PrimaryGeneratedColumn,
Column,
ManyToOne,
OneToMany,
} from "typeorm"
@Entity()
export class Category {
@PrimaryGeneratedColumn()
id: number
@Column()
title: string
@Column()
text: string
@ManyToOne((type) => Category, (category) => category.childCategories)
parentCategory: Category
@OneToMany((type) => Category, (category) => category.parentCategory)
childCategories: Category[]
}
Как использовать ID связи без загрузки связанных данных?
Иногда требуется получить ID связанного объекта без его полной загрузки. Например:
import { Entity, PrimaryGeneratedColumn, Column } from "typeorm"
@Entity()
export class Profile {
@PrimaryGeneratedColumn()
id: number
@Column()
gender: string
@Column()
photo: string
}
import {
Entity,
PrimaryGeneratedColumn,
Column,
OneToOne,
JoinColumn,
} from "typeorm"
import { Profile } from "./Profile"
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number
@Column()
name: string
@OneToOne((type) => Profile)
@JoinColumn()
profile: Profile
}
Если загрузить пользователя без связи profile, в объекте не будет информации о профиле,
включая его ID:
User {
id: 1,
name: "Umed"
}
Но иногда нужно узнать "ID профиля" пользователя без загрузки всего профиля.
Для этого добавьте в сущность свойство с @Column,
именованное точно так же, как столбец, создаваемый связью. Пример:
import {
Entity,
PrimaryGeneratedColumn,
Column,
OneToOne,
JoinColumn,
} from "typeorm"
import { Profile } from "./Profile"
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number
@Column()
name: string
@Column({ nullable: true })
profileId: number
@OneToOne((type) => Profile)
@JoinColumn()
profile: Profile
}
Готово! Теперь при загрузке пользователя будет доступен ID профиля:
User {
id: 1,
name: "Umed",
profileId: 1
}
Как загружать связи в сущностях?
Самый простой способ — опция relations в FindOptions:
const users = await dataSource.getRepository(User).find({
relations: {
profile: true,
photos: true,
videos: true,
},
})
Более гибкая альтернатива — использование QueryBuilder:
const user = await dataSource
.getRepository(User)
.createQueryBuilder("user")
.leftJoinAndSelect("user.profile", "profile")
.leftJoinAndSelect("user.photos", "photo")
.leftJoinAndSelect("user.videos", "video")
.getMany()
С QueryBuilder можно использовать innerJoinAndSelect вместо leftJoinAndSelect
(разница между LEFT JOIN и INNER JOIN описана в документации SQL),
фильтровать связи по условиям, добавлять сортировку и т.д.
Подробнее о QueryBuilder.