본문 바로가기

portfolio

FASTAPI와 mongoDB ODM을 활용한 CRUD , SEARCH 엔드포인트 구축

 
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

 
 

ㅈㄱㄴ를 검색하니 질문내용에 ㅈㄱㄴ라는 글이 있다. 그리고 질문속 답변 내용도 검색이 가능하다.