이전 파트에서 마무리 짓지 못했던 걸 이어서 해보도록 하겠다.
그러기 위해서 먼저 findOneAndUpdate()
라는 function
에 대해 배워 볼거다.
https://mongoosejs.com/docs/api.html#model_Model.findOneAndUpdate
실제로 model
에는 할수 있는게 굉장히 많다.
여러가지 들이 있는데 이것들의 차이점은 뭐냐면 예를 들어 findOne
을 보면
어떤 조건이든 지정할수가 있다. 제목이 Hello
인 영상을 하나 검색 할 수도 있다.
다른 말로는 영상 제목으로 검색 할수 있다는 말이다.
하지만 영상을 ID
로만 찾을 거란걸 미리 알고 있다면 findOne
을 쓸 필요가 없다.
그냥 findById
를 쓰면 된다. 그리고 이미 준비 되어 있다.
findByIdAndUpdate()
도 있다. 지금 상황에 딱 필요 한거다.
지금 해야 하는 것은 영상의 ID
를 여기 findByIdAndUpdate()
에 입력 하면 된다.
그러면 이제 귀찮게 일일이 수정하는 대신
videoController.js
에서
export const postEdit = async (req, res) => {
const { id } = req.params;
const { title, description, hashtags } = req.body;
const video = await Video.findById(id);
if (!video) {
return res.render("404", { pageTitle: "Video not found." });
}
await Video.findByIdAndUpdate(id, {
title,
description,
hashtags: hashtags
.split(",")
.map((word) => (word.startsWith("#") ? word : `#${word}`)),
});
return res.redirect(`/videos/${id}`);
};
await Video.findByIdAndUpdate()
이라고 하면 된다.
findByIdAndUpdate()
은 두개의 인수 (argument
)가 필요하다.
하나는 업데이트 하고자 하는 영상의 ID
이다. 그 ID
는 바로 위에 있다.
그러니까 id
라고 입력 하고 두번째 인수는 업데이트 할 정보 혹은 내용이다.
그래서 위에 처럼 입력 하게 되었다. hashtags
만 조금 다르다.
이제 코드를 테스트 해보고 아무 문제 없으면 다음으로 넘어 가도록 한다. 잘 작동한다.
두가지 옵션을 배웠다.
하나는 일단 데이터 베이스에서 영상을 찾은후에 수동으로 video.title = something
이런 식으로 수정하는 방법이였다.
다른 방법은 Mongoose
에서 제공하는 function
을 쓰는 거다.
Video
는 사용되는 model
이고 findByIdAndUpdate()
아주 큰 차이가 있다.
대문자 V
의 video
는 만든 영상 Model
이다.
소문자 v
의 video
는 database
에서 검색한 영상 object
이다.
Model
이기 때문에 이곳에 있는 모든 것들을 쓸수 있다.
https://mongoosejs.com/docs/api/model.html
그 중에
exists()
를 살펴 본다.
exists()
굉장히 유용하다. 예를 들어
export const postEdit = async (req, res) => {
const { id } = req.params;
const { title, description, hashtags } = req.body;
const video = await Video.findById(id);
이곳을 보면 영상이 존재하는지 확인해야 한다. 꼭 굳이 video object
를 가져올 필요까지는 없다.
const video = await Video.findById(id);
지금까지 video object
전체를 항상 검색하였다. 왜냐하면 video.title = blabla
이렇게 수정하려면 전체가 다 필요 했기 때문이다. 지금은 video object
전체가 필요 하지 않다.
findById()
대신에 exsts()
를 써 줄수 있다. 그럼 exists()
는 ture
를 return
하게 된다.
영상이 없을 경우 false
를 return
할 것이다.
다시 말하자면 postEdit
에서 video
를 찾을 필요가 없다.
그래서
exists()
로 바꿔 준다.
그리고 exists()
는 ID
를 받지 않는다. exists()
는 filter
를 받는다.
이 말은 원하는 조건은 아무거나 쓸수 있다는 거다. 그래서 이 경우에는
const video = await Video.exists({ _id: id });
여기에 조건을 입력할거다. mongodb
에서 볼수 있듯 object
에는 id
가 있다.
(mongodb
에서 db.videos.find()
를 입력 하는데 아무 반응이 없길래
알아 봤더니 터미널이 종료 되면 다시 mongo shell
안에서 use wetube
를 해줘야 한다.)
이제 object
의 id
가 req.params
의 id
와 같은 경우를 찾는다.
한마디로 video object
를 받는 대신에 true
혹은 false
를 받는거다.
이 경우에도
exists()
를 쓸수 있을까?
export const getEdit = async (req, res) => {
const { id } = req.params;
const video = await Video.findById(id);
if (!video) {
return res.render("404", { pageTitle: "Video not found." });
}
return res.render("edit", { pageTitle: `Edit ${video.title}`, video });
};
안된다. 왜냐하면 getEdit
에서는 video object
가 꼭 필요하다.
object
를 edit template
으로 보내줘야 한다. 이 같은 경우에는 exists()
를 쓸수가 없다.
하지만 postEdit
에서는 video object
가 필요 없다.
단순히 영상이 존재하는지만 확인하면 된다. 그리고 exists()
같은 경우엔 ID
만 받지 않는다.
filter
를 받는다. 그래서 제목이 "hello"
인 영상의 존재 여부를 알수 있다.
원하는 모든 조건을 입력 할수 있다.
ex:) const video = await Video.exists({ title: "hello" });
이제
hashtags
부분을 알아 본다.
hashtags: hashtags
.split(",")
.map((word) => (word.startsWith("#") ? word : `#${word}`)),
생각해야 될게 지금 뭘 하고 싶은지 뭘 하고 있는지 생각해야 한다.
지금 해시태그들을 처리하고 있다. 변경사항을 저장할때마다 혹은 저장하기 직전에
영상 업데이트나 영상 생성을 위해 저장하기 전에 hashtags
를 처리하고 있다.
그러니까 저 부분은 Model
에 저장하기전에 처리 하는 것들이다.
생각해보면 영상을 저장하기전에 여러가지를 할수 있고 해야만 하는 거다.
예를 들어 코멘트가 있다고 가정해본다. 그리고 그 코멘트를 저장하기전에 비속어를 검색하고 싶다고 가정해 본다.
아니면 사용자를 생성한다고 해본다. 그리고 생성하기전에 e-mail
이 존재하는 이메일인지
아닌지 확인한다 던가 그러니깐 저장하기전에 고려해야 할것들이 정말 많다.
hashtag processing
은 그냥 예시일 뿐이다. 실제로는 저장 하기전에 뭔가를 하거나 체크를 한다.
복붙하기에 좀 꺼려지는 이유가 왜냐하면 보다시피 영상을 생성하기전에 그리고 영상을 업데이트 하기전에
해시태그를 처리하고 있다.
그래서 Mongoose
에는 또 다른 걸 써 볼거다.
영상을 저장, 혹은 업데이트 전에 이거저거 하라고 시키는거다.
그걸 Middleware
라고 한다. Express
에서 본 Middleware
랑 똑같다.
Mongoose
에도 Middelware
가 있고, pre
,post
,hook
도 있다.
이름은 그렇게 중요한 것이 아니다. 중요한건 그것들이 끼어들 틈을 만들어 준다는 거다.
objcet
가 저장 되기전에 무엇인가를 먼저하고 나머질 처리 할수 있게 말이다.
그게 정확하게 지금 하고자 하는 거다.
영상을 생성하거나 업데이트 하기전에 그 프로세스를 잠시 중단하고 hashtags
를 처리해서
더 깔끔하게 정리를 하고 그리고 하던걸 마저 하는 거다.
하지만 그건 다음 파트에서 하기로 한다.이번 파트에서는 그냥 몇가지를 알아 본다.
첫번째로 exists()
랑 findById
같은거다.
exists()
는 필터를 필요로 하고 영상의 어떤 property
도 필터 가능하다.
하지만 findById
는 꼭 id
를 인자(argument
)로 받는다.
두번째로 영상을 생성하거나 업데이트 하기전에 작동할 function
의 필요성에 대한 이해이다.
이 같은 경우
await Video.findByIdAndUpdate(id, {
이 function
은 hashtags
를 처리해서 hashtags
같이 보이게 하는
hashtags: hashtags
.split(",")
.map((word) => (word.startsWith("#") ? word : `#${word}`)),
이부분이 될거다.