2021.12.2 TIL

권윤경·2021년 12월 5일
0

TIL

목록 보기
3/15
post-thumbnail

Mongoose의 populate

mongoose는 NoSQL(Not Only Structured Query)의 대표적인 DB(Data Base)이다.
즉, 비관계형 데이터베이스의 대표적인 DB이다.

그러나 mongoDB를 사용하다보면 컬렉션의 특정 데이터를 기반으로 다른 컬렉션의 데이터를 참조하는 상황이 발생한다. 이때 등장한게 populate()이다.

populate은 SQL의 join과 같은 기능 을 한다.

쇼핑몰에 사용되는 DB를 생각해보자,
하나의 테이블에는 고객ID와 고객주소지가 있고, 다른 테이블에는 고객들이 현재까지 주문한 상품정보와 해당 상품을 주문한 고객ID가 저장되어 있다.

배송을 위해서는 고객들이 주문한 상품 정보와, 고객의 주소지를 알아야 한다. 이때 두 컬렉션을 활용하여 데이터를 얻어야하는데, 처음부터 컬렉션 하나만 생성하여 데이터를 모두 넣거나, 두 컬렉션에 동일한 주소지 데이터를 추가하면 되지 않을까 하는 생각이 들 수 있다. 그러나 앞서 말한 방법으로 진행하게되면 컬렉션의 컬럼이 너무 많아져 보기에도 좋지 않고, 속도에도 영향을 미치게 된다. 또한 두 테이블 모두에 주소지 데이터를 넣어버린다면 현재의 문제는 해결 되겠지만, 추후에도 계속해서 다른 필드 참조를 위해 칼럼을 추가하고 데이터를 추가하는 일을 반복하다 보면, 비슷한 문제가 계속 발생할것이다. 컬럼 추가로 인해 중복된 데이터가 테이블에 있다면 데이터 업데이트를 하는데에도 상당한 불편함을 감수해야 할 것이다.

이럴때 사용하는 연산이 Join연산이며, mongoDB에서는 populate()을 사용한다. Join 연산은 하나 이상의 칼럼이 공유(현재 상황에서는 고객ID)되어 있을 때, 다른 테이블의 데이터 검색을 할 수 있게 되어 하나의 테이블처럼 검색을 할 수 있게 해주는 쿼리 문법이다.

populate 사용

User 스키마

import mongoose from "mongoose";

const UserSchema = new mongoose.Schema({
 	userId: { type: String, required: true},
  	userAddress: { type: String, required: true},
});

const User = mongoose.model("User", UserSchema);

export default User;

OderInfo 스키마

import mongoose from "mongoose";

const OrderInfoSchema = new mongoose.Schema({
 	userId: { type: String, required: true},
  	productInfo: { type: String, required: true},
    userAdress:{
    	type: mongoose.Schema.Types.ObjectId,
        required: true,
        ref:"User",
    },
});

const OrderInfo = mongoose.model("OrderInfo", OrderInfoSchema);

export default OrderInfo;

위과 같이 Join을 원하는 컬렉션의 type에 mongoose.Schema.Types.ObjectId 정의해주고 ref에 Join하려는 컬렉션의 이름을 작성하여 스키마를 생성해주면 Join을 위한 준비는 완료된다.

join된 컬렉션의 데이터 조회를 위해서는 populate()을 활용하여 작성한다.
OrderInfo에 find로 쿼리를 날린 다음에, User컬렉션 필드의 자세한 정보를 알기 위해서 아래와 같이 작성하면 데이터를 얻을 수 있다. 데이터 확인을 위해서는 변수에 해당 코드를 담아 콘솔로 찍어보면 확인해 볼 수 있다.

OrderInfo.findOne({ _id: userId }).populate("User"); 

0개의 댓글