본문 바로가기
자바스크립트(Javascript)

MongoDB에 데이터 일괄 업로드 하기(2)

by 즐거운코딩 2023. 12. 22.
반응형

JSON 파일을 기반으로 MongoDB에 일괄 업로드 하는 방법에 대해 예시를 들어 설명하겠습니다.

MongoDB 데이터베이스에 데이터를 입력하기 위해서는 다음과 같은 과정이 필요합니다.

단계별 과정을 구체적으로 보여드리겠습니다.

 

📌 설명하는 데이터 샘플은 이전 포스트의 내용을 참조

2023.12.21 - [자바스크립트(Javascript)] - MongoDB에 데이터 일괄 업로드 하기(1)

 

MongoDB에 데이터 일괄 업로드 하기(1)

서비스 개발을 하기 위해 필요한 더미(Dummy) 데이터를 만들 필요가 있거나, 서비스용 데이터를 별도 입력 웹페이지를 만들어서 한 건씩 입력하는 것이 어렵기 때문에 초기 데이터 일괄 업로드 하

peter-codinglife.tistory.com

 

1.  MongoDB Schema 만들기

데이터를 입력할 데이터베이스 테이블을 구성해야 합니다.

다음과 같이 Mongo Schema를 생성하여 저장할 데이터 항목별 필드(Field)명과 데이터 타입(Type)을 정의해줍니다.

 

데이터 모델의 Shema 만들기

const mongoose = require("mongoose");
const Review = require("./review");
const Schema = mongoose.Schema;

const ImageSchema = new Schema({
  url: String,
  filename: String,
});

ImageSchema.virtual("thumbnail").get(function () {
  return this.url.replace("/upload", "/upload/w_200");
});

const opts = { toJSON: { virtuals: true } };

const TourinfoSchema = new Schema(
  {
    trrsrtNm: String, // 관광지명
    trrsrtSe: {
      type: String,
      enum: ["관광지", "관광단지", "축제행사", "음식점", "숙박"],
    }, // 관광지구분
    images: [ImageSchema], // 사용자 등록 이미지
    imageURL: String, // 외부 이미지 사용 (23/12/4)
    homepageURL: String, // 업소 소개 웹페이지 (23/12/4)
    geocoord: String,
    geometry: {
      type: {
        type: String, // Don't do `{ location: { type: String } }`
        enum: ["Point"], // 'location.type' must be 'Point'
        // required: true,
      },
      coordinates: {
        type: [Number],
        // required: true,
      },
    },
    city: String, // 시도
    addr: String, // 소재지주소
    ar: Number, // 면적
    cnvnncFclty: String, // 공공편익시설정보
    stayngInfo: String, // 숙박시설정보
    mvmAmsmtFclty: String, // 운동및오락시설정보
    recrtClturFclty: String, // 휴양및문화시설정보
    hospitalityFclty: String, // 접객시설정보
    sportFclty: String, // 지원시설정보
    appnDate: Date, // 지정일자
    aceptncCo: Number, // 수용인원
    prkplceCo: Number, // 주차가능수
    trrsrtIntrcn: String, // 관광지소개
    phoneNumber: String, // 관리기관전화번호
    institutionNm: String, // 관리기관명
    referenceDate: String, // 데이터기준일자
    instt_code: String, // 관리기관코드
    itemSource: String, // 정보원천 (23/12/4)
    author: {
      type: Schema.Types.ObjectId,
      ref: "User",
    },
    reviews: [
      {
        type: Schema.Types.ObjectId,
        ref: "Review",
      },
    ],
  },
  opts
);

module.exports = mongoose.model("Tourinfo", TourinfoSchema);
  • 여행정보 서비스의 세부데이터 등록으로 TourinfoSchema 로 지정합니다.
  • 여행지별 상세 정보 구성은 다음과 같습니다.
    • 관광지명 및 관광 카테고리
    • 관광지 이미지 : 사용자 등록 이미지와 외부 이미지 URL 등록
    • 홈페이지 주소, GPS 좌표, 소개자료 등 세부정보 
    • 관광지 리뷰 및 리뷰작성자 
  • 공공데이터포탈에서 가져오는 정보는 관광지명과 그 세부 데이터들로 포탈에서 사용한 필드명을 그대로 사용하였습니다.

2.  등록할 JSON 파일 만들기

JSON 포맷 데이터를 불러 오기 위해 아래와 같이 데이터를 export 해줍니다.

 

파일명 sights.js 로 지정 

module.exports = [
  {
    관광지명: "무각사",
    관광지구분: "관광지",
    소재지도로명주소: "광주광역시 서구 운천로 230",
    소재지지번주소: "",
    위도: "35.15378107",
    경도: "126.8560181",
    면적: "510",
    공공편익시설정보: "화장실+주차장",
    숙박시설정보: "",
    운동및오락시설정보: "",
    휴양및문화시설정보: "",
    접객시설정보: "",
    지원시설정보: "",
    지정일자: "2007-07-27",
    수용인원수: "100",
    주차가능수: "30",
    관광지소개:
      "일주문, 사천왕문, 대웅전, 종각 등 전통사찰의 형태를 여법하게 갖추며 일주문에서 사천왕, 대웅전으로 이어지는 가람 형태는 도심 한복판에 자리해 있으면서도 깊은 산사에 들어선 듯 경건함",
    관리기관전화번호: "062-383-0108",
    관리기관명: "광주광역시 서구청",
    데이터기준일자: "2022-01-01",
    제공기관코드: "6290000",
    제공기관명: "광주광역시",
  },
  ...
  • 데이터를 배열(array) 타입으로 바꾸고,
  • module.exports 합니다.

3.  MongoDB에 입력하기

입력할 데이터 (sights.js) 를 불러와서 MongoDB에 입력하기 위해 다음과 같이 코드를 작성합니다.

 

파일명  seeds/index.js 로 작성

const mongoose = require("mongoose");
const sights = require("./sights");
const Tourinfo = require("../models/campground");

mongoose.connect("mongodb://127.0.0.1:27017/tourinfo", {
  useNewUrlParser: true,
  useUnifiedTopology: true,
});

const db = mongoose.connection;
db.on("error", console.error.bind(console, "connection error:"));
db.once("open", () => {
  console.log("Database connected");
});

// const sample = (array) => array[Math.floor(Math.random() * array.length)];

const seedDb = async () => {
  await Tourinfo.deleteMany({});
  for (let i = 0; i < 962; i++) {
    const tour = new Tourinfo({
      // your user id
      author: "656dd9f88177595b554387f3",
      trrsrtNm: sights[i].관광지명,
      trrsrtSe: sights[i].관광지구분,
      trrsrtIntrcn: sights[i].관광지소개,
      // 삼항연산으로 도로명주소 없는 경우만 지번주소 사용
      addr: sights[i].소재지도로명주소
        ? sights[i].소재지도로명주소
        : sights[i].소재지지번주소,
      city: sights[i].소재지도로명주소
        ? sights[i].소재지도로명주소.split(" ")[0]
        : sights[i].소재지지번주소.split(" ")[0],
      institutionNm: sights[i].관리기관명,
      referenceDate: sights[i].데이터기준일자,
      geometry: {
        type: "Point",
        coordinates: [sights[i].경도, sights[i].위도],
      },
      images: [
        {
          url: "https://res.cloudinary.com/dc2gmdv7u/image/upload/v1702194458/PeterCamp/tourinfologo_f9mf2a.png",
          filename: "tourinfologo_f9mf2a",
        },
      ],
      itemSource: "전국관광지정보표준데이터",
    });
    await tour.save();
  }
};

seedDb().then(() => {
  mongoose.connection.close();
});
  • moonge 로 DB에 connection 합니다. (tourinfo : 데이터베이스 이름 )
  • seedDb 로 sights 데이터를 가져와 데이터베이스에 저장
    • 신규 입력이므로 혹시 기존에 입력한 전체 여행정보 데이터를 삭제 Tourinfo.deleteMany({})
    • 총 데이터 건수인 962개 데이터를 입력하기 위해 for 문 사용 하고
    • 작성자는 User 테이블에 저장된 userid에 해당되는 ObjectID를 지정 (User 관련 기능은 다른 포스트에서 안내)
    • sights 데이터는 배열이므로 각 데이터를 순서대로 불러오고 사용하고자 하는 데이터만 Schema에 정의한 필드명에 매칭
    • addr 같이 주소 데이터의 경우 원천데이터에서 도로명주소, 지번주소  두 종류의 데이터가 있는데 도로명 주소를 우선 보여주도록 함 (삼항연산 사용)
    • geometry 경우 경위도 데이터를 Point type에 맞게 입력
    • Image의 경우 모든 데이터에 동일한 샘플이미지를 등록하도록 함
    • 개별 데이터 저장을 하기 위해  tour.save() 실행
    • 데이터 입력이 끝나면 connection 을 종료 mongoose.connection.close()

4.  데이터 일괄 업로드 실행하기

 

터미널에서 $node ./seeds/index.js 실행

데이터 정상 저장되었는지는 MongoDB Compass 에서 확인해 봅니다.

MongoDB Compass 화면

 

  • 추가로 이미지 데이터를 등록하면 아래와 같이 mogoDB에서 image데이터를 확인할 수 있습니다

  • 입력한 정보로 다음과 같이 관광지 상세 화면을 구성하였습니다.

반응형