project code search

별하·2024년 6월 17일

프로젝트2

목록 보기
3/10

<메인페이지에서 가게이름, 종류로 검색하는 기능을 구현해보자>

1. db에 저장되어있는것에서 메뉴이름을 검색했을때 검색한 메뉴 불러오기

  • controller
	@GetMapping("search")
	public String search(@RequestParam(required=false) String store_menu_name, Model model) {
		ms.search(store_menu_name, model);
		return "main/search";
	}
  • serviceImpl
public void search(String store_menu_name, Model model) {
		
		List<MainDTO> dtoList;
		  if (store_menu_name != null && !store_menu_name.isEmpty()) {
		        // If search keyword is provided, filter by name
		        dtoList = mapper.search(Arrays.asList(store_menu_name.split(","))); // Adjust this as per your requirement
		    } else {
		        // If no search keyword, fetch all items
		        dtoList = mapper.mainPage1();
		    }
		model.addAttribute("dtoList", dtoList);

	}
  • mapper
public List<MainDTO> search(@Param("store_menu_name") List<String> store_menu_name);
  • mapper.xml
<select id="search" resultMap="main" parameterType="java.util.List">
    SELECT * FROM store_menu
    <where>
        <if test="store_menu_name != null and store_menu_name.size() > 0">
            AND store_menu_name IN
            <foreach item="name" collection="store_menu_name" open="(" separator="," close=")">
                #{name}
            </foreach>
        </if>
    </where>
</select>
  • header.jsp의 js
<script>
function submitSearch() {
    var keyword = document.getElementById('store_menu_name').value.trim(); // 검색어 가져오기

    // 검색어가 유효한 경우에만 검색 실행
    if (keyword !== '') {
        var path = '<%= request.getContextPath() %>';
        var url = path + '/main/search';

        // 검색어를 파라미터로 추가하여 인코딩
        url += '?store_menu_name=' + encodeURIComponent(keyword);

        window.location.href = url; // 검색 결과 페이지로 이동
    } else {
        alert('검색어를 입력하세요.');
    }
}
</script>

2. db에 저장되어있는것에서 메뉴이름또는 메뉴종류를 검색했을때 검색한 값 불러오기

  • controller
	@GetMapping("search")
	public String search(@RequestParam(required=false) String keyword, Model model) {
		model.addAttribute("dtoList", dtoList);
		return "main/search";
	}
  • serviceImpl
	public List<MainDTO> search(String keyword) {
	    return mapper.search(keyword); 
	}
  • mapper
public List<MainDTO> search(@Param("keyword") String keyword);
  • mapper.xml
<select id="search" resultMap="main">
    SELECT * FROM store_menu
    <where>
        <if test="keyword != null and keyword != ''">
            (store_menu_name LIKE '%' || #{keyword} || '%'
            OR store_menu_category LIKE '%' || #{keyword} || '%')
        </if>
    </where>
</select>
  • header.jsp의 js
<script>
function submitSearch() {
    var keyword = document.getElementById('search_keyword').value.trim(); // 검색어 가져오기

    // 검색어가 유효한 경우에만 검색 실행
    if (keyword !== '') {
        var path = '<%= request.getContextPath() %>';
        var url = path + '/main/search';

        // 검색어를 파라미터로 추가하여 인코딩
        url += '?keyword=' + encodeURIComponent(keyword);

        window.location.href = url; // 검색 결과 페이지로 이동
    } else {
        alert('검색어를 입력하세요.');
    }
}
</script>

3. 전체 메뉴이름또는 메뉴종류를 검색했을때 검색한 값 불러오기(드롭다운을 이용한 필터)

  • controller
	@GetMapping("search")
	public String search(@RequestParam(required=false) String keyword, 
						 @RequestParam(required=false) String searchType ,
						Model model) {
		List<MainDTO> dtoList = ms.search(keyword,searchType);
		model.addAttribute("dtoList", dtoList);
		return "main/search";
	}
  • serviceImpl
	public List<MainDTO> search(String keyword, String searchType) {
		Map<String, Object> params = new HashMap<>();
	    params.put("keyword", keyword);
	    params.put("searchType", searchType);

	    return mapper.search(params);   
	}
  • mapper
public List<MainDTO> search(@Param("params") Map<String, Object> params);
  • mapper.xml
 <select id="search" resultMap="main">
        SELECT * FROM store_menu
        <where>
            <if test="params.keyword != null and params.keyword != ''">
                <choose>
                    <when test="params.searchType == 'menu_name'">
                        store_menu_name LIKE '%' || #{params.keyword} || '%'
                    </when>
                    <when test="params.searchType == 'menu_category'">
                        store_menu_category LIKE '%' || #{params.keyword} || '%'
                    </when>
                    <otherwise>
                        store_menu_name LIKE '%' || #{params.keyword} || '%'
                        OR store_menu_category LIKE '%' || #{params.keyword} || '%'
                    </otherwise>
                </choose>
            </if>
        </where>
    </select>
  • header.jsp의 js
<script>
function submitSearch() {
    var category = document.getElementById('search_category').value;
    var keyword = document.getElementById('search_keyword').value.trim();

    // 검색어가 유효한 경우에만 검색 실행
    if (keyword !== '') {
        var path = '<%= request.getContextPath() %>';
        var url = path + '/main/search';

        if (category !== '') {
            url += '?searchType=' + category + '&keyword=' + encodeURIComponent(keyword);
        } else {
            url += '?keyword=' + encodeURIComponent(keyword);
        }

        window.location.href = url; // 검색 결과 페이지로 이동
    } else {
        alert('검색어를 입력하세요.');
    }
}
</script>

4. 메뉴 카테고리에 3개까지 등록시 하나하나 필터로 출력하기

  • mapper.xml
<select id="search" resultMap="main">
    SELECT * FROM store_menu
    <where>
        <if test="params.keyword != null and params.keyword != ''">
            <choose>
            	<!-- 검색유형 메뉴이름일 경우 -->
                <when test="params.searchType == 'menu_name'">
                	<!-- store_menu_name 컬럼이 검색 키워드를 포함하는 레코드 찾음 -->
                    store_menu_name LIKE '%' || #{params.keyword} || '%'
                </when>
                <!-- 검색유형 메뉴 카테고리일 경우 -->
                <when test="params.searchType == 'menu_category'">
                    EXISTS (
                        <!-- store_menu_category 컬러의 값을 '/'로 구분하여 각 부분을 검색 키워드와 비교 -->
                        SELECT 1 FROM dual
                        <!-- store_menu_category 값을 '/'로 구분하여 각 부분을 추출 -->
                        WHERE REGEXP_SUBSTR(store_menu_category, '[^/]+', 1, LEVEL) = #{params.keyword}
                        <!-- oracle sql의 쿼리 구조를 사용하여 '/'로 구분된 모든 부분을 순차적으로 비교 -->
                        CONNECT BY REGEXP_SUBSTR(store_menu_category, '[^/]+', 1, LEVEL) IS NOT NULL
                    )
                </when>
                <!-- 검색유형이 지정되지 않았거나 다른 경우 -->
                <otherwise>
                    store_menu_name LIKE '%' || #{params.keyword} || '%'
                    OR EXISTS (
                        SELECT 1 FROM dual
                        WHERE REGEXP_SUBSTR(store_menu_category, '[^/]+', 1, LEVEL) = #{params.keyword}
                        CONNECT BY REGEXP_SUBSTR(store_menu_category, '[^/]+', 1, LEVEL) IS NOT NULL
                    )
                </otherwise>
            </choose>
        </if>
    </where>
</select>
  • search.jsp
<c:choose>
		<c:when test="${not empty dtoList }">
		    <table border="1">
		        <thead>
		            <tr>
		                <th>메뉴 이름</th>
		                <th>카테고리</th>
		            </tr>
		        </thead>
		        <tbody>
		            <!-- 검색 결과를 반복하여 표시 -->
		            <c:forEach var="search" items="${dtoList}">
		               
                        <tr>
                            <td>${search.store_menu_name}</td>
                            <td>
                           <c:forEach var="category" items="${fn:split(search.store_menu_category, '/')}">
                                <c:if test="${fn:contains(category, param.keyword)}">
                                    ${category}
                                </c:if>
                            </c:forEach>
                            </td>
                        </tr>
              
		            </c:forEach>
		        </tbody>
		    </table>
    	</c:when>
    	<c:otherwise>
    		<p>검색 결과가 없습니다.</p>
    	</c:otherwise>
    </c:choose>

->문제점 : all카테고리 선택시에도 종류가 하나씩만나옴, 예를들어 한식/중식/일식 db에 저장한후 검색시 한식 한식 중식 일식으로 출력

  • REGEXP_SUBSTR함수

    1. REGEXP_SUBSTR(대상 문자, 패턴, 시작위치(최소값1), 매칭순번)
    2. REGEXP_SUBSTR(source_string, pattern [, start_position [, match_occurrence [, return_option [, match_param ]]]])
  • REGEXP_SUBSTR은 정규 표현식 패턴에 대한 문자열을 찾는 SUBSTR 함수의 확장이다.

5. all카테고리 선택시 종류 3개 다보이면서 category 선택하고 종류 하나 검색시 하나 출력, 중복 없애기(수정 코드만, 나중에 merge후 다시 수정 필요)

	<h2>검색 결과</h2>
	<c:choose>
		<c:when test="${not empty dtoList }">
		    <table border="1">
		        <thead>
		            <tr>
		                <th>메뉴 이름</th>
		                <th>카테고리</th>
		            </tr>
		        </thead>
		        <tbody>
		            <!-- 검색 결과를 반복하여 표시 -->
		             <c:forEach var="search" items="${dtoList}">
                        <tr>
                            <td>${search.store_menu_name}</td>
                            <td>
                                <c:set var="seenCategories" value="" />
                                <!-- 특정 카테고리로 검색 시 -->
                                <c:forEach var="category" items="${fn:split(search.store_menu_category, '/')}">
                                    <c:if test="${fn:contains(category, param.keyword)}">
                                        <c:if test="${not fn:contains(seenCategories, category)}">
                                            <c:if test="${!empty seenCategories}">
                                                /
                                            </c:if>
                                            ${category}
                                            <c:set var="seenCategories" value="${seenCategories}${category}/" />
                                        </c:if>
                                    </c:if>
                                </c:forEach>
                                
                                <!-- "ALL" 또는 메뉴 이름으로 검색 시 모든 카테고리 출력 -->
                                <c:if test="${param.searchType == 'menu_name' || param.searchType == '' || param.searchType == null}">
                                    <c:forEach var="category" items="${fn:split(search.store_menu_category, '/')}">
                                        <c:if test="${not fn:contains(seenCategories, category)}">
                                            <c:if test="${!empty seenCategories}">
                                                /
                                            </c:if>
                                            ${category}
                                            <c:set var="seenCategories" value="${seenCategories}${category}/" />
                                        </c:if>
                                    </c:forEach>
                                </c:if>
                                
                            </td>
                        </tr>
		            </c:forEach>
		        </tbody>
		    </table>
    	</c:when>
    	<c:otherwise>
    		<p>검색 결과가 없습니다.</p>
    	</c:otherwise>
    </c:choose>
    <a href="/root/main/mainPage1">메인페이지</a>

6. 그 뒤 join해서 수정

<select id="getStoreInfo" resultMap="mainMap">
    SELECT si.*, 
           sm.store_menu_img, 
           sm.store_menu_name, 
           sm.store_menu_price, 
           sm.store_menu_detail, 
           sm.store_menu_category 
    FROM store_info si
    LEFT JOIN store_menu sm ON si.store_id = sm.store_id
    <where>
        <if test="params.keyword != null and params.keyword != ''">
            <choose>
                <when test="params.searchType == 'menu_name'">
                    si.store_name LIKE '%' || #{params.keyword} || '%'
                </when>
                <when test="params.searchType == 'menu_category'">
                    EXISTS (
                        SELECT 1 FROM dual
                        WHERE REGEXP_SUBSTR(si.store_category, '[^/]+', 1, LEVEL) = #{params.keyword}
                        CONNECT BY REGEXP_SUBSTR(si.store_category, '[^/]+', 1, LEVEL) IS NOT NULL
                    )
                </when>
                <otherwise>
                    si.store_name LIKE '%' || #{params.keyword} || '%'
                    OR EXISTS (
                        SELECT 1 FROM dual
                        WHERE REGEXP_SUBSTR(si.store_category, '[^/]+', 1, LEVEL) = #{params.keyword}
                        CONNECT BY REGEXP_SUBSTR(si.store_category, '[^/]+', 1, LEVEL) IS NOT NULL
                    )
                </otherwise>
            </choose>
        </if>
        <if test="params.category != null and params.category != ''">
            AND si.store_category LIKE '%' || #{params.category} || '%'
        </if>
    </where>
</select>

0개의 댓글