Nodejs, express, MongDB를 이용한 CRUD(7)_미들웨어
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는 뭐 앞선 방법으로 처리를 했다.