DevOps/Database

mongoDB 에러 해결 모음 (json serializable err, logger err, BSON byte err)

soohey 2022. 11. 2. 20:06

회사에서 수집 데이터를 mongoDB에 넣는 작업을 하면서 생긴 에러들 모음집...

기록용이라 진짜 간결하게 해결만 씁니다.

 

1. json 변환 err

TypeError: Object of type Tag is not JSON serializable
ERROR:uvicorn.error:Exception in ASGI application

파이썬 기반 웹 api 작성시 자주 생기는 에러다.

파이썬은 json 모듈을 사용해서 list -> dictionary로 바꾸는 방식을 주로 사용하는데,

이때 list에 올바르지 않은 데이터값이 들어가서 json 변환중에 에러가 생겼다.

 

나는 default를 string으로 걸어서 아예 안생기는 방향으로 바꿔버렸다.

찾아보니 json 모듈이 인식하지 못하는 타입(ex : 날짜)이 종종 있으니 확인 후에 default로 박아버리는걸 추천한다.

(다른 방법있으면 알려주세용)

https://dgkim5360.tistory.com/entry/not-JSON-serializable-error-on-python-json

import json

result = json.dumps(data, default=str)

 

2. logger err

ERROR - error() missing 1 required positional argument: 'msg'

다시보니 진짜 희한한 에러 ㅋㅋ..

try-exeption 걸고 logger.error(e)로 에러 확인하려는데 떴던 에러다

error() 함수는

def error(self, msg, *args, **kwargs):

위처럼 msg를 받는데 그걸 못받아서 나는 에러다.. 왜 못 받았냐면 아래 코드를 추가 안해줌

import logging

logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)

 

3. mongoDB BSON err

BSON document too large (23608013 bytes) - the connected server supports BSON document sizes up to 16793598 bytes.

한 도큐먼트에 너무 큰 크기의 json이 할당됐을 때 생기는 에러다.

BSON은 Binary JSON이라는 의미이며 JSON과 구조가 동일한데 binary 형태로 변경된 구조다.

 

실제로 사람이 볼 일이 없는 형태다.

내부적으로 mongoDB에 동적으로 저장할 때 쓰는 형태일 뿐, 사용자에게는 우리가 익숙한 JSON 형태로 보인다.

이러한 BSON 데이터 관리는 MongoDB Atlas에서 확인 가능하다.

 

궁금해서 찾아본 몽고 DB가 JSON 대신 BSON을 사용하는 이유

  • 텍스트 기반의 JSON은 구문 분석이 매우 느리다.
  • JSON은 공간 효율성과 거리가 멀다.

 

암튼 BSON 크기 제한이래서 찾아봤더니 지금 애초에 제공하는 크기가 16MB라 개발자가 변경할 수 있는 부분은 없다고 함

그래서 생각한 방법 2가지

1. 파일로 저장

2. 하위 도큐먼트로 쪼개서 저장

 

파일로 저장하는 방법은 MongoDB에서 제공하는 GridFS(https://www.mongodb.com/docs/manual/core/gridfs/)를 사용할까하다가 문서 읽어보니 첫줄에 multi-document transactions.

를 지원 안한다고 써져있더라

크롤링 데이터는 주로 분석에 사용되기 때문에 지원안되면 말짱 꽝이다.

 

포기하고 두번째 방법 선택함..

pymongo 모듈의 insert_many 사용하기

document_list = []
date = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

for res in result:
    document_data = JsonContent(
        parms=[],
        date=date,
        content=json.dumps(res, default=str)
    )
    document_list.append(document_data.dict())
                
collection = get_db_collection(collection_name=collection_name)
inserted_obj = collection.insert_many(hash_obj)

result는 넣을 데이터인데 넣을 collection의 document형태로 바꿔줘야해서

document_list로 변경해서 넣어줌~