Video Owner #02

0_CyberLover_0·2022년 7월 27일
0

Node.JS #06

목록 보기
2/3

전 단계에서 영상에 영상 소유자의 id를 저장해봤다.

DB를 보면 이 video를 업로드한 유저의 id를 볼수 있다.

추가적으로 watch화면에서 영상 소유자의 이름을 보여주도록 만들었다.

여기까지의 코드를 보고 여기에 쓴 reference가 무슨 쓸모가 있는지 궁금해 진다.

왜냐하면 video.ownerUser id 라는걸 아는데 이걸 직접 해주고 있으니 그렇다.

export const watch = async (req, res) => {
  const { id } = req.params;
  const video = await Video.findById(id);
  const owner = await User.findById(video.owner);
  const owner = await User.findById(video.owner);

그래서 이 코드를 지워 준다.

export const watch = async (req, res) => {
const { id } = req.params;
const video = await Video.findById(id);

이렇게 하면 owner가 없으니까 에러가 난다. 그러니 지워 준다.

export const watch = async (req, res) => {
  const { id } = req.params;
  const video = await Video.findById(id);
  if (!video) {
    return res.status(404).render("404", { pageTitle: "Video not found." });
  }
  return res.render("watch", { pageTitle: video.title, video, owner });
};
  return res.render("watch", { pageTitle: video.title, video});

그래도 에러가 나오니 좀 이상해 질거다.

하지만 이 작업의 핵심은 같은 기능을 더 짧은 코드로 구현해 보는거다.

여기서 videoconsole.log해주면 DB에서 찾은 video를 확인할수 있을거다.

이 상태에서 브라우저를 새로고침하면 오류가 생길거다.

걱정하지 않아도 된다. 핵심은 node console에 출력된 video이다.

이제 mongoose의 도움을 받아 볼거다.

 meta: { views: 0, rating: 0 },
  _id: new ObjectId("6278c6ea843aa2ab1951cb7a"),
  title: 'code',
  fileUrl: 'uploads/videos/8354fc579bb23fa577b406bccaafe453',
  description: 'codecodecodecodecode',
  hashtags: [ '#code' ],
  owner: new ObjectId("6278ad69eeed5a64dd710d36"),
  createdAt: 2022-05-09T07:46:50.207Z,
  __v: 0
}

mongoose는 이 objectIDUser에서 오는걸 아니까 도와 줄거다.

그래서 mongoose가 찾게 만들어 볼거다.

export const watch = async (req, res) => {
  const { id } = req.params;
  const video = await Video.findById(id).populate();

populate가 뭘 하냐면

 owner: new ObjectId("6278ad69eeed5a64dd710d36"),

이 부분을 실제 User 데이터로 채워 준다.

ownerpopulate해준다.

export const watch = async (req, res) => {
 const { id } = req.params;
 const video = await Video.findById(id).populate("owner");

owner만 적어주면 끝이다.

populaterelationship만 적어주면 된다.

그리고 이제 populatevideoconsole.log 해본다.

오류는 걱정하지 말고 일단 새로고침을 해본다. 에러가 있지만 코드를 한번 보도록 한다.

차이가 보일 것이다.

video안에 owner object전체 정보가 들어와 있다.

populate하기전의 owner는 단순히 string이지만

populate를 하면 mongoosevideo를 찾고 그 안에서 owner도 찾아 줄거다.

mongooseownerobject ID인 것을 알고 이 idUser에서 온 것임을 안다.

그래서 mongoose가 해당 User를 찾고 video를 로드했을때 User 정보도 얻을수 있다.

id뿐만 아니라 모든 정보를 볼수 있다는 건 정말 대단한 일이다.

이제 template만 수정해서 작동하게 만들어 본다.

이전 코드에서는 이 두가지를 string으로 변환하고 비교 해야했다.

왜냐하면 이전에는 ownerid에 불과 했다. 하지만 이제는 object이니깐 수정이 필요하다.

watch.pug에서

   if String(video.owner) === String(loggedInUser._id)   
   if String(video.owner._id) === String(loggedInUser._id)   

이 작업만 하면 mongoose가 나머지는 다 해결해주는 거다.

이제 이 부분의 오류도 해결할수 있다.

기존 코드 대신 video.owner.name으로 바꿔 볼거다.

      small Uploaded by #{owner.name}   
      small Uploaded by #{video.owner.name}   

이런 식으로 바꿔 주고 홈페이지 새로고침을 해주면 작동 되는걸 확인할수 있다.

보다시피 영상 소유자가 보이게 된다. 이 기능은 코드 한줄로 구현 된거다.

이게 바로 mongoose relationship의 힘이다.

현재 id만 저장하고 있다. User 전체가 아니라 id만 저장한다.

DB에서 populate를 써도 작동이 되는지 해보니 작동하지 않는다.

populatefunction이 아니다.

하지만 코드에서 populate("owner")를 사용하면 owner object전체가 불려지는걸 볼수 있다.

id를 저장하고 mongoose에 이 idUser model에서 왔다고 알려주기만 하면 된다.

그래서 이런식으로 이름을 통일하고 사전에 모든 model들을 import하는게 좋은거다.

그래야 mongoose가 도와 줄수 있다.

이제 여기에 링크를 걸어본다. 소유자 프로필에 갈수 있게 만들어 본다.

이건 다른 populate, relation을 할수 있게 도와 줄거다.

videoowner를 추가하는건 끝났다.

다음 단계는 특정 사용자가 업로드한 모든 영상을 볼 수 있게 만드는 거다.

그러기 위해선 User.js 코드를 수정해야 한다.

이제 watch template을 수정해 본다.

      small Uploaded by #{video.owner.name}   
small Uploaded by 
      a(href=`/users/${video.owner._id}`)=video.owner.name

새로고침하고 링크를 눌러주면 프로필 화면으로 넘어간다.

이제 사용자가 업로드한 영상들을 가져와야 한다.

여러가지 방법이 있는데 이해를 돕기 위해 좀더 긴 코드를 먼저 보도록 한다.

그 다음 짧은 코드를 보도록 한다.

userController.js를 띄워 준다.

userController에서 user를 찾고 있다.

그리고 idowner로 가진 video들을 찾을 수도 있다.

export const see = async (req, res) => {
  const { id } = req.params;
  const user = await User.findById(id);
  if (!user) {
    return res.status(404).render("404", { pageTitle: "User not found." });
  }
export const see = async (req, res) => {
  const { id } = req.params;
  const user = await User.findById(id);
  if (!user) {
    return res.status(404).render("404", { pageTitle: "User not found." });
  }
  const videos = await Video.find({ owner: user._id });

Video을 쓰고 여러개의 video를 찾아 올거다.

그리고 findOne 이런거 말고 그냥 find를 써서 videoownerparamsid와 같은 video들을 찾는거다.

videoowner idrk URL에 있는 id와 같은 video를 찾는거다.

추가해 준다. 그리고 import가 안되는 경우도 있으니 꼭 확인한다.

안되 있으면

import Video from "../models/Video";

추가 해준다.

그리고 videoconsole.log해주고 새로고침을 해보면 array가 나온다.

URLidvideo owner id가 일치한 경우만 나온거다.

현재 지금 userownerid가 같은 video들을 찾고 있다.

이것만 해도 충분하다. template으로 videos를 보낼수 있다.

const videos = await Video.find({ owner: user._id });
  return res.render("users/profile", {
    pageTitle: user.name,
    user,
    videos,
  });

users/profile.pug에서

block content 
	h1 hello

이 말은 users/profile에서 hello 대신에 videos를 보여 줄수 있다는 거다.

videos를 보여주는 방법은 home에서 하는 방법 이랑 똑같다.


block content 
    each video in videos 
        +video(video)

이렇게 바꿔 줄수 있다.

videos array를 보내고 each video in videos를 썼을 뿐이다.

home하는 방식과 똑같고 mixin도 사용했다. 코드를 복붙해도 코드가 작동하는데 문제가 없다.

물론 minxininclude해줘야 한다.

include ../mixins/video

왜냐하면 지금 /users/profile.pug안에 있기 때문이다.

새로고침해서 확인해 보면 유저가 업로드한 영상이 나오고 있다.

home에서도 다룬거라 새로운 내용은 아니다.

차이점은 profilevideos가 특정 유저의 idowner id가 같은 video만 가져 온다는 거다.

그리고 user.idURL에 있는 id로 찾은 거다.

하지만 이 방법은 긴 코드로 작성 되었다. 짧게 만들 수도 있다.

하지만 이 지름길을 사용하려면 또 다시 DB를 초기화 시켜야 한다.

초기화 해야하는 이유는 model을 수정해야 하기 때문이다.

이제 아무것도 안되고 영상들도 다 사라졌다.

database를 초기화 하고 다음 파트로 넘어가도록 한다.

profile
꿈꾸는 개발자

0개의 댓글