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

데이터 검색 화면 만들기(mongoDB)

by 즐거운코딩 2023. 10. 20.
반응형

MongoDB 데이터베이스를 이용하고 Node.js-express 이용하여 데이터를 조회하는 화면을 만들어 보겠습니다.

예시 화면은 관광지명을 검색하여 조회하는 화면입니다.

 

1.   MongoDB 여행지 정보 데이터 구성

관광지 정보는 공공데이터포탈의 전국관광지정보표준데이터를 활용하였습니다.

https://www.data.go.kr/data/15021141/standard.do

MongoDB에 tourinfo Schema를 아래와 같이 만듭니다.

 

models>campgroud.js

- 기본적인 관광지 정보외 경위도 위치, 이미지 데이터 정보도 같이 관리하는데 이번은 검색 기능에 대한 설명으로 제한하고자 합니다.

- 검색은 관광지명칭(trrsrNm) 기준으로 검색하겠습니다.

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],
    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, // 관리기관코드
    author: {
      type: Schema.Types.ObjectId,
      ref: "User",
    },
    reviews: [
      {
        type: Schema.Types.ObjectId,
        ref: "Review",
      },
    ],
  },
  opts
);

 

2. 검색기능 화면 만들기

- 화면 상단 메뉴(Navbar)에 검색창을 만듭니다.

- 기본적인 UI는 Bootstrap의 serch form 을 활용합니다.

        <div>
          <form
            class="d-flex"
            role="search"
            action="/campgrounds/search"
            method="GET"
            novalidate
            class="validated-form"
            enctype="multipart/form-data"
          >
            <input
              class="form-control me-2"
              type="search"
              placeholder="Search"
              aria-label="Search"
              name="site"
            />
            <button class="btn btn-outline-success" type="submit">
              Search
            </button>
          </form>
        </div>

3. mongoDB에서 데이터 검색기능

데이터베이스에서 필요한 데이터 검색방법은 아래와 같이 다양합니다.

검색결과 전체 가져오기, 하나만 가져오기, 유사검색에 대한 내용은 다음과 같습니다.

  • Model.find() : 검색조건에 맞는 전체 데이터 조회
  • Model.findOne() : 검색조건에 맞는 1개 데이터만 조회
  • Model.findById() : Id 기준 조회

(예시)

// 모든 데이터 조회
await MyModel.find({});

// find all documents named john and at least 18
await MyModel.find({ name: 'john', age: { $gte: 18 } }).exec();

// executes, name LIKE john and only selecting the "name" and "friends" fields
await MyModel.find({ name: /john/i }, 'name friends').exec();

// passing options
await MyModel.find({ name: /john/i }, null, { skip: 10 }).exec();
// Find one adventure whose `country` is 'Croatia', otherwise `null`
await Adventure.findOne({ country: 'Croatia' }).exec();

// Model.findOne() no longer accepts a callback

// Select only the adventures name and length
await Adventure.findOne({ country: 'Croatia' }, 'name length').exec();
// Find the adventure with the given `id`, or `null` if not found
await Adventure.findById(id).exec();

// select only the adventures name and length
await Adventure.findById(id, 'name length').exec();

관광지명의 like 검색은 아래와 같이 사용할 수 있습니다.

검색기능을 별도 모듈로 만들었습니다.

 

쿼리명에서 검색할 관광지명을 추출하여, Tourinfo 테이블에서 trrsrtNm(관광지명) 필드에서 $regrex 를 이용하여 검색합니다.

검색결과가 있으면 campgrounds/find 페이지에 표출하도록 합니다.

module.exports.searchCampground = async (req, res) => {
  const site = req.query.site;
  console.log("검색명칭", site);
  const campgrounds = await Tourinfo.find({ trrsrtNm: { $regex: site } });
  console.log(campgrounds);
  if (campgrounds.length > 0) {
    res.render("campgrounds/find", {
      campgrounds,
      cities,
    });
  } else {
    res.redirect("/campgrounds/?page=1");
  }
};

4. 검색결과 조회하면 만들기

데이터베이스에서 검색한 결과값을 rendering할 화면으로 넘겨줍니다.

(예시: 결과값을 campgrounds 배열 객체로 저장)

 

관광지명칭에 "마을" 이름이 들어 간 데이터가 총45건  조회되었고 아래와 같이 지도 위치와 목록이 표출됩니다.

<% if (campgrounds.length) { %> <% for (let campground of campgrounds) { %>
<div class="card mb-3">
  <div class="row">
    <div class="col-md-4">
      <% if(campground.images.length) { %>
      <img
        crossorigin="anonymous"
        class="img-fluid"
        src="<%= campground.images[0].url %>"
        alt=""
      />
      <% } else { %>
      <img
        class="img-fluid"
        src="https://res.cloudinary.com/dc2gmdv7u/image/upload/v1695652195/PeterCamp/xvn0ax7patuy8o74oy5d.jpg"
        alt=""
      />
      <% } %>
    </div>
    <div class="col-md-8">
      <div class="card-body">
        <h5 class="card-title"><%= campground.trrsrtNm %></h5>
        <p class="card-text"><%= (campground.trrsrtIntrcn.length > 200) ?
          campground.trrsrtIntrcn.slice(0,200)+" ..." : campground.trrsrtIntrcn
          %></p>
        <p class="card-text">
          <small class="text-muted"><%= campground.addr %></small>
        </p>
        <a class="btn btn-primary" href="/campgrounds/<%= campground._id %>"
          >세부정보</a
        >
      </div>
    </div>
  </div>
</div>
<% } %> <% } else { %>
<div>검색된 결과가 없으니 다시 조회해주세요!</div>
<% } %>

 

반응형