feat: search quiz done

This commit is contained in:
akhdanre 2025-05-01 19:59:09 +07:00
parent ad00d2b9de
commit 89deae92b3
5 changed files with 110 additions and 1 deletions

View File

@ -59,3 +59,12 @@ def get_user_quiz(
page = request.args.get("page", default=1, type=int)
page_size = request.args.get("page_size", default=10, type=int)
return controller.get_user_quiz(user_id=user_id, page=page, page_size=page_size)
@quiz_bp.route("/search", methods=["GET"])
@inject
def search_quiz(controller: QuizController = Provide[Container.quiz_controller]):
keyword = request.args.get("keyword", "")
page = int(request.args.get("page", 1))
limit = int(request.args.get("limit", 10))
return controller.search_quiz(keyword=keyword, page=page, limit=limit)

View File

@ -127,3 +127,10 @@ class QuizController:
)
except Exception as e:
return make_error_response(e)
def search_quiz(self, keyword: str, page: int, limit: int):
try:
result = self.quiz_service.search_quiz(keyword, page, limit)
return make_response(message="success", data=result)
except Exception as e:
return make_error_response(e)

View File

@ -10,7 +10,7 @@ class QuizEntity(BaseModel):
author_id: Optional[str] = None
title: str
description: Optional[str] = None
subject: str
# subject: str
is_public: bool = False
date: Optional[datetime] = None
total_quiz: Optional[int] = 0

View File

@ -21,6 +21,68 @@ class QuizRepository:
return QuizEntity(**data)
return None
# def search_by_title_or_category(
# self, keyword: str, page: int, page_size: int
# ) -> List[QuizEntity]:
# skip = (page - 1) * page_size
# pipeline = [
# {
# "$lookup": {
# "from": "category",
# "localField": "category_id",
# "foreignField": "_id",
# "as": "category_info",
# }
# },
# {"$unwind": "$category_info"},
# {
# "$match": {
# "$or": [
# {"title": {"$regex": keyword, "$options": "i"}},
# {"category_info.name": {"$regex": keyword, "$options": "i"}},
# ]
# }
# },
# {"$skip": skip},
# {"$limit": page_size},
# ]
# cursor = self.collection.aggregate(pipeline)
# return [QuizEntity(**doc) for doc in cursor]
def search_by_title_or_category(
self, keyword: str, page: int, page_size: int
) -> List[QuizEntity]:
skip = (page - 1) * page_size
cursor = (
self.collection.find(
{
"$and": [
{"is_public": True},
{
"$or": [
{"title": {"$regex": keyword, "$options": "i"}},
# {"category": {"$regex": keyword, "$options": "i"}},
]
},
]
}
)
.skip(skip)
.limit(page_size)
)
return [QuizEntity(**doc) for doc in cursor]
def count_by_search(self, keyword: str) -> int:
return self.collection.count_documents(
{
"$or": [
{"title": {"$regex": keyword, "$options": "i"}},
{"category": {"$regex": keyword, "$options": "i"}},
]
}
)
def get_by_ids(self, quiz_ids: List[str]) -> Optional[List[QuizEntity]]:
object_ids = [ObjectId(qid) for qid in quiz_ids]
cursor = self.collection.find({"_id": {"$in": object_ids}})

View File

@ -19,6 +19,37 @@ class QuizService:
raise DataNotFoundException("Quiz not found")
return map_quiz_entity_to_schema(data)
def search_quiz(
self, keyword: str, page: int = 1, page_size: int = 10
) -> tuple[list[RecomendationResponse], int]:
if not keyword:
raise ValidationException("Keyword cannot be empty.")
quizzes = self.quiz_repository.search_by_title_or_category(
keyword, page, page_size
)
total = self.quiz_repository.count_by_search(keyword)
print("quiz len", len(quizzes))
mapped_quizzes = []
for quiz in quizzes:
author = self.user_repostory.get_user_by_id(user_id=quiz.author_id)
if author is None:
print(quiz.author_id, "skipped")
continue # or handle default name
mapped_quizzes.append(
RecomendationResponse(
quiz_id=str(quiz.id),
author_id=str(author.id),
author_name=author.name,
title=quiz.title,
description=quiz.description,
date=quiz.date.strftime("%d-%B-%Y"),
)
)
return mapped_quizzes, total
def get_user_quiz(
self, user_id: str, page: int = 1, page_size: int = 10
) -> UserQuizListResponse: