기억해!!!!!! loader/db.ts에서 connectDB 안에
import mongoose from "mongoose";
import config from "../config";
import Movie from "../models/Movie";
import Review from "../models/Review";
const connectDB = async () => {
try {
await mongoose.connect(config.mongoURI);
mongoose.set('autoCreate', true);
console.log("Mongoose Connected ...");
// 여기
Movie.createCollection().then(function (collection) {
console.log("Movie Collection is created!");
});
Review.createCollection().then(function (collection) {
console.log("Review Collection is created!");
});
// 안에
} catch (err: any) {
console.error(err.message);
process.exit(1);
}
};
export default connectDB;
컬렉션이름.createCollection()할 때 putty에서 서버 돌리면 mongodb에서 컬렉션이 안만들어짐 먼저 local 환경에서 서버 한번 띄워야지 mongodb compass에 collection이 만들어진걸 확인할 수 있다!!!!!!!!!!
+) 그리고,, git clone해서 putty에서 배포하고 local에 있는 코드를 수정한 뒤에 수정한 버전으로 api test를 하고싶으면 localhost로 서버를 띄워서 봐야함 즉 local에서 코드 수정한 내용은 aws에 반영이 안된다는 소리 아니 이 당연한걸 도대체 왜 이걸로 삽질했지?? 진짜어이없다
MovieRouter.ts
const { body } = require("express-validator");
router.post("/movies/:movieId", [
body("title").notEmpty().withMessage("제목써라"),
body("writer").notEmpty().withMessage("글쓴이써라"),
body("content").notEmpty().withMessage("내용써라")
], ReviewController.createReview);
Controller 단에서 express-validator의 body를 가져와서 여러가지 검증을 해준다
MovieController.ts
const { validationResult } = require("express-validator");
const createMovie = async (req: Request, res: Response) => {
const error = validationResult(req);
if (!error.isEmpty()){
console.log(error);
return res.status(statusCode.BAD_REQUEST).send(util.fail(statusCode.BAD_REQUEST, message.BAD_REQUEST, res.json({ errors: error.array() })));
}
validationResult로 req에 넘어온 error를 검증해준다
에러메시지를 그대로 보여주고 싶으면
res.json({ errors: error.array() }
이렇게 가져오면 됨
populate란?
document의 경로를 다른 collection의 실제 document로 자동으로 바꾸는 방법
몽고db에서 하나의 document가 다른 객체의 ObjectId를 참조할 때 ObjectId를 해당 객체로 바꾸는 작업을 해주는 거라고 알면 됨
ReviewInfo.ts
import mongoose from "mongoose";
export interface ReviewInfo {
writer: mongoose.Types.ObjectId;
movie: mongoose.Types.ObjectId;
title: string;
content: string;
}
review가 movie와 writer를 참조하는 상황이다
이 때 revier를 조회할 때 movie 객체 전부와 writer 객체의 name 필드만 가져오도록 해보겠음
ReviewService.ts
const getReviews = async (movieId: string): Promise<ReviewResponseDto[]> => {
try{
const reviews = await Review.find({
movie: movieId
}).populate('writer', 'name').populate('movie'); // writer 객체의 name만, movie 객체 전부 가져옴
const data = await Promise.all(reviews.map((review: any) => {
const result = {
writer: review.writer.name, // writer 이름만
movie: review.movie, // movie 객체 전부가 통째로 가져옴
title: review.title,
content: review.content
};
return result;
}));
return data;
} catch (error){
console.log(error);
throw error;
}
}
const reviews = await Review.find({
movie: movieId
}).populate('writer', 'name').populate('movie');
review를 찾는데 key는 매개변수로 전달받은 movieId로 한다.
review는 writer와 movie를 둘 다 참조하기 때문에 populate를 안하면 그냥 ObjectId로만 값을 가져온다.
따라서 writer 객체는 name 필드만, movie 객체는 전부 가져오도록 populate 해준다
writer의 password와 같은 다른 필드도 가져오고 싶으면 아래처럼 써주면 됨
.populate('writer', 'name password')
이렇게 가져온 reviews라는 배열을 map으로 돌려서 새로운 배열을 만들어준다
const data = await Promise.all(reviews.map((review: any) => {
const result = {
writer: review.writer.name, // writer 이름만
movie: review.movie, // movie 객체 전부가 통째로 가져옴
title: review.title,
content: review.content
};
return result;
}));
return data;
result에 각각의 필드에 해당하는 값을 넣어주고 이걸 반환하여 data에 저장한다
ReviewResponseDto.ts는 애초에 writer 필드를 writer name만 받기로 정했기 때문에 그것만 넣어준다
Promise.all()에 대한 자세한 설명은 아래 참고
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
https://merrily-code.tistory.com/214
참고로 ReviewResponseDto.ts는 다음과 같이 생겼음
import { MovieInfo } from "../movie/MovieInfo";
export interface ReviewResponseDto {
writer: string; // writer 이름만
movie: MovieInfo; // movie 객체 전체 가져오도록
title: string;
content: string;
}
ReviewController.ts
const getReviews = async (req: Request, res: Response) => {
const { movieId } = req.params;
try{
const data: ReviewResponseDto[] = await ReviewService.getReviews(movieId);
res.status(statusCode.OK).send(util.success(statusCode.OK, message.READ_REVIEW_SUCCESS, data));
} catch(error){
console.log(error)
res.status(statusCode.INTERNAL_SERVER_ERROR).send(util.fail(statusCode.INTERNAL_SERVER_ERROR, message.READ_REVIEW_FAIL));
}
}