Authored by Gino Zhang

搜索统计关键字的redis按日期统计

1 -package com.yoho.search.service.common;  
2 -  
3 -public class RedisKeys {  
4 -  
5 - public static String YOHO_SEARCH_KEYWORDS_HOT = "YOHO.SEARCH.KEYWORDS.HOT.%s";  
6 - //public static String YOHO_SEARCH_KEYWORDS_HOT_TOKENS = YOHO_SEARCH_KEYWORDS_HOT + ".TOEKNS";  
7 -  
8 - public static String YOHO_SEARCH_KEYWORDS_EMPTY = "YOHO.SEARCH.KEYWORDS.EMPTY.%s";  
9 - //public static String YOHO_SEARCH_KEYWORDS_EMPTY_TOKENS = YOHO_SEARCH_KEYWORDS_EMPTY + ".TOEKNS";  
10 -  
11 - public static String YOHO_SEARCH_KEYWORDS_LESS = "YOHO.SEARCH.KEYWORDS.LESS.%s";  
12 - //public static String YOHO_SEARCH_KEYWORDS_LESS_TOKENS = YOHO_SEARCH_KEYWORDS_LESS + ".TOEKNS";  
13 -  
14 -}  
@@ -40,35 +40,17 @@ public class ToolsController { @@ -40,35 +40,17 @@ public class ToolsController {
40 */ 40 */
41 @RequestMapping(method = RequestMethod.GET, value = "/hotSearchWords") 41 @RequestMapping(method = RequestMethod.GET, value = "/hotSearchWords")
42 @ResponseBody 42 @ResponseBody
43 - public SearchApiResult hotSearchWords(@RequestParam(defaultValue = "1000") int limit, @RequestParam(defaultValue = "false") boolean onlyShowKeyWord) { 43 + public SearchApiResult hotSearchWords(@RequestParam(defaultValue = "1000") int limit,
  44 + @RequestParam(defaultValue = "false") boolean onlyShowKeyWord,
  45 + @RequestParam(defaultValue = "true") boolean returnTodayRecords) {
44 SearchApiResult searchApiResult = new SearchApiResult(); 46 SearchApiResult searchApiResult = new SearchApiResult();
45 - List<KeyWordWithCount> results = searchKeyWordService.getHotkeyWords(limit); 47 + Map<String, Object> results = searchKeyWordService.getHotkeyWords(limit, onlyShowKeyWord ? false : returnTodayRecords);
46 if (!onlyShowKeyWord) { 48 if (!onlyShowKeyWord) {
47 return searchApiResult.setData(results); 49 return searchApiResult.setData(results);
48 } 50 }
49 - List<String> keywords = new ArrayList<String>();  
50 - for (KeyWordWithCount keyWordWithCount : results) {  
51 - keywords.add(keyWordWithCount.getKeyWord());  
52 - }  
53 - return searchApiResult.setData(keywords);  
54 - }  
55 51
56 - /**  
57 - * 获取热搜词结果  
58 - *  
59 - * @param request  
60 - * @return  
61 - */  
62 - @RequestMapping(method = RequestMethod.GET, value = "/hotSearchWordTokens")  
63 - @ResponseBody  
64 - public SearchApiResult hotSearchWordTokens(@RequestParam(defaultValue = "1000") int limit, @RequestParam(defaultValue = "false") boolean onlyShowKeyWord) {  
65 - SearchApiResult searchApiResult = new SearchApiResult();  
66 - List<KeyWordWithCount> results = searchKeyWordService.getHotkeyWordTokens(limit);  
67 - if (!onlyShowKeyWord) {  
68 - return searchApiResult.setData(results);  
69 - }  
70 - List<String> keywords = new ArrayList<String>();  
71 - for (KeyWordWithCount keyWordWithCount : results) { 52 + List<String> keywords = new ArrayList<>();
  53 + for (KeyWordWithCount keyWordWithCount : (List<KeyWordWithCount>)results.get("-1")) {
72 keywords.add(keyWordWithCount.getKeyWord()); 54 keywords.add(keyWordWithCount.getKeyWord());
73 } 55 }
74 return searchApiResult.setData(keywords); 56 return searchApiResult.setData(keywords);
@@ -76,41 +58,21 @@ public class ToolsController { @@ -76,41 +58,21 @@ public class ToolsController {
76 58
77 /** 59 /**
78 * 获取空结果搜索词 60 * 获取空结果搜索词
79 - *  
80 - * @param request  
81 * @return 61 * @return
82 */ 62 */
83 @RequestMapping(method = RequestMethod.GET, value = "/emptyResultKeywords") 63 @RequestMapping(method = RequestMethod.GET, value = "/emptyResultKeywords")
84 @ResponseBody 64 @ResponseBody
85 - public SearchApiResult emptyResultKeywords(@RequestParam(defaultValue = "1000") int limit, @RequestParam(defaultValue = "false") boolean onlyShowKeyWord) { 65 + public SearchApiResult emptyResultKeywords(@RequestParam(defaultValue = "1000") int limit,
  66 + @RequestParam(defaultValue = "false") boolean onlyShowKeyWord,
  67 + @RequestParam(defaultValue = "true") boolean returnTodayRecords) {
86 SearchApiResult searchApiResult = new SearchApiResult(); 68 SearchApiResult searchApiResult = new SearchApiResult();
87 - List<KeyWordWithCount> results = searchKeyWordService.getEmptyKeyWords(limit); 69 + Map<String, Object> results = searchKeyWordService.getEmptyKeyWords(limit, onlyShowKeyWord ? false : returnTodayRecords);
88 if (!onlyShowKeyWord) { 70 if (!onlyShowKeyWord) {
89 return searchApiResult.setData(results); 71 return searchApiResult.setData(results);
90 } 72 }
91 - List<String> keywords = new ArrayList<String>();  
92 - for (KeyWordWithCount keyWordWithCount : results) {  
93 - keywords.add(keyWordWithCount.getKeyWord());  
94 - }  
95 - return searchApiResult.setData(keywords);  
96 - }  
97 73
98 - /**  
99 - * 获取空结果搜索词  
100 - *  
101 - * @param request  
102 - * @return  
103 - */  
104 - @RequestMapping(method = RequestMethod.GET, value = "/emptyResultKeywordTokens")  
105 - @ResponseBody  
106 - public SearchApiResult emptyResultKeywordTokens(@RequestParam(defaultValue = "1000") int limit, @RequestParam(defaultValue = "false") boolean onlyShowKeyWord) {  
107 - SearchApiResult searchApiResult = new SearchApiResult();  
108 - List<KeyWordWithCount> results = searchKeyWordService.getEmptyKeyWordTokens(limit);  
109 - if (!onlyShowKeyWord) {  
110 - return searchApiResult.setData(results);  
111 - }  
112 - List<String> keywords = new ArrayList<String>();  
113 - for (KeyWordWithCount keyWordWithCount : results) { 74 + List<String> keywords = new ArrayList<>();
  75 + for (KeyWordWithCount keyWordWithCount : (List<KeyWordWithCount>)results.get("-1")) {
114 keywords.add(keyWordWithCount.getKeyWord()); 76 keywords.add(keyWordWithCount.getKeyWord());
115 } 77 }
116 return searchApiResult.setData(keywords); 78 return searchApiResult.setData(keywords);
@@ -124,35 +86,17 @@ public class ToolsController { @@ -124,35 +86,17 @@ public class ToolsController {
124 */ 86 */
125 @RequestMapping(method = RequestMethod.GET, value = "/lessKeyWords") 87 @RequestMapping(method = RequestMethod.GET, value = "/lessKeyWords")
126 @ResponseBody 88 @ResponseBody
127 - public SearchApiResult lessKeyWords(@RequestParam(defaultValue = "1000") int limit, @RequestParam(defaultValue = "false") boolean onlyShowKeyWord) { 89 + public SearchApiResult lessKeyWords(@RequestParam(defaultValue = "1000") int limit,
  90 + @RequestParam(defaultValue = "false") boolean onlyShowKeyWord,
  91 + @RequestParam(defaultValue = "true") boolean returnTodayRecords) {
128 SearchApiResult searchApiResult = new SearchApiResult(); 92 SearchApiResult searchApiResult = new SearchApiResult();
129 - List<KeyWordWithCount> results = searchKeyWordService.getLessKeyWords(limit); 93 + Map<String, Object> results = searchKeyWordService.getLessKeyWords(limit, onlyShowKeyWord ? false : returnTodayRecords);
130 if (!onlyShowKeyWord) { 94 if (!onlyShowKeyWord) {
131 return searchApiResult.setData(results); 95 return searchApiResult.setData(results);
132 } 96 }
133 - List<String> keywords = new ArrayList<String>();  
134 - for (KeyWordWithCount keyWordWithCount : results) {  
135 - keywords.add(keyWordWithCount.getKeyWord());  
136 - }  
137 - return searchApiResult.setData(keywords);  
138 - }  
139 97
140 - /**  
141 - * 获取一页搜索词  
142 - *  
143 - * @param request  
144 - * @return  
145 - */  
146 - @RequestMapping(method = RequestMethod.GET, value = "/lessKeyWordTokens")  
147 - @ResponseBody  
148 - public SearchApiResult lessKeyWordTokens(@RequestParam(defaultValue = "1000") int limit, @RequestParam(defaultValue = "false") boolean onlyShowKeyWord) {  
149 - SearchApiResult searchApiResult = new SearchApiResult();  
150 - List<KeyWordWithCount> results = searchKeyWordService.getLessKeyWordTokens(limit);  
151 - if (!onlyShowKeyWord) {  
152 - return searchApiResult.setData(results);  
153 - }  
154 - List<String> keywords = new ArrayList<String>();  
155 - for (KeyWordWithCount keyWordWithCount : results) { 98 + List<String> keywords = new ArrayList<>();
  99 + for (KeyWordWithCount keyWordWithCount : (List<KeyWordWithCount>)results.get("-1")) {
156 keywords.add(keyWordWithCount.getKeyWord()); 100 keywords.add(keyWordWithCount.getKeyWord());
157 } 101 }
158 return searchApiResult.setData(keywords); 102 return searchApiResult.setData(keywords);
1 package com.yoho.search.service.service; 1 package com.yoho.search.service.service;
2 2
  3 +import com.yoho.core.redis.YHRedisTemplate;
3 import com.yoho.core.redis.YHZSetOperations; 4 import com.yoho.core.redis.YHZSetOperations;
  5 +import com.yoho.search.base.utils.DateStyle;
  6 +import com.yoho.search.base.utils.DateUtil;
4 import com.yoho.search.base.utils.ISearchConstants; 7 import com.yoho.search.base.utils.ISearchConstants;
5 import com.yoho.search.core.es.IElasticsearchClient; 8 import com.yoho.search.core.es.IElasticsearchClient;
6 import com.yoho.search.core.es.impl.YohoIndexHelper; 9 import com.yoho.search.core.es.impl.YohoIndexHelper;
7 -import com.yoho.search.service.common.RedisKeys; 10 +import com.yoho.search.base.utils.RedisKeys;
8 import com.yoho.search.service.vo.KeyWordWithCount; 11 import com.yoho.search.service.vo.KeyWordWithCount;
9 import org.elasticsearch.action.admin.indices.analyze.AnalyzeResponse.AnalyzeToken; 12 import org.elasticsearch.action.admin.indices.analyze.AnalyzeResponse.AnalyzeToken;
10 import org.slf4j.Logger; 13 import org.slf4j.Logger;
@@ -16,194 +19,197 @@ import org.springframework.stereotype.Service; @@ -16,194 +19,197 @@ import org.springframework.stereotype.Service;
16 19
17 import javax.annotation.Resource; 20 import javax.annotation.Resource;
18 import java.text.SimpleDateFormat; 21 import java.text.SimpleDateFormat;
19 -import java.util.ArrayList;  
20 -import java.util.List;  
21 -import java.util.Map;  
22 -import java.util.Set; 22 +import java.util.*;
23 import java.util.concurrent.ExecutorService; 23 import java.util.concurrent.ExecutorService;
24 import java.util.concurrent.Executors; 24 import java.util.concurrent.Executors;
  25 +import java.util.concurrent.TimeUnit;
25 26
26 /** 27 /**
27 * 将关键字结果存进redis中 28 * 将关键字结果存进redis中
28 * 29 *
29 * @author hugufei 30 * @author hugufei
30 - *  
31 */ 31 */
32 32
33 @Service 33 @Service
34 public class SearchKeyWordService { 34 public class SearchKeyWordService {
35 35
36 - private static final Logger logger = LoggerFactory.getLogger(SearchKeyWordService.class);  
37 -  
38 - private static final Logger EMPTY_RESULT = LoggerFactory.getLogger("EMPTY_RESULT");  
39 -  
40 - @Resource(name = "yhNoSyncZSetOperations")  
41 - private YHZSetOperations<String, String> yhNoSyncZSetOperations;  
42 -  
43 - @Autowired  
44 - private ESClientMgr esClientMgr;  
45 -  
46 - @Autowired  
47 - private YohoIndexHelper yohoIndexHelper;  
48 -  
49 - private ExecutorService service = Executors.newFixedThreadPool(5);  
50 -  
51 - public List<AnalyzeToken> getAnalyzeTokens(String text, String analyzer) {  
52 - List<AnalyzeToken> analyzeTokens = new ArrayList<AnalyzeToken>();  
53 - final String yohoIndexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;  
54 - IElasticsearchClient client = esClientMgr.getClient(yohoIndexName);  
55 - List<String> realIndexNames = yohoIndexHelper.getRealIndexNames(yohoIndexName, client);  
56 - if (realIndexNames == null || realIndexNames.isEmpty() || realIndexNames.size() > 1) {  
57 - return analyzeTokens;  
58 - }  
59 - return client.getAnalyzeResponse(yohoIndexName, text, analyzer).getTokens();  
60 - }  
61 -  
62 - /**  
63 - * 获取分词结果  
64 - *  
65 - * @param keyWord  
66 - * @return  
67 - */  
68 - public List<String> getAnalyzeTerms(String keyWord, String analyzer) {  
69 - try {  
70 - List<AnalyzeToken> tokens = getAnalyzeTokens(keyWord, analyzer);  
71 - List<String> results = new ArrayList<String>();  
72 - for (AnalyzeToken analyzeToken : tokens) {  
73 - results.add(analyzeToken.getTerm());  
74 - }  
75 - return results;  
76 - } catch (Exception e) {  
77 - logger.error(keyWord, e);  
78 - return new ArrayList<>();  
79 - }  
80 - }  
81 -  
82 - /**  
83 - * 获取分词结果  
84 - *  
85 - * @param keyWord  
86 - * @return  
87 - */  
88 - private List<String> getAnalyzeTokens(String keyWord) {  
89 - return getAnalyzeTerms(keyWord, "ik_complex");  
90 - }  
91 -  
92 - // 异步的做法是防止redis报错影响搜索主流程  
93 - private void recordKeyWord(String redisKey, String queryWord) {  
94 - service.submit(new Runnable() {  
95 - @Override  
96 - public void run() {  
97 - try {  
98 - // 1、记录整词  
99 - String keyWord = queryWord;  
100 - yhNoSyncZSetOperations.incrementScore(redisKey, keyWord, 1);  
101 -  
102 - // 2、记录分词结果  
103 - String redisKeyWithToken = redisKey + ".TOEKNS";  
104 - List<String> tokens = getAnalyzeTokens(keyWord);  
105 - for (String token : tokens) {  
106 - yhNoSyncZSetOperations.incrementScore(redisKeyWithToken, token, 1);  
107 - }  
108 - } catch (Exception e) {  
109 - logger.error(e.getMessage(), e);  
110 - }  
111 - }  
112 - });  
113 - }  
114 -  
115 - /**  
116 - * 增加热搜词的次数  
117 - *  
118 - * @param queryWord  
119 - */  
120 - public void recordKeyWord(String queryWord) {  
121 - this.recordKeyWord(RedisKeys.YOHO_SEARCH_KEYWORDS_HOT, queryWord);  
122 - }  
123 -  
124 - /**  
125 - * 根据【搜索结果数】记录搜索词  
126 - *  
127 - * @param queryWord  
128 - * @param total  
129 - */  
130 - public void recordKeyWordByResultCount(String queryWord, long total) {  
131 - // 1、如果搜索结果为0,则加入【空结果列表】  
132 - if (total == 0) {  
133 - this.recordKeyWord(RedisKeys.YOHO_SEARCH_KEYWORDS_EMPTY, queryWord);  
134 - return;  
135 - }  
136 - // 2、如果搜索结果为小于10,则加入【结果<10个的结果集】  
137 - if (total <= 10) {  
138 - this.recordKeyWord(RedisKeys.YOHO_SEARCH_KEYWORDS_LESS, queryWord);  
139 - return;  
140 - }  
141 - }  
142 -  
143 - // 获取【热搜】toplist  
144 - public List<KeyWordWithCount> getHotkeyWords(int limit) {  
145 - return this.getListByScoreDesc(RedisKeys.YOHO_SEARCH_KEYWORDS_HOT, limit);  
146 - }  
147 -  
148 - // 获取【热搜】toplist  
149 - public List<KeyWordWithCount> getHotkeyWordTokens(int limit) {  
150 - //return this.getListByScoreDesc(RedisKeys.YOHO_SEARCH_KEYWORDS_HOT_TOKENS, limit);  
151 - // token没什么用处 先不存储  
152 - return new ArrayList<>();  
153 - }  
154 -  
155 - // 获取空结果的toplist  
156 - public List<KeyWordWithCount> getEmptyKeyWords(int limit) {  
157 - return this.getListByScoreDesc(RedisKeys.YOHO_SEARCH_KEYWORDS_EMPTY, limit);  
158 - }  
159 -  
160 - // 获取空结果的toplist  
161 - public List<KeyWordWithCount> getEmptyKeyWordTokens(int limit) {  
162 - //return this.getListByScoreDesc(RedisKeys.YOHO_SEARCH_KEYWORDS_EMPTY_TOKENS, limit);  
163 - // token没什么用处 先不存储  
164 - return new ArrayList<>();  
165 - }  
166 -  
167 - // 获取只有一页结果的toplist  
168 - public List<KeyWordWithCount> getLessKeyWords(int limit) {  
169 - return this.getListByScoreDesc(RedisKeys.YOHO_SEARCH_KEYWORDS_LESS, limit);  
170 - }  
171 -  
172 - // 获取只有一页结果的toplist  
173 - public List<KeyWordWithCount> getLessKeyWordTokens(int limit) {  
174 - //return this.getListByScoreDesc(RedisKeys.YOHO_SEARCH_KEYWORDS_LESS_TOKENS, limit);  
175 - // token没什么用处 先不存储  
176 - return new ArrayList<>();  
177 - }  
178 -  
179 - private List<KeyWordWithCount> getListByScoreDesc(String redisKey, int limit) {  
180 - Set<ZSetOperations.TypedTuple<String>> redisResults = yhNoSyncZSetOperations.reverseRangeWithScores(redisKey, 0, limit);  
181 - List<KeyWordWithCount> results = new ArrayList<KeyWordWithCount>();  
182 - for (TypedTuple<String> typedTuple : redisResults) {  
183 - String keyWord = typedTuple.getValue();  
184 - KeyWordWithCount result = new KeyWordWithCount(keyWord, (int) typedTuple.getScore().doubleValue());  
185 - results.add(result);  
186 - }  
187 - return results;  
188 - }  
189 -  
190 - public void handleEmptyRecords(Map<String, String> paramMap) {  
191 - StringBuilder paramStringBuilder = new StringBuilder();  
192 - for (Map.Entry<String, String> entry : paramMap.entrySet()) {  
193 - paramStringBuilder.append("&").append(entry.getKey()).append("=").append(entry.getValue());  
194 - }  
195 - String paramString = paramStringBuilder.toString().replaceFirst("&", "");  
196 - EMPTY_RESULT.info("empty records for search.json: time[{}], param [{}]", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(System.currentTimeMillis()), paramString);  
197 -  
198 - // 商品池或品类列表 为空,则告警  
199 - if (paramMap.get("filter_poolId") != null) {// ||  
200 - // paramMap.get("msort")!=null  
201 - // ||  
202 - // paramMap.get("misort")!=null  
203 - // ||  
204 - // paramMap.get("sort")!=null  
205 - // /TODO  
206 - }  
207 - } 36 + private static final Logger logger = LoggerFactory.getLogger(SearchKeyWordService.class);
  37 +
  38 + private static final Logger EMPTY_RESULT = LoggerFactory.getLogger("EMPTY_RESULT");
  39 +
  40 + @Resource(name = "yhNoSyncZSetOperations")
  41 + private YHZSetOperations<String, String> yhNoSyncZSetOperations;
  42 +
  43 +
  44 + @Resource(name = "yhNoSyncRedisTemplate")
  45 + private YHRedisTemplate<String, String> yhNoSyncRedisTemplate;
  46 +
  47 + @Autowired
  48 + private ESClientMgr esClientMgr;
  49 +
  50 + @Autowired
  51 + private YohoIndexHelper yohoIndexHelper;
  52 +
  53 + private ExecutorService service = Executors.newFixedThreadPool(5);
  54 +
  55 + // 保存rediskey中的日期
  56 + private volatile String dateForRedisKey = null;
  57 +
  58 + public List<AnalyzeToken> getAnalyzeTokens(String text, String analyzer) {
  59 + List<AnalyzeToken> analyzeTokens = new ArrayList<AnalyzeToken>();
  60 + final String yohoIndexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
  61 + IElasticsearchClient client = esClientMgr.getClient(yohoIndexName);
  62 + List<String> realIndexNames = yohoIndexHelper.getRealIndexNames(yohoIndexName, client);
  63 + if (realIndexNames == null || realIndexNames.isEmpty() || realIndexNames.size() > 1) {
  64 + return analyzeTokens;
  65 + }
  66 + return client.getAnalyzeResponse(yohoIndexName, text, analyzer).getTokens();
  67 + }
  68 +
  69 + /**
  70 + * 获取分词结果
  71 + *
  72 + * @param keyWord
  73 + * @return
  74 + */
  75 + public List<String> getAnalyzeTerms(String keyWord, String analyzer) {
  76 + try {
  77 + List<AnalyzeToken> tokens = getAnalyzeTokens(keyWord, analyzer);
  78 + List<String> results = new ArrayList<String>();
  79 + for (AnalyzeToken analyzeToken : tokens) {
  80 + results.add(analyzeToken.getTerm());
  81 + }
  82 + return results;
  83 + } catch (Exception e) {
  84 + logger.error(keyWord, e);
  85 + return new ArrayList<>();
  86 + }
  87 + }
  88 +
  89 + // 异步的做法是防止redis报错影响搜索主流程
  90 + private void recordKeyWord(String redisKeyTemplate, String queryWord) {
  91 + service.submit(new Runnable() {
  92 + @Override
  93 + public void run() {
  94 + try {
  95 + // 按照当前时间和rediKey格式生成真正的redisKey
  96 + // 如果是第一次生成的话 给redis设置30个小时的失效时间
  97 + String currentDate = DateUtil.DateToString(new Date(), DateStyle.YYYYMMDD);
  98 + String redisKey = String.format(redisKeyTemplate, currentDate);
  99 + boolean hasIncreased = false;
  100 + if (!currentDate.equals(dateForRedisKey)) {
  101 + synchronized (this) {
  102 + if (!currentDate.equals(dateForRedisKey)) {
  103 + dateForRedisKey = currentDate;
  104 + yhNoSyncZSetOperations.incrementScore(redisKey, queryWord, 1);
  105 + yhNoSyncRedisTemplate.longExpire(redisKey, 30L, TimeUnit.HOURS);
  106 + hasIncreased = true;
  107 + logger.info("update new redis key date {}.", dateForRedisKey);
  108 + }
  109 + }
  110 + }
  111 +
  112 + if (!hasIncreased) {
  113 + yhNoSyncZSetOperations.incrementScore(redisKey, queryWord, 1);
  114 + }
  115 + } catch (Exception e) {
  116 + logger.error(queryWord + "/" + redisKeyTemplate, e);
  117 + }
  118 + }
  119 + });
  120 + }
  121 +
  122 + /**
  123 + * 增加热搜词的次数
  124 + *
  125 + * @param queryWord
  126 + */
  127 + public void recordKeyWord(String queryWord) {
  128 + this.recordKeyWord(RedisKeys.YOHO_SEARCH_KEYWORDS_HOT, queryWord);
  129 + }
  130 +
  131 + /**
  132 + * 根据【搜索结果数】记录搜索词
  133 + *
  134 + * @param queryWord
  135 + * @param total
  136 + */
  137 + public void recordKeyWordByResultCount(String queryWord, long total) {
  138 + // 1、如果搜索结果为0,则加入【空结果列表】
  139 + if (total == 0) {
  140 + this.recordKeyWord(RedisKeys.YOHO_SEARCH_KEYWORDS_EMPTY, queryWord);
  141 + return;
  142 + }
  143 + // 2、如果搜索结果为小于10,则加入【结果<10个的结果集】
  144 + if (total <= 10) {
  145 + this.recordKeyWord(RedisKeys.YOHO_SEARCH_KEYWORDS_LESS, queryWord);
  146 + return;
  147 + }
  148 + }
  149 +
  150 + // 获取【热搜】toplist
  151 + public Map<String, Object> getHotkeyWords(int limit, boolean isReturnTodayRecords) {
  152 + return this.getListByScoreDesc(RedisKeys.YOHO_SEARCH_KEYWORDS_HOT, limit, isReturnTodayRecords);
  153 + }
  154 +
  155 + // 获取空结果的toplist
  156 + public Map<String, Object> getEmptyKeyWords(int limit, boolean isReturnTodayRecords) {
  157 + return this.getListByScoreDesc(RedisKeys.YOHO_SEARCH_KEYWORDS_EMPTY, limit, isReturnTodayRecords);
  158 + }
  159 +
  160 + // 获取只有一页结果的toplist
  161 + public Map<String, Object> getLessKeyWords(int limit, boolean isReturnTodayRecords) {
  162 + return this.getListByScoreDesc(RedisKeys.YOHO_SEARCH_KEYWORDS_LESS, limit, isReturnTodayRecords);
  163 + }
  164 +
  165 + private Map<String, Object> getListByScoreDesc(String redisKeyTemplate, int limit, boolean isReturnTodayRecords) {
  166 + Map<String, Object> resultMap = new HashMap<>(3);
  167 + resultMap.put("dateForRedisKey", dateForRedisKey);
  168 + if (this.dateForRedisKey == null) {
  169 + return resultMap;
  170 + }
  171 +
  172 + String redisKey = RedisKeys.getRedisKey4Yesterday(redisKeyTemplate);
  173 + Set<ZSetOperations.TypedTuple<String>> redisResults = yhNoSyncZSetOperations.reverseRangeWithScores(redisKey, 0, limit);
  174 + List<KeyWordWithCount> results = new ArrayList<KeyWordWithCount>();
  175 + for (TypedTuple<String> typedTuple : redisResults) {
  176 + results.add(new KeyWordWithCount(typedTuple.getValue(), (int) typedTuple.getScore().doubleValue()));
  177 + }
  178 +
  179 + if (isReturnTodayRecords) {
  180 + // 也返回今天的数据
  181 + String redisKey4Today = RedisKeys.getRedisKey4Today(redisKeyTemplate);
  182 + Set<ZSetOperations.TypedTuple<String>> redisResults4Today = yhNoSyncZSetOperations.reverseRangeWithScores(redisKey4Today, 0, limit);
  183 + List<KeyWordWithCount> results4Today = new ArrayList<KeyWordWithCount>();
  184 + for (TypedTuple<String> typedTuple : redisResults4Today) {
  185 + results4Today.add(new KeyWordWithCount(typedTuple.getValue(), (int) typedTuple.getScore().doubleValue()));
  186 + }
  187 +
  188 + resultMap.put("0", results4Today);
  189 + }
  190 +
  191 + resultMap.put("redisKey", redisKey);
  192 + resultMap.put("-1", results);
  193 + return resultMap;
  194 + }
  195 +
  196 + public void handleEmptyRecords(Map<String, String> paramMap) {
  197 + StringBuilder paramStringBuilder = new StringBuilder();
  198 + for (Map.Entry<String, String> entry : paramMap.entrySet()) {
  199 + paramStringBuilder.append("&").append(entry.getKey()).append("=").append(entry.getValue());
  200 + }
  201 + String paramString = paramStringBuilder.toString().replaceFirst("&", "");
  202 + EMPTY_RESULT.info("empty records for search.json: time[{}], param [{}]", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(System.currentTimeMillis()), paramString);
  203 +
  204 + // 商品池或品类列表 为空,则告警
  205 + if (paramMap.get("filter_poolId") != null) {// ||
  206 + // paramMap.get("msort")!=null
  207 + // ||
  208 + // paramMap.get("misort")!=null
  209 + // ||
  210 + // paramMap.get("sort")!=null
  211 + // /TODO
  212 + }
  213 + }
208 214
209 } 215 }