TIL

jathazp·2022년 2월 19일
0

populate

하나의 다큐먼트가 다른 다큐먼트의 ObjectId를 쓰는 경우가 있다. 그럴 때 그 ObjectId를 실제 객체로 치환하는 작업이 필요하다. 그 때 유용한게 mongoose의 populate기능이다.
아래 예시를 보자

1. 먼저 populate를 적용하기 위해서는 해당 ObjectId가 속해있는 모델을 넣어준다. 현재는 자기 자신(User)을 가리키지만 다른 컬렉션에도 적용이 가능하다.

//userSchema
const userSchema = new mongoose.Schema({
  name: String,
  friends: [{ 
    type: mongoose.Schema.Types.ObjectId, 
    ref: 'User' 
  }],
  bestFriend: { 
    type: mongoose.Schema.Types.ObjectId, 
    ref: 'User' 
  }],
});
mongoose.model('User', userSchema);

이제 findOne을 통해 객체를 불러왔다고 하자

//db.users.findOne({ name: 'zero' }) 를 통해 불러온 객체
{
  _id: { $oid: '574e9c0f9f663a1700fbe06e' },
  name: 'zero',
  friends: [{ $oid: '59a66f8372262500184b5363' }, { $oid: '574e8f46c9100617001c9cb9' }],
  bestFriend: { $oid: '574e8f46c9100617001c9cb9' }
}

그럼 아래와 같은 코드를 통해 populate를 적용할 수 있다.
User.findOne({ name: 'zero' }).populate('bestFriend').exec((err, data) => {
  console.log(data);
}); // 또는 populate({ path: 'bestFriend' })도 가능

그럼 data의 구조는 아래와 같다.

{
  _id: { $oid: '574e9c0f9f663a1700fbe06e' },
  name: 'zero',
  friends: [{ $oid: '59a66f8372262500184b5363' }, { $oid: '574e8f46c9100617001c9cb9' }],
  bestFriend: { 
    _id: { $oid: '574e8f46c9100617001c9cb9' },
    name: 'hero',
    friends: [{ $oid: '59a66f8372262500184b5363' }, { $oid: '574e9c0f9f663a1700fbe06e' }],
    bestFriend: { $oid: '59a66f8372262500184b5363' }
  }
}

bestFriend에 ObjectId가 해당하는 객체로 치환된 모습을 볼 수 있다.
populate할 때 bestFriend의 name과 bestFriend만 보고 싶다면 두 번째 인자로 넣어주면 된다.

User.findOne({ name: 'zero' }).populate('bestFriend', 'name bestFriend').exec((err, data) => {
  console.log(data);
});

한번에 여러 objectId를 치환하기 위해 populate를 연달아 사용할 수도 있다.

User.findOne({ name: 'zero' }).populate('bestFriend').populate('friends').exec((err, data) => {
  console.log(data);
});

하지만 populate는 $oid로 모두 조회를 해서 자바스크립트 단에서 합쳐주는 것이지 JOIN처럼 DB 자체에서 합쳐주는 것이 아니기 때문에 남용하면 성능 문제가 생길 확률이 크다.

virtual

0개의 댓글