16. mongoDB에서 관계설정

유현준·2022년 9월 3일
0

hello! Nest

목록 보기
16/17

1. 준비물

    "@nestjs/mongoose": "^8.0.1",
    "mongoose": "^5.13.9",
  • 기존에는 mogoose 버전은 6 이상, nestjs/mongoose는 9이상 버전이었다.
  • mongoDB에서 관계 설정과 관련해서는 populate method를 이용하는데, 이와 관련해서 mongoose 버전이 6 이상인 경우, nestjs/mongoose 버전 8 이상인 것과 호환이 잘 안된다는 내용이 있었다.
  • 실제로, populate가 잘 먹히지 않는 것을 목격할 수 있었고, 관계설정 시에는 mongoDB 버전을 위와 같이 설정하는 것이 안전한 것 같다.

2. 관계 주입(?)

  • 특정 테이블A(스키마)에 관계를 주입시킬 테이블B(스키마)이 있는 module에 테이블 A를 import한다.
imports: [   MongooseModule.forFeature([
      { name: Cat.name, schema: CatSchema },
      { name: Comments.name, schema: CommentsSchema },
    ])
         ], // DB Query 작업을 위해, schema import | Authmodule 순환참조

3. schema에서 관계 설정

  • B 테이블에서 A 테이블과 관계를 설정해준다. 이 때, virtual field를 이용해서 작업한다.
  • virtual filed를 schema에 적용시켜준다. 이 때, field 값 이름은 virtual filed와 동일하게 한다.
1. 관게설정
_CatSchema.virtual('comments', {
  // 연동되는 스키마와 식별자를 지정
  // cats의 _id === comments의 info를 엮음.
  ref: 'comments',
  localField: '_id', // B테이블의 관계 식별자
  foreignField: 'info', // A테이블의 관계 식별자
});
_CatSchema.set('toObject', { virtuals: true });
_CatSchema.set('toJSON', { virtuals: true });

export const CatSchema = _CatSchema;

----
2. virtual field 등록
onst options: SchemaOptions = {
  timestamps: true, // DB에서 스키마 생성 시 일자를 출력
};

@Schema(options)
export class Cat extends Document {

readonly comments: Comments[] // Comments는 CommentSchema 객체이다.
}

4. select query에서 관계를 명시

  • 관계 설정을 활용하여 select를 할 때에는, mongoose의 populate 메소드를 이용한다.
const comments = mongoose.model('comments', CommentsSchema); // du연결한 schema 이름
const data = await this.catModel.find().populate('comments', comments); // virtual field 이름 명시해야함.
return data;

5. 유의사항! 관계 식별자 값을 insert 할 때는 반드시 ObjectId 값으로 삽입

  • popluate 메소드를 이용하면, 다음과 같이 query가 작성된다.
comments.find(
  { info: { '$in': [ ObjectId("631359b781bd8128c4504cae"), ObjectId("631359c181bd8128c4504cb1") ] }},
  { projection: {} })
  • 즉, 테이블 A와 B에서 상호간 관계식별자인 info 필드값과 _id 필드값이 일치한 필드를 찾는 것이다.
  • 이 때, 필자는 쿼리문이 잘 전달되었음에도 불구하고, response에서 comments 값이 빈 배열로 출력된 것을 목격했다. 다음과 같이 말이다.
  "data": [
    {
      "name": "레드",
      "comments": []
    },
    {
      "name": "블루",
      "comments": []
    }
  ]
}
  • 원인은 comments에 info 값을 insert할 시에, ObjectId 타입아 아니라 ,string 타입으로 insert가 되어, query문이 제대로 작동하지 않았던 것이다.
  • 그래서 다음과 같이 comments에 데이터를 insert하는 코드에서 info에 삽입될 값의 타입을 ObjectId 타입으로 변경하는 코드를 추가해서 문제를 해결했다.
await this.commentModel.create(
  { author: user._id, content: comments.content,
   info: mongoose.Types.ObjectId(id) });

즉, mongoDB를 이용하면서, 관계식별자로 ObjectId를 사용하는 경우, 각 관계식별자에 Type이 ObjectId 타입으로 잘 들어가 있는지 꼼꼼히 확인해야한다...!

profile
차가운에스프레소의 개발블로그입니다. (22.03. ~ 22.12.)

0개의 댓글