몽고DB 저장 전 데이터 업데이트

MOON HEE·2023년 3월 2일
0

카카오맵에서 식당정보를 스크래핑해서 몽고DB 컬렉션에 저장하는데 성공했다👀
나중에 상호명이나 평점이 바뀔 수 있기 때문에 주소에 unique를 주고 주소가 중복돼서 에러가 나면 그때 최신 데이터로 업데이트하도록 하면 됐다(덮어쓰기).

1. 최초에 크롤링 데이터를 수집해서 db에 저장
   └ 크롤링 하면서 주소가 중복되면 에러(E11000) 발생하고 저장이 안됨
2. 이후 크롤링에서 데이터를 저장할 때 고려사항
   └ 주소가 중복되면 새롭게 크롤링한 내용 덮어쓰기

Restaurant 모델

address를 고유하게 설정해서 동일한 식당인지 구별할 수 있도록 했다. certicied는 인증된 채식식당인지 여부이고, certicifation은 인증되었다면 그 인증정보를 담도록 했다.

import mongoose, { Schema } from 'mongoose';

const restaurantSchema = new Schema({
    title: {
        type: String,
    },
    category: {
        type: String,
    },
    rating: {
        type: String,
    },
    address: {
        type: String,
        unique: 1,
    },
    certified: {
        type: Boolean,
        default: false,
    },
    certification: {
        type: String,
    },
});

const Restaurant = mongoose.model('Restaurant', restaurantSchema);

export default Restaurant;

scrapper.ts에서 saveScrapped 함수

// puppeteer에서 saveScrapped로 데이터 전달
if (typeof category === 'string') {
  if (!excludeCategory.includes(category)) { // 제외하고 싶은 키워드 필터링
    saveScrapped({
      title: ...,
      category: ...,
      rating: ...,
      address: ...,
      certified: false,
      certification: null,
    });
  }
                        }
// saveScrapped.ts
import type { scrappedData } from '../scrapper';
import fetch from 'node-fetch';

export async function saveScrapped(item: scrappedData) {
    try {
        const res = await fetch(`http://localhost:3000/api/scrappers/save`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify(item),
        });

        const data: any = await res.json();

        if (data.saveSuccess) {
            console.log('저장완료--');
        } else {
            console.log('❌❌❌', data.errorMessage);
        }
    } catch (err) {
        console.error(err);
    }
}

findOneAndUpdate

  • 주어진 필터와 일치하는 첫 번째 문서를 찾아 업데이트를 적용하고 문서를 반환한다.
  • save()를 사용하여 문서를 업데이트하는 경우, findOne()을 사용하여 문서를 로드할 때와 save()를 사용하여 문서를 저장할 때 사이에 MongoDB에서 문서가 변경될 수 있다. 이 문제를 findOneAndUpdate가 해결할 수 있다고 설명되어 있다(mongoose docs에서 예제확인).
app.post('/api/scrappers/save', (req, res) => {
  const restaurant = new Restaurant(req.body);

  restaurant.save(async (err, restaurantInfo) => {
    if (err) { // 주소가 같으면 err가 발생
      if (err.message.includes('E11000')) { // 중복 에러면
        const filter = { address: req.body.address };
        const update = { ...req.body };
		// filter에 해당하는 문서를 update 변수에 담긴 내용으로 변경하기
        await Restaurant.findOneAndUpdate(filter, update);
      }
    }
    return res.status(200).json({ saveSuccess: true });
  });
});

변경 전 데이터

변경 후 데이터

postman으로 요청한 후 몽고DB의 Restaurants 컬렉션에서 잘 업데이트 된 것을 확인할 수 있다. 주소를 그대로 유지하고 나머지 값을 변경하면 잘 바뀐다.

profile
자고 일어나면 해결되는게 더 많은 듯 그럼 잘까

0개의 댓글