fastapi엔드포인트에 mongodb 비동기 ODM으로 사용할 beanie CRUD 구축

1. Question모델의 answers필드가 Answer의 모델을 참조하고 빈객체를 넣어 질문에 답변들을 달수 있게 구성하였다.
# 모델 정의
class Answer(Document):
id:str
content: str
class Question(Document):
id:str
title: str
description: str
answers: List[Answer] = []
1-1. pydantic의 BaseModel을 상속받아 데이터 유효성검사를 위해 모델의 스키마를 정의한다. 생성스키마, 업데이트 스키마를 따로 구분하였다. 여기서 스키마란 데이터의 구조와 명세를 의미한다.
# Pydantic을 이용한 질문, 모델 생성 스키마
class AnswerCreate(BaseModel):
id:str
content: str
class QuestionCreate(BaseModel):
id:str
title: str
description: str
# 질문, 답변 수정 스키마
class AnswerUpdate(BaseModel):
id:str = None
content: str = None
class QuestionUpdate(BaseModel):
id: str = None
title: str = None
description: str = None
2. 답변 추가 POST 엔드포인트- 질문 모델이 참조한 빈리스트가 담긴 필드에 객체를 추가하려면 append를 사용해서 새로운 객체를 추가한게 만들었다.
# 답변 추가
@app.post("/questions/{question_id}/answers/", response_model=AnswerCreate)
async def add_answer_to_question(question_id: str, answer: AnswerCreate):
question = await Question.get(document_id=question_id)
if not question:
raise HTTPException(status_code=404, detail="Question not found")
answer_obj = Answer(**answer.dict())
question.answers.append(answer_obj)
await question.save()
return answer_obj

3. 질문문서 answers필드에 답변모델을 참조되고 있으니 처음에 질문문서를 조회하고 질문 내의 답변 목록에서 수정하려는 답변을 찾는다 마지막으로 질문문서에 수정한 답변을 save시켜 업데이트에 반영한다.
# 답변 수정
@app.patch("/questions/{question_id}/answers/{answer_id}", response_model=Question)
async def update_answer(question_id: str, answer_id: str, answer_update: AnswerUpdate):
# 1.질문 문서 조회
question = await Question.get(document_id=question_id)
if not question:
raise HTTPException(status_code=404, detail="Question not found")
# 2.질문 내의 답변 목록에서 수정하려는 답변 찾기
updated = False
for answer in question.answers:
if answer.id == answer_id: # id 필드를 기반으로 답변 식별
if answer_update.content is not None:
answer.content = answer_update.content
updated = True
break
if not updated:
raise HTTPException(status_code=404, detail="Answer not found")
# 3.질문 문서 저장하여 답변 업데이트 반영
await question.save()
return question
4. 삭제한 길이를 비교해 완전 제거되었는지 확인한다.
# 답변이 실제로 제거되었는지 확인
if len(question.answers) == original_answer_count:
raise HTTPException(status_code=404, detail="Answer not found")
5. mongoDB atlas search기능을 이용해 검색 엔드포인트를 만들었다.
atlas search를 이용한 글 참조
https://devttaemppang.tistory.com/43
mongoDB search INDEX
인데스란 전체 데이터 조회할때 속도를 높이는 것을 말한다 인덱스 구조는 B-TREE로 되어있고 지금부터 node js를 사용해 실습을 해보겠다. const MongoClient = require("mongodb").MongoClient; const url = "mongodb+sr
devttaemppang.tistory.com
# 검색기능
from fastapi import FastAPI, HTTPException
from pymongo import MongoClient
client = MongoClient(DATABASE_URL)
db = client["Cluster0"]
@app.get("/search/")
async def search_questions_and_answers(search_query: str):
search_result = db.Question.aggregate([
{
"$search": {
"index": "hongsun2", # Atlas Search 인덱스 이름
"text": {
"query": search_query,
"path": ["_id","title", "description", "answers._id", "answers.content"] # 검색할 필드 지정
}
}
}
])
# search_result 객체를 리스트로 변환
search_results = list(search_result)
# 결과반환
return search_results

'portfolio' 카테고리의 다른 글
FASTAPI OAUTH2.0 인증, 인코딩 디코딩을 통한 JWT 생성과 검증, 리프레시 토큰 생성 (0) | 2024.03.25 |
---|---|
FASTAPI 정적 토큰헤더를 통한 인증 (0) | 2024.03.15 |
리액트 노드 socket.io를 활용한 실시간 영화예매시스템 구축 (0) | 2024.03.07 |
장고(DRF) + 리액트 REACT.JS 포트폴리오 2 (0) | 2024.02.27 |
장고(DRF) + 리액트 REACT.JS 포트폴리오 1 (0) | 2024.02.27 |