서비스 프레임워크 설명서 |
상세 검색 기능을 추가해보자. 상세 검색 기능에서는 키워드 외에 기간과 정렬 조건을 검색 조건에 추가할 수 있게 하였다. 상세 검색을 위한 폼을 아래와 같이 먼저 추가한다. (가독성을 위해 태그 및 태그 속성들은 생략했다.)
1. … 2. <a data-target="#detailed-search" role="button" class="btn btn-link" data-toggle="collapse"> <small>상세 검색</small> </a> 3. … 4. <form name="detailed-search-form" class="form-horizontal" role="form"> 5. <div id="detailed-search" class="box box-bordered collapse"> 6. … 7. <labe>키워드</label> 8. <input type="text" name="query" class="form-control" /> 9. <label>기간</label> 10. <label><input type="radio" name="date-range" value=""/> 전체</label> 11. <label><input type="radio" name="date-range" value="d"/> 최근 1일</label> 12. <label><input type="radio" name="date-range" value="w"/> 최근 1주</label> 13. <label><input type="radio" name="date-range" value="m"/> 최근 1달</label> 14. <label><input type="radio" name="date-range" value="y"/> 최근 1년</label> 15. <label><input type="radio" name="date-range" value="r"/> 직접입력</label> 16. <input type="text" name="date-from"/> - <input type="text" name="date-to"/> 17. <label>정렬</label> 18. <label><input type="radio" name="sort" value=""/> 정확도</label> 19. <label><input type="radio" name="sort" value="regdate desc"/> 최신순</label> 20. <button type="submit" class="btn btn-primary">검색</button> 21. <button type="reset" class="btn" id="reset">초기화</button> 22. … 23. </div> 24. </form> 25. …
추가된 폼은 아래와 같이 표시된다.
"상세 검색" 앵커 클릭 시 "상세 검색" 폼이 보이게 하는 것은 bootstrap의 Collapse를 활용하였다.
상세 검색 후 페이지 이동 시 혹은 금칙어, 추천 검색어, 오타 교정 등의 처리를 위해 키워드 검색 폼(search-form)이 포함하는 p, original-query 등의 입력 필드 값들도 함께 서버로 전달되어야 한다. 이를 위해 상세 검색 폼(detailed-search-form)의 검색 버튼 클릭 시 상세 검색 폼을 제출하지 않고 사용자가 입력한 검색 조건들을 키워드 검색 폼에 복사 후 사용자 검색 폼을 제출한다.
아래와 같이 키워드 검색 폼에 상세 검색 폼의 검색 조건들을 추가한다. 페이지 이동 시 검색 조건이 유지될 수 있게 하기 위해 각 앨리먼트의 값들은 요청 파라미터 값들로 초기화한다.
1. … 2. <form name="search-form" method="post" class="form-inline" role="form"> 3. … <input type="hidden" id="date-range" name="date-range" value="${param['date-range']}"/> 4. <input type="hidden" id="date-from" name="date-from" value="${param['date-from']}"/> 5. <input type="hidden" id="date-to" name="date-to" value="${param['date-to']}"/> 6. <input type="hidden" id="sort" name="sort" value="${param['sort']}"/> 7. </form> 8. …
이렇게 키워드 검색 폼에 상세 검색 폼의 검색 조건들을 복사하지 않고 페이지 이동 등을 처리하기 위해 세션 변수에 처음 검색 조건을 저장한 후, 페이지 이동 시 세션 변수에 저장된 검색 조건을 재사용할 수도 있다. (세션 변수를 너무 많이 사용하면 WAS가 사용할 수 있는 가용 메모리가 줄어들므로 가급적 세션 변수 사용은 자제하는 것이 바람직하다.)
이제 상세 검색과 관련된 자바스크립트를 작성해 보자. 먼저 상세 검색 폼의 각 검색 조건을 키워드 검색 폼에 초기화된 값들로 일치시켜 상세 검색 폼을 보여줄 때 현재 검색 조건을 확인할 수 있게 한다.
1. $(function() { 2. … 3. $f = $("form[name=detailed-search-form]"); 4. $f.find("input[name=query]").val($("#query").val()); 5. $f.find("input[name=date-range]").filter("[value="+ $("#date-range").val() + "]").prop("checked",true); 6. $f.find("input[name=date-from]").val($("#date-from").val()); 7. $f.find("input[name=date-to]").val($("#date-to").val()); 8. $f.find("input[name=sort]").filter("[value=\""+ $("#sort").val()+"\"]").prop("checked",true); 9. });
다음 상세 검색 폼 제출 시 검색 조건들을 키워드 검색 폼으로 복사하고 키워드 검색 폼을 대신 제출한다.
10. $f.on("submit", function(e) { // 상세 검색 폼이 제출되지 못하도록 디폴트 핸들러 실행을 막는다. 11. e.preventDefault(); // 검색 조건들을 키워드 검색 폼으로 복사한다. 12. $("#date-range").val($f.find("input[name=date-range]:checked") .val()); 13. $("#date-from").val($f.find("input[name=date-from]").val()); 14. $("#date-to").val($f.find("input[name=date-to]").val()); 15. $("#sort").val($f.find("input[name=sort]:checked").val()); 16. $("#query").val($f.find("input[name=query]").val()); // 키워드 검색 폼을 제출한다. 17. $("form[name=search-form]").submit(); 18. });
상세 검색의 경우 검색 조건이 복잡해졌다. 검색 조건으로부터 SearchQuery 객체를 만드는 클래스를 아래와 같이 SearchQueryBuilder 라는 이름으로 구현한다.
1. <%!public static class SearchQueryBuilder { 2. private String query; 3. 4. public SearchQueryBuilder(String query) { 5. this.query = query; 6. } 7. 8. public SearchQuery getSearchQuery(HttpServletRequest request) { 9. QueryBuilder qb = new QueryBuilder(); // 키워드 검색 조건 10. qb.whereColumnEquals("text_idx", query, "allwordthruindex"); 11. String dateRange = RequestUtils.getParameter (request, "date-range"); 12. if ("r".equals(dateRange)) { // 기간이 직접 입력일 경우 13. qb.whereColumnInDateRange("regdate", RequestUtils.getParameter(request, "date-from"), RequestUtils.getParameter(request, "date-to")); 14. } else { // 기간이 전체, 최근1일, 최근1주, 최근1달, 최근1년일 경우 15. qb.whereColumnInDateRange("regdate", dateRange); 16. } // 정렬 기준 17. qb.orderBy(RequestUtils.getParameterValues(request, "sort")); 18. 19. SearchQuery sq = new SearchQuery("sample", query); 20. sq.setLimit(RequestUtils.getParameterInt(request, "rpp", 10)); 21. sq.setOffset(RequestUtils.getParameterInt(request, "p", 0) * sq.getLimit()); 22. sq.setWhereClause(qb.getWhereClause()); 23. sq.setSortingClause(qb.getSortingClause()); 24. return sq; 25. } 26. } 27. %>
이제 SearchQueryBuilder를 이용해서 검색 결과를 구하도록 JSP 스크립트를 변경한다.
1. … 2. CrzClient crzclient = new CrzClient("127.0.0.1", 9577); 3. SearchQueryBuilder builder = new SearchQueryBuilder(query); 4. SearchQuery sq = builder.getSearchQuery(request); 5. SearchResultSet srs = crzclient.search(sq); 6. …