저번에 만들었던 페이지네이션에 검색 기능을 추가하려고 한다.
입력으로 쿼리문을 사용해서 요구사항을 받아줄건데 크게 다음의 세개의 기능을 넣어서 구현하려고 한다.
- 카테고리(category) : 카테고리를 입력하면 원하는 카테고리에서만 데이터를 가져오기
- 분류하기(sortBy) : 신상품순, 낮은가격순, 판매량많은순 이렇게 세가지 기준으로 분류
- 검색하기(name) : 검색어를 입력하면 검색어가 들어간 데이터만 가져오기
입력데이터 예시) url/goods?category=SHIRTS?name=stripe?sortBy=BEST
이런 url으로 데이터를 요청하면 카테고리가 셔츠이고 이름에 stripe가 들어가고 판매량 많은 순으로 데이터를 출력해주면 된다.
자 이제 요구사항대로 직접 구현해보자.
async searchGoods(page: SearchGoodsDto) {
//쿼리로 category가 들어있으면 카테고리에 맞는것들만 가져와야함
const { sortBy, category, name } = page;
console.log(page);
/**total : 물품갯수 카운트, sortObj : 분류기준 , found : 찾은 물풀들 */
let total, sortObj, found;
if (!sortBy) {
//sortBy가 비어있으면 분류를 안함
} else {
switch (sortBy) {
case SortMethod.BEST:
sortObj = { sellnum: 'DESC' };
break;
case SortMethod.LOWPRICE:
sortObj = { price: 'ASC' };
break;
case SortMethod.NEW:
sortObj = { createdAt: 'DESC' };
break;
}
}
if (!category) {
//category가 비어있을때
total = await this.goodsRepository.count();
found = await this.getPagination(page, sortObj, name);
} else {
//category가 들어있을 때
/**카테고리에 알맞은 데이터 전체 갯수 세기 */
total = await this.goodsRepository.count({ category });
found = await this.getPaginationByCategory(page, category, sortObj, name);
}
return new Page(total, page.pageSize, found);
}
/**카테고리에 따른 페이지네이션*/
async getPaginationByCategory(page, category, sortObj, name) {
const goods = await this.goodsRepository.find({
where: { category, name: Like(`%${name}%`) },
take: page.getLimit(),
skip: page.getOffset(),
order: sortObj,
});
return goods;
}
/**카테고리 없이 페이지네이션 */
async getPagination(page, sortObj, name) {
console.log(sortObj);
const goods = await this.goodsRepository.find({
where: { name: Like(`%${name}%`) },
take: page.getLimit(),
skip: page.getOffset(),
order: sortObj,
});
return goods;
}
먼저 요청한 url의 쿼리를 컨트롤러에서 받아서 page라는 변수에 저장해놓은 다음,
분류기준이 판매량많은순(BEST), 낮은가격순(LOWPRICE), 신상품순(NEW)인지 스위치문에서 체크를 해준다.
if (!sortBy) {
//sortBy가 비어있으면 분류를 안함
} else {
switch (sortBy) {
case SortMethod.BEST:
sortObj = { sellnum: 'DESC' };
break;
case SortMethod.LOWPRICE:
sortObj = { price: 'ASC' };
break;
case SortMethod.NEW:
sortObj = { createdAt: 'DESC' };
break;
}
}
카테고리를 쿼리에 넣지않아도 데이터를 불러올수있게 로직을 만들었기 때문에, category가 있을 때와 없을 때를 각각 처리해주었다.
if (!category) {
//category가 비어있을때
total = await this.goodsRepository.count();
found = await this.getPagination(page, sortObj, name);
} else {
//category가 들어있을 때
/**카테고리에 알맞은 데이터 전체 갯수 세기 */
total = await this.goodsRepository.count({ category });
found = await this.getPaginationByCategory(page, category, sortObj, name);
}
카테고리가 없을 때는 카테고리 없이 find매서드 옵션을 주어서 원하는 값들을 찾아준다.
이때 검색어로 받은 name은 where 옵션의 Like함수로 처리한다.
(find에 관한 더 자세한 정보는 다음의 링크 참조 typeorm-find)
/**카테고리 없이 페이지네이션 */
async getPagination(page, sortObj, name) {
console.log(sortObj);
const goods = await this.goodsRepository.find({
where: { name: Like(`%${name}%`) },
take: page.getLimit(),
skip: page.getOffset(),
order: sortObj,
});
return goods;
}
카테고리가 있을 때는 카테고리가 없을 때에 find 옵션으로 category만 추가해서 원하는 값들을 찾아주면 된다.
/**카테고리에 따른 페이지네이션*/
async getPaginationByCategory(page, category, sortObj, name) {
const goods = await this.goodsRepository.find({
where: { category, name: Like(`%${name}%`) },
take: page.getLimit(),
skip: page.getOffset(),
order: sortObj,
});
return goods;
}
원하는대로 구현이 된것을 확인할 수 있다!