그저 내가 되었고
🌱mongoDB:: relation 설정하기(populate 이용) 본문
1. 데이터베이스(db)의 종류
- 관계형 데이터베이스 vs 비관계형 데이터베이스
- SQL 기반 데이터베이스 vs. NoSQL 기반 데이터베이스
- 관계형 데이터베이스 vs. NoSQL
- SQL vs. NoSQL
2. 몽고db
- NoSQL 기반 db
- 그러므로 모델끼리의 관계를 직접 설정할 수 없음
- 하지만 다른 documents들이 서로를 참조할 수 있게끔 설정하기는 가능
- SQL에 Join 이 있다면, NoSQL에는 Schema Implant가 있는 것. SQL에서 테이블을 정의할 때 자료형을 정의하듯이, NoSQL에서는 서로 관계를 맺고 싶은 스키마를 다른 스키마에 삽입하면 됨.
- populate 메소드를 사용할 것. populate method는 몽구스 ODM의 핵심 요소로, 몽고디비 컬렉션 간에 동적 관계 맺어주는 역할을 함.
3. 설정하고자 하는 부분의 관계
* 게시글에는 1인 1댓글만 작성 가능
* 게시글 글쓴이는 댓글러 차단 가능
* 댓글 get할때 차단된 사용자인지 아닌지 같이 보내달라고 함
* 차단된 사용자 여부는 post 테이블 참조하면 찾아올 수 있음(banUser column 존재)
4. 코드
1) 스키마 설정
* schema/comments.js
const mongoose = require("mongoose");
const Schema = mongoose.Schema
const CommentsSchema = new mongoose.Schema({
postId: {
type: Schema.Types.ObjectId,
ref: 'Posts', //🌟참조할 모델명을 적음. reference 없이 스키마 이식하면 _id만 갖고옴. ref를 해야 해당_id의 포스트에 해당하는 모든 정보 갖고옴.
required: true,
},
userId: {
type: String,
},
nickName: {
type: String,
},
birth: {
type: String,
},
gender: {
type: String,
},
myPlace: {
type: Array,
},
comment: {
type: String
},
createdAt: {
type: Date,
default: Date.now
},
updatedAt: {
type: Date,
default: Date.now
},
});
module.exports = mongoose.model("Comments", CommentsSchema);
* repositories/comments.js
const Comments = require('../schema/comments');
const Posts = require('../schema/posts');
class CommentsRepository {
//댓글 전체 목록 보기
findAllComments = async (postId) => {
const allCommentsData = await Comments
.find({postId})
.populate('postId') //🌟populate() 이용하여 _id에 해당하는 포스트의 정보 몽땅 불러오기.
//이때 ('postId', 'banUser')하면 해당하는 두개만 잘 불러와지는데 두개 넘어가면 그냥 오류나고 안찾아짐....
.sort({updatedAt: -1});
return allCommentsData;
};
····
}
module.exports = CommentsRepository;
↳postman 실행 결과(http://localhost:3007/comments/637f504fe29cecfaa4d986ea);
{
"comments": [
{
"_id": "63815b50ea21792854cf2b28",
"postId": {
"_id": "637f504fe29cecfaa4d986ea",
"userId": "bbbb",
"nickName": "원지2입니다",
"title": "고인물 김지용님 찾습니다",
"content": "고인물 김지용님 찾습니다",
"location": {
"x": "126.927583207158",
"y": "37.4836907160217"
},
"cafe": "서울 관악구 남부순환로 1592",
"date": "2022-11-29",
"time": [
"2022-11-29T10:00:00.000Z",
"2022-11-29T14:00:00.000Z"
],
"map": "관악구",
"partyMember": 2,
"participant": [
"원지입니다",
"1234",
"jade"
],
"confirmMember": [
"원지2입니다"
],
"banUser": [],
"closed": 0,
"expireAt": "2022-11-29T14:00:00.000Z",
"createdAt": "2022-11-24T11:06:55.573Z",
"updatedAt": "2022-11-24T11:06:55.573Z",
"__v": 0
},
"userId": "jade",
"nickName": "jade",
"gender": "female",
"myPlace": [
"경북",
"영주시"
],
"comment": "댓글",
"createdAt": "2022-11-26T00:18:24.672Z",
"updatedAt": "2022-11-26T00:18:24.672Z",
"__v": 0
}
]
}
잘 불러와지긴 함. 근데 저만큼 다 필요 없고 banUser만 갖고 오면 되니까 특정 부분만 populate하는 문법으로 변경.
const Comments = require('../schema/comments');
const Posts = require('../schema/posts');
class CommentsRepository {
//댓글 전체 목록 보기
findAllComments = async (postId) => {
const allCommentsData = await Comments
.find({postId})
.populate('postId', 'banUser') //🌟populate() 이용하여 _id에 해당하는 포스트의 정보 몽땅 불러오기
.sort({updatedAt: -1});
return allCommentsData;
};
····
}
module.exports = CommentsRepository;
↳postman 실행 결과(http://localhost:3007/comments/637f504fe29cecfaa4d986ea);
{
"comments": [
{
"_id": "63815b50ea21792854cf2b28",
"postId": {
"_id": "637f504fe29cecfaa4d986ea",
"banUser": [
"너"
]
},
"userId": "jade",
"nickName": "jade",
"gender": "female",
"myPlace": [
"경북",
"영주시"
],
"comment": "댓글",
"createdAt": "2022-11-26T00:18:24.672Z",
"updatedAt": "2022-11-26T00:18:24.672Z",
"__v": 0
}
]
}
5. 특정 댓글 작성자가 밴 유저인지 아닌지 조회하기
- 일단 populate 이용해서 댓글 조회하면서 해당 댓글이 달린 post의 postId 이용하여 post scheme의 banUser도 함께 가져오도록 한 상태.
- comment의 모든 데이터를 불러오면서 map을 돌려서 필요한 정보들을 추출하고, 거기다가 banOrNot을 추가함.
- 그러면 해당 comment 작성자의 nickName을 해당 comment가 작성된 포스트의 banUser목록과 비교하여 존재하는지 체크
- 존재하면(즉 ban된 user면) true, 존재하지 않으면(즉 ban된 유저가 아니면) false 반환.
* services/comments.js
const CommentsRepository = require('../repositories/comments');
class CommentsService {
commentsRepository = new CommentsRepository();
//댓글 전체 목록 보기
findAllComments = async (postId) => {
const findAllCommentResult = await this.commentsRepository.findAllComments(postId);
const mapComments = findAllCommentResult.map((item) => {
return {
_id: item._id,
postId: item.postId,
userId: item.userId,
nickName: item.nickName,
gender: item.gender,
myPlace: item.myPlace,
comment : item.comment,
createdAt: item.createdAt,
updatedAt: item.updatedAt,
banOrNot: item.postId.banUser.includes(item.nickName) //🌟
}
})
return mapComments;
};
····
}
module.exports = CommentsService;
↳postman 실행 결과; http://localhost:3007/comments/637f504fe29cecfaa4d986ea
{
"comments": [
{
"_id": "63822ec6e1699208d1d50187",
"postId": {
"_id": "637f504fe29cecfaa4d986ea",
"banUser": [
"jade",
"kim"
]
},
"userId": "jade",
"nickName": "뀽",
"gender": "female",
"myPlace": [
"경북",
"영주시"
],
"comment": "11111댓글",
"createdAt": "2022-11-26T15:20:38.073Z",
"updatedAt": "2022-11-26T15:20:38.073Z",
"banOrNot": false
},
{
"_id": "63822ec4e1699208d1d50182",
"postId": {
"_id": "637f504fe29cecfaa4d986ea",
"banUser": [
"jade",
"kim"
]
},
"userId": "jade",
"nickName": "호호",
"gender": "female",
"myPlace": [
"경북",
"영주시"
],
"comment": "11111댓글",
"createdAt": "2022-11-26T15:20:36.868Z",
"updatedAt": "2022-11-26T15:20:36.868Z",
"banOrNot": false
},
{
"_id": "63815b50ea21792854cf2b28",
"postId": {
"_id": "637f504fe29cecfaa4d986ea",
"banUser": [
"jade",
"kim"
]
},
"userId": "jade",
"nickName": "jade",
"gender": "female",
"myPlace": [
"경북",
"영주시"
],
"comment": "댓글",
"createdAt": "2022-11-26T00:18:24.672Z",
"updatedAt": "2022-11-26T00:18:24.672Z",
"banOrNot": true
}
]
}
'개발 > DB' 카테고리의 다른 글
🌱mongoDB:: 배열 수정 관련 & JS::객체/배열 관련 (0) | 2022.12.01 |
---|---|
🌱mongoDB:: Array로 find? (0) | 2022.11.30 |
🌱mongoDB:: population (0) | 2022.11.29 |
🎯Node.js + mongoDB:: 중첩 조건으로 게시글 필터링하기 (0) | 2022.11.25 |
🎯Node.js + mongoDB:: 게시판 검색 기능 (0) | 2022.11.22 |