Перейти к основному содержанию

Работа со связями

Неофициальный Бета-перевод

Эта страница переведена PageTurner AI (бета). Не одобрена официально проектом. Нашли ошибку? Сообщить о проблеме →

RelationQueryBuilder — это особый тип QueryBuilder, который позволяет работать со связями. С его помощью вы можете связывать сущности в базе данных без необходимости загружать их, а также легко загружать связанные сущности.

Например, у нас есть сущность Post с отношением "многие-ко-многим" к Category под названием categories. Добавим новую категорию в это отношение:

await dataSource
.createQueryBuilder()
.relation(Post, "categories")
.of(post)
.add(category)

Этот код эквивалентен следующему:

const postRepository = dataSource.manager.getRepository(Post)
const post = await postRepository.findOne({
where: {
id: 1,
},
relations: {
categories: true,
},
})
post.categories.push(category)
await postRepository.save(post)

Но работает эффективнее, поскольку выполняет минимальное количество операций и связывает сущности напрямую в базе, в отличие от громоздкого вызова метода save.

Ещё одно преимущество этого подхода — отсутствие необходимости загружать все связанные сущности перед добавлением. Например, если в одном посте содержится десять тысяч категорий, стандартное добавление новых категорий станет проблемой: придётся загрузить пост со всеми категориями, добавить новую и сохранить. Это приведёт к высоким нагрузкам и неприменимо в production-средах. RelationQueryBuilder решает эту проблему.

Также при связывании не обязательно использовать сами сущности — достаточно их идентификаторов. Например, добавим категорию с id = 3 к посту с id = 1:

await dataSource.createQueryBuilder().relation(Post, "categories").of(1).add(3)

Для составных первичных ключей передавайте их как карту id:

await dataSource
.createQueryBuilder()
.relation(Post, "categories")
.of({ firstPostId: 1, secondPostId: 3 })
.add({ firstCategoryId: 2, secondCategoryId: 4 })

Удаление сущностей работает аналогично добавлению:

// this code removes a category from a given post
await dataSource
.createQueryBuilder()
.relation(Post, "categories")
.of(post) // you can use just post id as well
.remove(category) // you can use just category id as well

Добавление и удаление работает для отношений many-to-many и one-to-many. Для one-to-one и many-to-one используйте set:

// this code sets category of a given post
await dataSource
.createQueryBuilder()
.relation(Post, "categories")
.of(post) // you can use just post id as well
.set(category) // you can use just category id as well

Чтобы сбросить связь (установить null), передайте null в set:

// this code unsets category of a given post
await dataSource
.createQueryBuilder()
.relation(Post, "categories")
.of(post) // you can use just post id as well
.set(null)

Помимо обновления связей, конструктор реляционных запросов также позволяет загружать связанные сущности. Например, если в сущности Post есть отношение "многие-ко-многим" categories и "многие-к-одному" user, загрузить их можно следующим кодом:

const post = await dataSource.manager.findOneBy(Post, {
id: 1,
})

post.categories = await dataSource
.createQueryBuilder()
.relation(Post, "categories")
.of(post) // you can use just post id as well
.loadMany()

post.author = await dataSource
.createQueryBuilder()
.relation(Post, "user")
.of(post) // you can use just post id as well
.loadOne()