package org.fastcatsearch.http.action.service; import org.fastcatsearch.control.JobService; import org.fastcatsearch.control.ResultFuture; import org.fastcatsearch.http.ActionMapping; import org.fastcatsearch.http.action.ActionRequest; import org.fastcatsearch.http.action.ActionResponse; import org.fastcatsearch.http.action.ServiceAction; import org.fastcatsearch.http.writer.DemoSearchResultWriter; import org.fastcatsearch.ir.IRService; import org.fastcatsearch.job.search.ClusterSearchJob; import org.fastcatsearch.query.QueryMap; import org.fastcatsearch.service.ServiceManager; import org.fastcatsearch.settings.SearchPageSettings; import org.fastcatsearch.settings.SearchPageSettings.SearchCategorySetting; import org.fastcatsearch.util.ResponseWriter; import org.fastcatsearch.util.ResultWriterException; import java.io.IOException; import java.net.URLDecoder; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; @ActionMapping("/service/demo/search") public class DemoSearchAction extends ServiceAction { private static final String SECTION_SEPARATOR = "(?<!\\\\)&"; private static final String VALUE_SEPARATOR = "(?<!\\\\)="; @Override public void doAction(ActionRequest request, ActionResponse response) throws Exception { String keyword = request.getParameter("keyword"); String category = request.getParameter("category"); int page = request.getIntParameter("page", 1); writeHeader(response); ResponseWriter responseWriter = getResponseWriter(response.getWriter(), ServiceAction.DEFAULT_ROOT_ELEMENT, true, null, false, false); long st = System.nanoTime(); responseWriter.object(); responseWriter.key("category").value(category != null ? category : ""); responseWriter.key("keyword").value(keyword != null ? keyword : ""); try { IRService irService = ServiceManager.getInstance().getService(IRService.class); SearchPageSettings searchPageSettings = irService.getSearchPageSettings(); String realtimePopularKeywordURL = searchPageSettings.getRealtimePopularKeywordURL(); String relateKeywordURL = searchPageSettings.getRelateKeywordURL(); if(relateKeywordURL != null){ relateKeywordURL = replaceKeyword(relateKeywordURL, keyword); } responseWriter.key("realtimePopularKeywordURL").value(realtimePopularKeywordURL != null ? realtimePopularKeywordURL : ""); responseWriter.key("relateKeywordURL").value(relateKeywordURL != null ? relateKeywordURL : ""); responseWriter.key("javascript").value(searchPageSettings.getJavascript()); responseWriter.key("css").value(searchPageSettings.getCss()); // logger.debug(">>> css > {}", searchPageSettings.getCss()); List<SearchCategorySetting> searchCategorySettingList = searchPageSettings.getSearchCategorySettingList(); TreeMap<Integer, SearchCategorySetting> map = new TreeMap<Integer, SearchCategorySetting>(); //order 로 우선순위를 구한다. for (SearchCategorySetting setting : searchCategorySettingList) { int order = Integer.parseInt(setting.getOrder()); map.put(order, setting); } responseWriter.key("category-list").array(); for (SearchCategorySetting s : map.values()) { responseWriter.object().key("id").value(s.getId()) .key("name").value(s.getName()).endObject(); } responseWriter.endArray(); responseWriter.key("result-list").array(); // logger.debug("category > [{}], map[{}]", category, map); if (category != null && category.length() > 0) { //개별 검색시 보여줄 리스트갯수. int searchListSize = searchPageSettings.getSearchListSize(); // 하나만 고른다. SearchCategorySetting setting = null; for (SearchCategorySetting s : searchCategorySettingList) { if (s.getId().equals(category)) { setting = s; break; } } // logger.debug("SearchCategorySetting > {}", setting); if(setting != null) { writeSettingSearchResult(setting, keyword, page, searchListSize, responseWriter); } } else { //통합검색시 보여줄 리스트갯수. int totalSearchListSize = searchPageSettings.getTotalSearchListSize(); for (SearchCategorySetting setting : map.values()) { // logger.debug("SearchCategorySetting2 > {}, {}", setting.getId(), setting); writeSettingSearchResult(setting, keyword, page, totalSearchListSize, responseWriter); } } responseWriter.endArray(); }catch(Exception e){ logger.error("", e); } finally { int time = (int) ((System.nanoTime() - st) / 1000000); String timeString = String.format("%.2f", ((float)time) / 1000.0f); responseWriter.key("time").value(timeString); responseWriter.endObject(); responseWriter.done(); } } private void writeSettingSearchResult(SearchCategorySetting setting, String keyword, int page, int searchListSize, ResponseWriter responseWriter) throws ResultWriterException, IOException{ String queryString = setting.getSearchQuery(); queryString = replaceKeyword(queryString, keyword); QueryMap queryMap = parse(queryString); int sn = (page - 1) * searchListSize + 1; queryMap.put("sn", Integer.toString(sn)); queryMap.put("ln", Integer.toString(searchListSize)); logger.debug("queryMap > {}", queryMap.queryString()); ClusterSearchJob searchJob = new ClusterSearchJob(); searchJob.setArgs(queryMap); long st = System.nanoTime(); ResultFuture resultFuture = JobService.getInstance().offer(searchJob); Object result = resultFuture.take(); long searchTime = (System.nanoTime() - st) / 1000000; responseWriter.object(); responseWriter.key("id").value(setting.getId()); responseWriter.key("name").value(setting.getName().toUpperCase()); responseWriter.key("searchListSize").value(searchListSize); responseWriter.key("result"); DemoSearchResultWriter searchResultWriter = new DemoSearchResultWriter(responseWriter, setting); searchResultWriter.writeResult(result, searchTime, resultFuture.isSuccess()); responseWriter.endObject(); } private String replaceKeyword(String tagetString, String keyword) { if(tagetString == null){ return null; } return tagetString.replace("#keyword", keyword); } private QueryMap parse(String queryString) { Map<String, String> parameterMap = new HashMap<String, String>(); String collectionId = null; for (String pair : queryString.split(SECTION_SEPARATOR)) { String[] kv = pair.split(VALUE_SEPARATOR); if (kv.length < 2) { // key with no value // parameterMap.put(pair.toUpperCase(), ""); parameterMap.put(pair, ""); } else { // key=value String key = kv[0]; String value = kv[1]; try { String decodedValue = URLDecoder.decode(value, "utf-8"); value = decodedValue; logger.debug("DECODE {} > {}", value, decodedValue); } catch (Exception e) { // 디코드 에러시 디코드하지 않음. '100%보증'과 같은 문자가 들어올수 있음. } parameterMap.put(key, value); if(key.equalsIgnoreCase("cn")){ collectionId = value; } } } QueryMap queryMap = new QueryMap(parameterMap); queryMap.setId(collectionId); // logger.debug("parameterMap >> {}", parameterMap); return queryMap; } }