NestJs - Join API 구현 본문
반응형
상당히 어려웠던 부분이다.
내가 구현했던 ERD에는
일 대 일 관계와 일 대 다 관계는 없기에,
다 대 일 / 다 대 다 관계에서 다룬다.
다 대 일
다 대 일로 작업한 내용은 카테고리였다.
// dto create-product.input.ts
@Field(() => String)
productCategory: string; // dto 에 카테고리 추가
// product.service.ts
create 함수 내부에 추가
create({
const { productCategory, ...product } = createProductInput;
// 구조 분해 할당
}
const result = this.productsRepository.save({
...product,
productCategory: { category_id: productCategory },
// 이떄, category_id == '카테고리 엔티티'안에 있는 카테고리 아이디 변수명이다.
});
return result
}
// 조회할 때 함께 조회할 수 있도록 relations 에 추가
// findAll & findOne 은 read 를 위한 함수와 연결된 함수
// findAll
findAll(): Promise<Product[]> {
return this.productsRepository.find({
relations: ['productCategory'], // 엔티티 이름을 문자열 타입으로 넣어준다.
});
}
// findOne
findOne({ productId }: IProductServiceFindOne): Promise<Product> {
return this.productsRepository.findOne({
where: { id: productId },
relations: ['productCategory'],
});
}
플레이그라운드에서 확인한 모습
다 대 다
다 대 다의 경우는 brand / allergy 를 적용하는 과정이었는데,
방식 자체는 동일하므로 하나에 대해서만 다룬다.
이 경우에는 input 할 때 함께 입력하는 방식을 택한다.
마찬가지로 dto에 파일을 수정한다.
// dto create-product.input.ts
@Field(() => [String]) // graphql type
productBrands: string[]; // typescript type
@Field(() => [String])
productAllegies: string[];
// product.service.ts
서비스 주입
constructor(
@InjectRepository(Product)
private readonly productsRepository: Repository<Product>,
private readonly productsAllegiesService: ProductsAllegiesService, // 알러지
private readonly productsBrandsService: ProductBrandService, // 브랜드
) {}
// create 함수 내부에 추가
create({
const { productCategory, productBrand, productAllegies...product } = createProductInput;
// 구조 분해 할당
}
// 중복된 브랜드값을 걸러내어 저장하기 위한 로직
const prevBrands = await this.productsBrandsService.findByBrands({
productBrands, // 기존 저장되어 있는 브랜드 배열
// findByBrands 는 Read 와 함께쓰는 함수 / 밑에서 설명
});
const tempForBrand = [];
productBrands.forEach((el) => {
const isExists = prevBrands.find((prevEl) => el === prevEl.brand_name);
if (!isExists) tempForBrand.push({ brand_name: el });
}); // 기존 저장된 배열과 일치하지 않을 경우 추가하는 알고리즘
const newBrands = await this.productsBrandsService.bulkInsert({
names: tempForBrand, // bulkInsert 밑에서 설명
});
const brandsNames = [...prevBrands, ...newBrands.identifiers];
//
const result = this.productsRepository.save({
...product,
productCategory: { category_id: productCategory },
productAllegies: allegiesNames, // 결과로 전송
productBrands: brandsNames, // product.entity : input
});
return result
}
// 조회할 때 함께 조회할 수 있도록 relations 에 추가
// findAll & findOne 은 read 를 위한 함수와 연결된 함수
// findAll
findAll(): Promise<Product[]> {
return this.productsRepository.find({
relations: ['productCategory', 'productAllegy', 'productBrand'], // 엔티티 이름을 문자열 타입으로 넣어준다.
});
}
// findOne
findOne({ productId }: IProductServiceFindOne): Promise<Product> {
return this.productsRepository.findOne({
where: { id: productId },
relations: ['productCategory', 'productAllegy', 'productBrand'],
});
}
// productBrand.service.ts
@Injectable() // DI
export class ProductBrandService {
constructor(
@InjectRepository(ProductBrand)
private readonly productBrandRepository: Repository<ProductBrand>,
) {}
findByBrands({ productBrands }: IProductBrandServiceFindBynames) {
return this.productBrandRepository.find({
where: { brand_name: In(productBrands) }, // brand 를 찾는 함수
});
}
bulkInsert({ names }: IProductBrandsServiceBulkInsert) {
return this.productBrandRepository.insert(names); // 대량으로 저장하는 함수 // 다량의 데이터에 효과적
}
}
반응형
'개발 > nest.js' 카테고리의 다른 글
NestJs - JWT 사용한 인증 & 인가 처리 (access token) (0) | 2023.02.12 |
---|---|
Nest JS - 회원 API 구현 (hashing & ConflictException) (0) | 2023.02.10 |
NestJS - CRUD / TypeORM (0) | 2023.02.07 |
entity 작성 / OneToOne || OneToMany & ManyToOne || ManyToMany / 관계도 MySQL 적용 (0) | 2023.02.04 |
집계 & 정렬 & 서브 쿼리 (0) | 2023.02.04 |
Comments