2022이전/node.js

Nodejs, express, MongDB를 이용한 CRUD(7)_미들웨어

바로퇴장 2020. 1. 12. 20:45

MongoDB는 cascade On 과 같은 기능을 따로 제공하지 않는 거 같다. 아무리 검색을 해봐도 mongDB 모델링 할 때 따로 지정해주는 것이 없었던 같다.(앞서 1장에서 말했던 내용) 대신 MongoDB는 미들웨어를 통해서 cascade On과 같은 기능을 따로 만들어 줘야한다.(이걸 일일이 지정해준다니 미쳤군) 미들웨어를 만들어 낼 때 중요한 것은 pre와 post를 잘 구분해 줘야한다. 왜냐하면 내가 값을 저장할 때 pre를 이용하게 되면 생성전의 외래키값을 참조할 수 없기 때문이다.

번외로 나중에 ORM을 이용하면 belong_to 와 같은 것을 이용하면 편하게 구현할 것 같다. 다음에 알아보기로 하자

model/User.js

...
//유저를 삭제할 때
UserSchema.pre('deleteOne', async function(next){
    const self = this._conditions._id;
    await Board.deleteMany({user: self}).exec();
    await Comment.deleteMany({user: self}).exec();
    await Like.deleteMany({user: self}).exec();    
});

this 라는 값은 create나 new User 을 하지 않으면 this._conditions._id을 통해서 자신의 객체를 가져올 수 있다. 만약 create 나 New User을 했다면 바로 this를 통하여 사용이 가능하다.

글쓴이는 User를 지울 때 관련된 모든 게시글, 댓글, Like가 지워지도록 구현을 하였다.

model/Board.js

...
//게시물 지우기
boardSchema.pre(/Delete$/, function(next){
    const self = this._conditions._id;
    Comment.deleteMany({board: self}).exec();
    Like.deleteMany({board: self}).exec();
    next();
}); 

게시물을 지울 때(DeleteOne, DeleteMany, findByIdAndDelete 등 Delete에 해당되는 모든 쿼리)를 적용 시키기 위해서 /Delete$/를 사용하여 미들웨어를 작성하였습니다.(이렇게 작성해야 User 지울 때 하위 좋아요와 Comment도 지울 수 있다.)

Model/Comment.js

...
//댓글 작성시 해당 게시판의 댓글_배열에 추가
CommentSchema.post('save', async function(next){
    const self = this;
    console.log(self.board);
    if(self.board){
        const ref_board = await mongoose.model('Board').findById(self.board);
        await ref_board.updateOne({$push :{comments: self}}).exec();
    }else{
        const parent_comment = await mongoose.model('Comment').findById(self.parent_comment);
        await parent_comment.updateOne({$push :{re_comments: self}}).exec();
    }

});

//댓글 삭제시
CommentSchema.pre(/Delete$/, async function(next){
    const self = this._conditions._id;

    //댓글일 때
    if(self.parent_comment === undefined){
        const ref_board = await mongoose.model('Board').findById(self.board);
        console.log(ref_board);
        await ref_board.updateOne({$pull: {comments: self}});
    }
    //대댓글 일때
    else{
        const parent_comment = await mongoose.model('Comment').findById(self.parent_comment);
        console.log(parent_comment);
        await parent_comment.updateOne({$pull : {re_comments: self._id}}).exec();
    }
});

Comment 도 Board와 마찬가지로 해당하는 /Delete$/를 통하여 모든 Delete쿼리 전에 참조된 외래키값들을 해제시키고 지워지도록 했다.(board[comments]와 같은 외래키값들)

하지만 대댓글이 지워질 때는 update만 이뤄지도록 처리를 하였다.

Model/Like.js

...

//좋아요 할 때 Board에 좋아요 유저 추가하기
LikeSchema.post('save', async function(next){
    const self = this;
    const ref_board = await mongoose.model('Board').findById(self.board);
    await ref_board.updateOne({$push : {likes: this.user}}).exec();
}); 

//좋아요 풀 때 Board에 좋아요 유저 빼기
LikeSchema.pre(/Delete$/, async function(next, doc){
    self = this._conditions._id;
    const ref_board = await mongoose.model('Board').findById(self.board);
    await ref_board.updateOne({$pull : {likes: self.user}}).exec();
})

Like는 뭐 앞선 방법으로 처리를 했다.

github : https://github.com/gmldbd94/node_express_mongoDB