← назад к разделу

QueryBuilder нужен, когда репозиторного find уже мало: join, агрегация, часть полей или особый порядок. Он строит SQL с параметрами, а не склеивает входные данные в строку.

Join и параметры

const products = await repo.createQueryBuilder('product')
  .leftJoinAndSelect('product.seller', 'seller')
  .where('product.price >= :minPrice', { minPrice: 1000 })
  .andWhere('seller.active = :active', { active: true })
  .orderBy('product.id', 'ASC')
  .getMany();

product и seller - aliases. Они используются в join, where и select. Опечатка в alias приводит к ошибке SQL или неожиданному запросу, поэтому единые имена выбирают на уровне сценария.

Параметр :minPrice передается драйверу отдельно. Строка product.price >= ${req.query.price} создает SQL-инъекцию и ломает типы.

Проекция вместо всей entity

Для списка не всегда нужны все колонки и все relations. QueryBuilder позволяет выбрать поля:

const rows = await repo.createQueryBuilder('product')
  .select('product.id', 'id')
  .addSelect('product.name', 'name')
  .where('product.active = :active', { active: true })
  .getRawMany();

getMany возвращает entities, getRawMany - строки проекции. Выбирают одно поведение явно и не смешивают ожидания.

Коротко

  • QueryBuilder используют для joins, проекций и агрегатов.
  • Входные данные передают параметрами, не интерполяцией.
  • Aliases должны совпадать во всех частях запроса.
  • getMany и getRawMany имеют разный результат.
  • Выбирают только нужные поля и relations.

Что почитать дальше