$lookup으로 MongoDB join하기

dev-well-being·2023년 1월 3일
1
post-thumbnail

MongoDB와 같은 DocumentDB에서는 당연히 Join 기능이 활용이 안될 줄 알았는데;

우연히 검색을 하던 차에 아래 블로그를 발견하였다.

[MongoDB] 몽고DB에서 Join을 해보자 - $lookup으로 Join하기 ...

일단 Join을 할 두 임시 테이블을 생성하였다.

db.team.find()

{ _id: ObjectId("63b3d479d0c3cab0ab33f361"), name: 'service platform' }
{ _id: ObjectId("63b3d479d0c3cab0ab33f362"), name: 'sw lab' }
{ _id: ObjectId("63b3d479d0c3cab0ab33f363"), name: 'ds' }
{ _id: ObjectId("63b3d479d0c3cab0ab33f364"), name: 'se' }

db.employee.find()

{ _id: ObjectId("63b3d65ed0c3cab0ab33f365"), name: '홍길동', team_id: ObjectId("63b3d479d0c3cab0ab33f361") }
{ _id: ObjectId("63b3d65ed0c3cab0ab33f366"), name: '임꺽정', team_id: ObjectId("63b3d479d0c3cab0ab33f361") }
{ _id: ObjectId("63b3d65ed0c3cab0ab33f367"), name: '한석봉', team_id: ObjectId("63b3d479d0c3cab0ab33f362") }
{ _id: ObjectId("63b3d65ed0c3cab0ab33f368"), name: '심청이', team_id: ObjectId("63b3d479d0c3cab0ab33f363") }
{ _id: ObjectId("63b3d65ed0c3cab0ab33f369"), name: '콩쥐', team_id: ObjectId("63b3d479d0c3cab0ab33f364") }

그리고 아래 aggregate 명령어를 실행하였다

db.employee.aggregate([
  {
      $lookup: {
        from: "team"
        , localField: "team_id"
        , foreignField: "_id"
        , as: "team_info"
      }
  }
  ])

aggregate : grouping, filter 등 find 만으로 데이터를 가공하기 어려울 때 주로 사용한다고 한다.

  • from : join 할 collection
  • localField : join할 key
  • foreignField : join 할 collection의 key
  • as: join으로 새로 생설될 field의 alias

실행결과

{ _id: ObjectId("63b3d65ed0c3cab0ab33f365")
, name: '홍길동'
, team_id: ObjectId("63b3d479d0c3cab0ab33f361")
, team_info: [ { _id: ObjectId("63b3d479d0c3cab0ab33f361"), name: 'service platform' } ] }
{ _id: ObjectId("63b3d65ed0c3cab0ab33f366"),
  name: '임꺽정',
  team_id: ObjectId("63b3d479d0c3cab0ab33f361"),
  team_info: [ { _id: ObjectId("63b3d479d0c3cab0ab33f361"), name: 'service platform' } ] }
{ _id: ObjectId("63b3d65ed0c3cab0ab33f367"),
  name: '한석봉',
  team_id: ObjectId("63b3d479d0c3cab0ab33f362"),
  team_info: [ { _id: ObjectId("63b3d479d0c3cab0ab33f362"), name: 'sw lab' } ] }
{ _id: ObjectId("63b3d65ed0c3cab0ab33f368"),
  name: '심청이',
  team_id: ObjectId("63b3d479d0c3cab0ab33f363"),
  team_info: [ { _id: ObjectId("63b3d479d0c3cab0ab33f363"), name: 'ds' } ] }
{ _id: ObjectId("63b3d65ed0c3cab0ab33f369"),
  name: '콩쥐',
  team_id: ObjectId("63b3d479d0c3cab0ab33f364"),
  team_info: [ { _id: ObjectId("63b3d479d0c3cab0ab33f364"), name: 'se' } ] }

실행 결과를 보면 team_info라는 field 안에 team_id와 매칭되는 team data가 조회된다.


보통 RDB에서도 join시 필요한 field만 지정하여 조회한다. MongoDB에서도 해당 기능을 제공한다.
db.employee.aggregate([
  {
      $lookup: {
        from: "team"
        , localField: "team_id"
        , foreignField: "_id"
        , as: "team_info"
      }
  }
  , {	$unwind: "$team_info"}
  , {
    	$project: {
      		name: 1,
      		team_name: "$team_info.name"
    	}
  }
])

$unwind : 배열형태로 된 필드는 하나하나 분리해주는 기능. 새롭게 생성된 team_info가 배열 형태로 감싸져 있어, 데이터에 접근시 불필요하게 $team_info[0].원하는 필드 형태로 접근해야 하는 걸 방지해 준다.

$project : 필요한 값만 지정할 때 사용한다. 원래 있던 필드는 1을 지정해 가지고 오고 $team_info 있는 필드는 $team_info.name로 지정할 수 있다.

{ _id: ObjectId("63b3d65ed0c3cab0ab33f365"), name: '홍길동', team_name: 'service platform' }
{ _id: ObjectId("63b3d65ed0c3cab0ab33f366"), name: '임꺽정', team_name: 'service platform' }
{ _id: ObjectId("63b3d65ed0c3cab0ab33f367"), name: '한석봉', team_name: 'sw lab' }
{ _id: ObjectId("63b3d65ed0c3cab0ab33f368"), name: '심청이', team_name: 'ds' }
{ _id: ObjectId("63b3d65ed0c3cab0ab33f369"), name: '콩쥐', team_name: 'se' }
profile
안녕하세요!! 좋은 개발 문화를 위해 노력하는 dev-well-being 입니다.

0개의 댓글