일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 솝트 후기
- nodejs
- S3
- 프로그래머스
- yolov5
- 카카오
- jwt
- 합격후기
- EC2
- spring-boot
- 솝트
- 서류전형
- 멋사
- 사물인식
- 절차지향
- 인공지능
- Python
- AWS
- objectdetection
- 피로그래밍
- jQuery
- 멋쟁이사자처럼
- Java
- 백준
- 페이지네이션
- CRUD
- 파이썬 #백준 #BFS
- MongoDB
- 파이썬
- 면접전형
- Today
- Total
찔끔찔끔씩😎
[Sopt] 7차 세미나(2) - Nodejs 검색 기능, 페이지네이션 본문
구현할 기능
- 특정 검색어에 해당하는 영화 검색 (search)
- title 에서 검색 (option)
- director 에서 검색 (option)
- title, director 에서 검색 (option)
- 페이지네이션
- 두 개씩 페이지를 나눈다
- 이때 클라이언트에게 마지막 페이지를 알려주기 위해 페이지 수도 함께 리턴해주자.
📍필요한 interfaces 들 추가해주기
interfaces/movie/MoviesResponseDto.ts
기존 MovieResponseDto에는 페이지 수를 넘겨줄 변수가 존재하지 않는다.
따라서 새로운 ResponseDto가 필요하다.
import { MovieInfo } from './MovieInfo';
export interface MoviesResponseDto{
movies: MovieInfo[];
lastPage: number;
}
interfaces/movie/MovieOptionType
검색시 조건을 담아둘 Dto를 만들어 준다. 우리는 세가지 조건을 사용할 것이기 때문에 아래와 같이 만들어준다.
export type MovieOptionType = 'title' | 'director' | 'title_director';
🔎 1. Controller 만들기
1. Search, Option
- req.query를 사용하여 받아온다.
- 위에서 받아온 option 이 지정한 option내에 있나 확인한다. (없다면 Bad Request)
2. Pagenation
- 페이지를 받아오거나, 없다면 1
3. 전체코드
/**
* @route GET /movie?search=&option=&page=
* @desc search movies
* @access public
*/
const getMoviesBySearch = async (req: Request, res: Response) => {
const { search,option } = req.query;
const isOptionType = (option: string): option is MovieOptionType => {
return ["title", "director", "title_director"].indexOf(option) !== -1;
} //-1이면 저안에 없는 것임
if (!isOptionType(option as string)) { // 우리가 정한 option이 아닌 넘이 넘어오면 Bad Request
return res.status(statusCode.BAD_REQUEST).send(util.fail(statusCode.BAD_REQUEST, message.NULL_VALUE));
}
const page: number = Number(req.query.page || 1);
try{
const data = await MovieService.getMoviesBySearch(search as string, option as MovieOptionType, page); // search 타입은 string
res.status(statusCode.OK).send(
util.success(statusCode.OK, message.SEARCH_MOVIE_SUCCESS, data));
}catch(error){
console.log(error);
res.status(statusCode.INTERNAL_SERVER_ERROR).send(
util.fail(
statusCode.INTERNAL_SERVER_ERROR,
message.INTERNAL_SERVER_ERROR,
),
);
}
}
🔎 2. Service 만들기
1. Search, Option
- 몽고 디비에서는 $regex, /.*string.*/을 사용한다. (cf. SQL에서는 LIKE 쓸 때 %string%)
- RegExp 생성자 방법은 let exp = new RegExp('abc') 처럼 사용한다.
- 정규 표현식 생성함수
const regex = (pattern: string) => new RegExp(`.*${pattern}.*`);
- 정규표현식 객체 생성 및 문자열 검색하기
const searchRegex: RegExp = regex(search); // 정규표현식 객체 생성
movies = await Movie.find({ title: { $regex: searchRegex } }) // $regex를 통해 정규표현식과 일치하는 문자열을 검색
2. Pagenation
- 해당 page에 해당하는 데이터 불러오기
perPage : 페이지 당 개수
sort : createAt 을 기준으로 -1 (최신순) 정렬
skip : 앞에서 부터 얼마나 건너뛸지
limit : 개수 제한
- 클라이언트에게 페이지 수 넘겨주기
Model.countDocuments({}) : 모든 도큐먼트 개수 반환
lastPage : 전체 document 개수 / 페이지 당 개수 (올림)
3. 전체코드
const getMoviesBySearch = async (
search: string,
option: MovieOptionType,
page: number,
): Promise<MoviesResponseDto[]> => {
const regex = (pattern: string) => new RegExp(`.*${pattern}.*`); // 몽고디비는 .*ㅇㄻㅇㄹ.* 을 사용하여 검색한다
let movies: MovieInfo[] = [];
const perPage: number = 2; // 페이지 당 데이터 수
try {
const searchRegex: RegExp = regex(search);
if (option === 'title') {
// title에서 검색
movies = await Movie.find({ title: { $regex: searchRegex } })
.sort({createAt:-1}) // 최신순 정렬
.skip(perPage * (page-1)) // 만약 3번째 페이지를 검색하려면, 2 * 2 개를 건너뛰게한다.
.limit(perPage) // 한페이지 당 parPage개 씩 ;
} else if (option === 'director') {
// director에서 검색
movies = await Movie.find({ director: { $regex: searchRegex } })
.sort({createAt:-1}) // 최신순 정렬
.skip(perPage * (page-1)) // 만약 3번째 페이지를 검색하려면, 2 * 2 개를 건너뛰게한다.
.limit(perPage) // 한페이지 당 parPage개 씩 ;
} else {
// title, director 에서 검색
movies = await Movie.find({
$or: [
{ director: { $regex: searchRegex } },
{ title: { $regex: searchRegex } },
],
})
.sort({createAt:-1}) // 최신순 정렬
.skip(perPage * (page-1)) // 만약 3번째 페이지를 검색하려면, 2 * 2 개를 건너뛰게한다.
.limit(perPage) // 한페이지 당 parPage개 씩 ;
}
// 클라에게 넘겨줄 마지막 페이지도 계산해주자
const total: number = await Movie.countDocuments({});
const lastPage: number = Math.ceil(total/perPage);
const data = {
movies,
lastPage
}
return data;
} catch (error) {
console.log(error);
throw error;
}
};
🔎 3. Router 만들기
router.get('/',MovieController.getMoviesBySearch);
'Server > Nodejs' 카테고리의 다른 글
[Sopt] 7차 세미나(1) - Nodjs AWS S3 파일 업로드 (0) | 2022.06.16 |
---|---|
[Sopt] 5차 세미나(1) - Middleware, Authentication, API 명세서 (0) | 2022.05.18 |
[Sopt] 4차 세미나(2) - Nodejs API 실습 (0) | 2022.05.18 |
[Sopt] 4차 세미나(1) - AWS EC2, PM2, S3 (0) | 2022.05.17 |
[Sopt] 3차 세미나(2) - NodeJS CRUD 실습✨ (0) | 2022.05.17 |