TIL_231108_검색 기능 적용

Sol Lee·2023년 11월 8일
0

검색기능

원래 기획단계에서는 recipe라는 모델에 ingredients라는 필드가 list로 들어갈 예정이었는데 여러가지 이슈🫠로 인해 ingredients라는 모델을 새로 생성하고 fk로 연결하는 것으로 변경.

검색 방식의 차이

검색하는 키워드를 모두 포함하는 레시피를 찾아야 함

키워드가 A,B,C 로 들어오면
레시피라는 덩어리에서 필터링 A -> & 필터링 B -> & 필터링 C 이렇게 좁혀가는 방식을 생각했는데,

현재는 재료뭉텅이에서 필터A를 포함하는 레시피들, 필터B를 포함하는 레시피들, 필터C를 포함하는 레시피들을 찾고 여기에 중복되는 값들을 찾아야 할 듯?

구현 방법

# views.py

class RecipeSearchView(APIView):
    def get(self, request):
        """ 검색된 재료 포함하는 레시피 구한 후 object 반환 """
        quart_string = request.GET['q'] # 파라미터값 추출
        ingredients = quart_string.split(",") # 파라미터 값에서 ,로 분리 -> 재료 목록
        recipe_ids = []
        compare_ids = []
        for i in range(len(ingredients)):
            ingredients_list = ArticleRecipeIngredients.objects.filter(
                ingredients__contains=ingredients[i].strip()) 
                # 재료 스키마의 ingredients필드에 ingredients[i]가 포함된 데이터 필터링
                # 공백이 포함되면 검색이 잘 안되서 앞뒤 공백제거도 해줌 .strip()
            for j in range(len(ingredients_list)):
                if i < 1:
                	# 첫번째 필터링 값은 바로 추가
                    # 레시피 아이디 append
                    recipe_ids.append(ingredients_list[j].article_recipe)
                else:
                	# 2번째부터는 앞선 레시피 아이디 리스트에 포함된 경우만 비교한 리스트에 저장
                    if ingredients_list[j].article_recipe in recipe_ids:
                        compare_ids.append(ingredients_list[j].article_recipe)
            if len(ingredients) > 1 and i > 0:
            	# 비교한 리스트를 앞선 레시피 리스트로 변경 비교 리스트 비우기
                recipe_ids = compare_ids
                compare_ids = []
        serializer = RecipeSerializer(recipe_ids, many=True)
        # 리스트 값들을 json화
        return Response(serializer.data, status=status.HTTP_200_OK)

이 방법이 효과적인지는 모르겠다.
검색 기능 구현 관련해서 검색해보면 Q를 사용하던데 너무 돌아갔나 싶기도 하고...🤔

여러가지 이슈 🫠

  1. list 필드
id | ingredients       | article_id
1  | [돼지고기,양파,김치]  | 2

위와 같은 느낌으로 생각했었는데 list 필드를 지원하는 DB가 별로 없다고 함.
튜터님께 문의해본 결과 mySQL의 경우 일정 버전 이상부터 json 타입을 지원하긴 하지만 종속성이 높아져 다른 DB로 바꾸거나 할 경우 문제가 될 수 있기 때문에 지양하는 것이 좋다고 함.

  1. 재료 전체 텍스트를 저장
id | ingredients         | article_id
1  | "돼지고기,양파,김치,파"  | 2
2  | "참치,김치"  	     | 5

어차피 텍스트를 포함하는 값을 필터링하는 거라면 그냥 통 텍스트를 저장하면 편하지 않겠냐는 의견이 나옴.
그러나 튜터님이 확장성을 고려하여 별로 모델을 생성하는 쪽을 추천하심.
그리고 만약 레시피를 수정할 경우 1번 레시피 내의 라는 단어를 마늘로 수정할 경우,
"돼지고기,양마늘,김치,마늘" 이 되어버릴 가능성이 있다.
조건을 걸면 해결될 수도 있지만 그냥 분리하여 별도 테이블로 관리하기로 함.

DB에 배열을 넣고 싶을 때

  1. 배열 개수만큼 필드 개수 추가(수가 적은 경우 사용)
  2. 별도의 테이블 추가(가장 무난)
  3. 배열을 문자열로 저장 & 꺼낼 땐 JSON으로 파싱해서 사용

참고
디비에 배열을 넣어야 할때 어떻게 하시나요 ?
MySQL(RDB)에 배열을 저장하는 방법

profile
직업: 개발자가 되고 싶은 오레오 집사

0개의 댓글