mongoDB 에러 해결 모음 (json serializable err, logger err, BSON byte err)
회사에서 수집 데이터를 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로 변경해서 넣어줌~