TypeORM QueryBuilder Type Safe하게 사용하기

개발하는자·2024년 3월 15일
0

TypeOrm

목록 보기
1/1

1. Pick을 활용한 필드 선택

import { EntityTarget, getRepository } from 'typeorm';


async function selectFields<T, K extends keyof T>(entity: EntityTarget<T>, fields: K[]): Promise<Pick<T, K>[]> {
    const repository = getRepository(entity);
    return repository
        .createQueryBuilder()
        .select(fields.map(field => `${entity.name}.${field}`))
        .getMany() as Promise<Pick<T, K>[]>;
}

// 사용 예시:
// User 엔티티에 대해 id와 name 필드만 조회
const users = await selectFields(User, ['id', 'name']);




2. 조건 배열을 활용한 유연한 TypeORM 쿼리 생성

import { EntityTarget, getRepository, SelectQueryBuilder } from 'typeorm';

// 여러 조건을 나타내기 위한 인터페이스 정의
interface QueryCondition<T> {
    fieldName: EntityFieldNames<T>;
    value: any;
    operator?: '=' | '>' | '<' | 'LIKE';
}

// 여러 조건을 받아서 쿼리를 실행하는 함수
async function queryWithConditions<T>(
    entity: EntityTarget<T>,
    conditions: QueryCondition<T>[]
): Promise<T[]> {
    const repository = getRepository(entity);
    let queryBuilder = repository.createQueryBuilder('entity');

    conditions.forEach(({ fieldName, value, operator = '=' }) => {
        queryBuilder = queryBuilder.andWhere(`entity.${fieldName} ${operator} :value`, { value });
    });

    return queryBuilder.getMany();
}

// 사용 예시
async function fetchUsers() {
    const users = await queryWithConditions(User, [
        { fieldName: 'name', value: 'John Doe' },
        { fieldName: 'age', value: 30, operator: '>' }
    ]);
    return users;
}




3. 유연한 쿼리 빌더

import { EntityTarget, getRepository, SelectQueryBuilder } from 'typeorm';

interface QueryOptions<T> {
  select?: (keyof T)[];
  where?: Partial<Record<keyof T, any>>;
  orderBy?: Array<{ field: keyof T; order: 'ASC' | 'DESC' }>;
}

function buildDynamicQuery<T>(entity: EntityTarget<T>, options: QueryOptions<T>): SelectQueryBuilder<T> {
  const repository = getRepository(entity);
  const queryBuilder = repository.createQueryBuilder(entity.name.toLowerCase());

  if (options.select && options.select.length > 0) {
    queryBuilder.select(options.select.map(field => `${entity.name.toLowerCase()}.${String(field)}`));
  }

  if (options.where) {
    Object.entries(options.where).forEach(([field, value]) => {
      queryBuilder.andWhere(`${entity.name.toLowerCase()}.${field} = :value`, { value });
    });
  }

  if (options.orderBy && options.orderBy.length > 0) {
    options.orderBy.forEach(order => {
      queryBuilder.addOrderBy(`${entity.name.toLowerCase()}.${String(order.field)}`, order.order);
    });
  }

  return queryBuilder;
}

// 사용 예시
async function fetchUsersWithDynamicQuery() {
  const userQuery = buildDynamicQuery(User, {
    select: ['id', 'name'],
    where: { isActive: true, age: 30 },
    orderBy: [{ field: 'name', order: 'ASC' }],
  });
  const users = await userQuery.getMany();
  return users;
}
profile
To the moon.

0개의 댓글