상세 컨텐츠

본문 제목

mongoose로 relation 설정하기 (populate 이용하기)

데이터베이스/NoSQL

by moonionn 2020. 9. 26. 10:53

본문

mongodb는 관계형 데이터베이스들과 다르게

모델끼리의 관계를 직접 설정할 수 없습니다.

하지만 다른 documents들이 서로를 참조할 수 있게끔 설정할 수 있습니다.

mongodb와 node.js의 ODM인 몽구스를 활용해 해당 기능을 구현해보려 합니다.

 

 

1. 모델(혹은 Collection) 생성

우선 예시를 위해 상품 모델과 상품판매자 모델을 생성합니다.

 

👇상품 모델 (sellerId 쿼리 주목)

// 참고: 각자 documents들의 _id는 원래 자동으로 생성됩니다.

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const product = new Schema({
  _id: Schema.Types.ObjectId,
  
  name: {
    type: String,
    required: true
  },
  
  price: {
    type: Number,
    required: true
  },
  
  sellerId: {
    type: Schema.Types.ObjectId,
    ref: 'Seller',
    required: true
  }
});

module.exports = mongoose.model('Product', product);

 

👇상품 판매자 모델

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const seller = new Schema({
  _id: Schema.Types.ObjectId,
  
  name: {
    type: String,
    required: true
  },
  
  email: {
    type: String,
    required: true
  }
});

module.exports = mongoose.model('Seller', seller);

product 모델에 해당 상품 판매자 정보를 알 수 있게 sellerId를 넣었습니다.

그리고 ref라는 옵션에 참조할 모델(collection)명을 적습니다.

 

ref 옵션 없이 sellerId를 삽입한다면

해당 상품 판매자의 _id만 가져올 수 있게 됩니다.

ref 옵션이 있어야 _id + name + email 정보가 연동됩니다.

 

 

2. documents 생성

모델을 만들었으면 그 모델에 맞는 document들을 생성해줍시다.

아래처럼 입력하면 데이터가 디비에 저장됩니다.

const product = new Product({
  _id: new mongoose.Types.ObjectId(),
  name: '강아지 간식',
  price: 8000,
  sellerId: seller._id
});
const seller = new Seller({
  _id: new mongoose.Types.ObjectId(),
  name: '강형욱',
  email: 'doggy@test.com'
})

 

 

3. populate()로 node.js app에서 데이터 불러오기

이제 populate()를 이용하여 상품판매자 정보를 불러올 수 있습니다.

만약 populate()를 이용하지 않는다면 아래와 같은 결과를 얻습니다.

const express = require('express');
const app = express();
const Product = require('yourModelPath/product');

app.use((req, res, next) => {

  // 👇 product 데이터 전부 가져오기
  
  return Product
    .find()
    .then(productsArray => {
      console.log(productsArray);
      next();
    }
    .catch(err => console.log(err));
    
});
//console 결과

[
  {
    _id: 5f6e9788677062e69814c2a4,
    name: '강아지 간식',
    price: 8000,
    sellerId: 5f6e9788677062e69814c2a3,
    __v: 0
  }
]

 

 

하지만 populate()를 이용하면?

const express = require('express');
const app = express();
const Product = require('yourModelPath/product');

app.use((req, res, next) => {

  // 👇 product 데이터 전부 가져오기
  
  return Product
    .find()
    
    // 👇 각 product 데이터에 저장된 sellerId에 맞게 해당 seller 정보 연동
    .populate('sellerId')
    
    .then(productsArray => {
      console.log(productsArray);
      next();
    }
    .catch(err => console.log(err));
});
//console 결과

[
  {
    _id: 5f6e9788677062e69814c2a4,
    name: '강아지 간식',
    price: 8000,
    sellerId: {
      _id: 5f6e9788677062e69814c2a3,
      name: '강형욱',
      email: 'doggy@test.com',
      __v: 0
    },
    __v: 0
  }
]

 

 

4. 데이터 활용하기

이를 통해 seller의 정보를 활용해 봅시다.

find().populate()는 array를 출력하기 때문에 array 처리 작업이 필요합니다.

const express = require('express');
const app = express();
const Product = require('yourModelPath/product');

app.use((req, res, next) => {

  return Product
    .find()
    .populate('sellerId')
    
    .then(productsArray => {
    
      productsArray
        .forEach(p => {
          console.log(`${p.sellerId.name}이 선보이는 ${p.name}! ${p.sellerId.email}로 연락주세요`)
        })
        
      next();
    }
    
    .catch(err => console.log(err));
});
//console 결과

강형욱이 선보이는 강아지 간식! doggy@test.com로 연락주세요

관련글 더보기

댓글 영역