Authored by 胡古飞

Merge branch 'zf_agg' into gray

@@ -3,6 +3,7 @@ package com.yoho.search.service.aggregations.impls; @@ -3,6 +3,7 @@ package com.yoho.search.service.aggregations.impls;
3 import com.yoho.search.core.es.agg.IAggregation; 3 import com.yoho.search.core.es.agg.IAggregation;
4 import com.yoho.search.service.aggregations.AggInterface; 4 import com.yoho.search.service.aggregations.AggInterface;
5 import com.yoho.search.service.service.SearchCommonService; 5 import com.yoho.search.service.service.SearchCommonService;
  6 +import com.yoho.search.service.servicenew.IShopsService;
6 import com.yoho.search.service.servicenew.impl.SearchAfterCacheService; 7 import com.yoho.search.service.servicenew.impl.SearchAfterCacheService;
7 import org.springframework.beans.factory.annotation.Autowired; 8 import org.springframework.beans.factory.annotation.Autowired;
8 import org.springframework.stereotype.Service; 9 import org.springframework.stereotype.Service;
@@ -17,6 +18,9 @@ public class AggregationFactoryService { @@ -17,6 +18,9 @@ public class AggregationFactoryService {
17 @Autowired 18 @Autowired
18 private SearchAfterCacheService searchAfterCacheService; 19 private SearchAfterCacheService searchAfterCacheService;
19 20
  21 + @Autowired
  22 + private IShopsService shopsService;
  23 +
20 public IAggregation getSubAggregationByType(int type, Map<String, String> paramMap) { 24 public IAggregation getSubAggregationByType(int type, Map<String, String> paramMap) {
21 IAggregation iAggregation = null; 25 IAggregation iAggregation = null;
22 switch (type) { 26 switch (type) {
@@ -127,4 +131,11 @@ public class AggregationFactoryService { @@ -127,4 +131,11 @@ public class AggregationFactoryService {
127 return new SortGroupAggregation(paramMap); 131 return new SortGroupAggregation(paramMap);
128 } 132 }
129 133
  134 + public IAggregation getKeywordAggregation(int aggCount) {
  135 + return new KeywordAggregation(aggCount);
  136 + }
  137 +
  138 + public IAggregation getShopAggregation(int aggCount) {
  139 + return new ShopAggregation(shopsService, aggCount);
  140 + }
130 } 141 }
  1 +package com.yoho.search.service.aggregations.impls;
  2 +
  3 +import org.apache.commons.collections.CollectionUtils;
  4 +import org.elasticsearch.search.aggregations.Aggregation;
  5 +
  6 +import java.util.Arrays;
  7 +import java.util.List;
  8 +import java.util.Map;
  9 +
  10 +public class KeywordAggregation extends AbstractSingleFieldAggregation {
  11 +
  12 + private static final List<String> IGNORE_KEYWORDS = Arrays.asList("正常", "无", "中", "中国");
  13 +
  14 + public KeywordAggregation(int count) {
  15 + super(count);
  16 + }
  17 +
  18 + @Override
  19 + public String aggName() {
  20 + return "keywordAgg";
  21 + }
  22 +
  23 + @Override
  24 + protected String getField() {
  25 + return "productAttrField";
  26 + }
  27 +
  28 + @Override
  29 + public Object getAggregationResponseMap(Map<String, Aggregation> aggMaps) {
  30 + List<String> valueList = (List<String>)super.getAggregationResponseMap(aggMaps);
  31 + if(CollectionUtils.isNotEmpty(valueList)){
  32 + valueList.removeAll(IGNORE_KEYWORDS);
  33 + }
  34 +
  35 + return valueList;
  36 + }
  37 +}
  1 +package com.yoho.search.service.aggregations.impls;
  2 +
  3 +import com.alibaba.fastjson.JSONObject;
  4 +import com.yoho.search.service.servicenew.IShopsService;
  5 +import com.yoho.search.service.utils.SearchRequestParams;
  6 +import com.yoho.search.service.vo.SearchApiResult;
  7 +import org.apache.commons.collections.CollectionUtils;
  8 +import org.elasticsearch.search.aggregations.Aggregation;
  9 +
  10 +import java.util.ArrayList;
  11 +import java.util.HashMap;
  12 +import java.util.List;
  13 +import java.util.Map;
  14 +import java.util.stream.Collectors;
  15 +
  16 +public class ShopAggregation extends AbstractSingleFieldAggregation {
  17 +
  18 + private IShopsService shopsService;
  19 +
  20 + public ShopAggregation(IShopsService shopsService, int count) {
  21 + super(count);
  22 + this.shopsService = shopsService;
  23 + }
  24 +
  25 + @Override
  26 + public String aggName() {
  27 + return "shopAgg";
  28 + }
  29 +
  30 + @Override
  31 + protected String getField() {
  32 + return "shopId";
  33 + }
  34 +
  35 + @Override
  36 + public Object getAggregationResponseMap(Map<String, Aggregation> aggMaps) {
  37 + List<String> shopIdList = (List<String>) super.getAggregationResponseMap(aggMaps);
  38 + if (CollectionUtils.isNotEmpty(shopIdList)) {
  39 + shopIdList = shopIdList.stream().map(Integer::valueOf).filter(shopId -> shopId != null && shopId.intValue() > 0).map(String::valueOf).collect(Collectors.toList());
  40 + }
  41 +
  42 + if (CollectionUtils.isEmpty(shopIdList)) {
  43 + return new ArrayList<>();
  44 + }
  45 +
  46 + // 调用Shops索引查询确保shopId有效
  47 + Map<String, String> shopsParam = new HashMap<>();
  48 + shopsParam.put(SearchRequestParams.PARAM_SEARCH_SHOP, shopIdList.stream().collect(Collectors.joining(",")));
  49 + shopsParam.put(SearchRequestParams.SHOPS_PARAM_STATUS, "1");
  50 + SearchApiResult searchApiResult = shopsService.getShopsInfo(shopsParam);
  51 + if (searchApiResult == null || searchApiResult.getData() == null || searchApiResult.getCode() != 200) {
  52 + return new ArrayList<>();
  53 + }
  54 +
  55 + JSONObject jsonObject = (JSONObject) searchApiResult.getData();
  56 + Map<String, Map<String, Object>> shopsInfo = (Map<String, Map<String, Object>>) jsonObject.get("shopInfo");
  57 + return shopsInfo == null || shopsInfo.isEmpty() ? new ArrayList<>() : shopsInfo.values().stream().collect(Collectors.toList());
  58 + }
  59 +}
@@ -175,4 +175,32 @@ public class ProductIndexController implements ApplicationEventPublisherAware { @@ -175,4 +175,32 @@ public class ProductIndexController implements ApplicationEventPublisherAware {
175 Map<String, String> paramMap = HttpServletRequestUtils.transParamType(request); 175 Map<String, String> paramMap = HttpServletRequestUtils.transParamType(request);
176 return productIndexService.aggSpecialoffer(paramMap); 176 return productIndexService.aggSpecialoffer(paramMap);
177 } 177 }
  178 +
  179 + /**
  180 + * 从商品列表聚合关键词,随机返回关键词
  181 + *
  182 + * @param request
  183 + * @return
  184 + */
  185 + @DownGradeAble(key = "recommendKeyword")
  186 + @RequestMapping(method = RequestMethod.GET, value = "/recommendKeyword")
  187 + @ResponseBody
  188 + public SearchApiResult recommendKeyword(HttpServletRequest request) {
  189 + Map<String, String> paramMap = HttpServletRequestUtils.transParamType(request);
  190 + return productIndexService.aggKeywords(paramMap);
  191 + }
  192 +
  193 + /**
  194 + * 聚合关键词
  195 + *
  196 + * @param request
  197 + * @return
  198 + */
  199 + @DownGradeAble(key = "recommendShop")
  200 + @RequestMapping(method = RequestMethod.GET, value = "/recommendShop")
  201 + @ResponseBody
  202 + public SearchApiResult recommendShop(HttpServletRequest request) {
  203 + Map<String, String> paramMap = HttpServletRequestUtils.transParamType(request);
  204 + return productIndexService.aggShops(paramMap);
  205 + }
178 } 206 }
@@ -40,22 +40,21 @@ public class ToolsController { @@ -40,22 +40,21 @@ public class ToolsController {
40 /** 40 /**
41 * 获取热搜词结果 41 * 获取热搜词结果
42 * 42 *
43 - * @param request  
44 * @return 43 * @return
45 */ 44 */
46 @RequestMapping(method = RequestMethod.GET, value = "/hotSearchWords") 45 @RequestMapping(method = RequestMethod.GET, value = "/hotSearchWords")
47 @ResponseBody 46 @ResponseBody
48 public SearchApiResult hotSearchWords(@RequestParam(defaultValue = "1000") int limit, 47 public SearchApiResult hotSearchWords(@RequestParam(defaultValue = "1000") int limit,
49 @RequestParam(defaultValue = "false") boolean onlyShowKeyWord, 48 @RequestParam(defaultValue = "false") boolean onlyShowKeyWord,
50 - @RequestParam(defaultValue = "true") boolean returnTodayRecords) { 49 + @RequestParam(defaultValue = "") String dateStr) {
51 SearchApiResult searchApiResult = new SearchApiResult(); 50 SearchApiResult searchApiResult = new SearchApiResult();
52 - Map<String, Object> results = searchKeyWordService.getHotkeyWords(limit, onlyShowKeyWord ? false : returnTodayRecords); 51 + Map<String, Object> results = searchKeyWordService.getHotkeyWords(limit, dateStr);
53 if (!onlyShowKeyWord) { 52 if (!onlyShowKeyWord) {
54 return searchApiResult.setData(results); 53 return searchApiResult.setData(results);
55 } 54 }
56 55
57 List<String> keywords = new ArrayList<>(); 56 List<String> keywords = new ArrayList<>();
58 - for (KeyWordWithCount keyWordWithCount : (List<KeyWordWithCount>) results.get("-1")) { 57 + for (KeyWordWithCount keyWordWithCount : (List<KeyWordWithCount>) results.get("keywords")) {
59 keywords.add(keyWordWithCount.getKeyWord()); 58 keywords.add(keyWordWithCount.getKeyWord());
60 } 59 }
61 return searchApiResult.setData(keywords); 60 return searchApiResult.setData(keywords);
@@ -70,15 +69,15 @@ public class ToolsController { @@ -70,15 +69,15 @@ public class ToolsController {
70 @ResponseBody 69 @ResponseBody
71 public SearchApiResult emptyResultKeywords(@RequestParam(defaultValue = "1000") int limit, 70 public SearchApiResult emptyResultKeywords(@RequestParam(defaultValue = "1000") int limit,
72 @RequestParam(defaultValue = "false") boolean onlyShowKeyWord, 71 @RequestParam(defaultValue = "false") boolean onlyShowKeyWord,
73 - @RequestParam(defaultValue = "true") boolean returnTodayRecords) { 72 + @RequestParam(defaultValue = "") String dateStr) {
74 SearchApiResult searchApiResult = new SearchApiResult(); 73 SearchApiResult searchApiResult = new SearchApiResult();
75 - Map<String, Object> results = searchKeyWordService.getEmptyKeyWords(limit, onlyShowKeyWord ? false : returnTodayRecords); 74 + Map<String, Object> results = searchKeyWordService.getEmptyKeyWords(limit, dateStr);
76 if (!onlyShowKeyWord) { 75 if (!onlyShowKeyWord) {
77 return searchApiResult.setData(results); 76 return searchApiResult.setData(results);
78 } 77 }
79 78
80 List<String> keywords = new ArrayList<>(); 79 List<String> keywords = new ArrayList<>();
81 - for (KeyWordWithCount keyWordWithCount : (List<KeyWordWithCount>) results.get("-1")) { 80 + for (KeyWordWithCount keyWordWithCount : (List<KeyWordWithCount>) results.get("keywords")) {
82 keywords.add(keyWordWithCount.getKeyWord()); 81 keywords.add(keyWordWithCount.getKeyWord());
83 } 82 }
84 return searchApiResult.setData(keywords); 83 return searchApiResult.setData(keywords);
@@ -87,22 +86,44 @@ public class ToolsController { @@ -87,22 +86,44 @@ public class ToolsController {
87 /** 86 /**
88 * 获取一页搜索词 87 * 获取一页搜索词
89 * 88 *
90 - * @param request  
91 * @return 89 * @return
92 */ 90 */
93 @RequestMapping(method = RequestMethod.GET, value = "/lessKeyWords") 91 @RequestMapping(method = RequestMethod.GET, value = "/lessKeyWords")
94 @ResponseBody 92 @ResponseBody
95 public SearchApiResult lessKeyWords(@RequestParam(defaultValue = "1000") int limit, 93 public SearchApiResult lessKeyWords(@RequestParam(defaultValue = "1000") int limit,
96 @RequestParam(defaultValue = "false") boolean onlyShowKeyWord, 94 @RequestParam(defaultValue = "false") boolean onlyShowKeyWord,
97 - @RequestParam(defaultValue = "true") boolean returnTodayRecords) { 95 + @RequestParam(defaultValue = "") String dateStr) {
98 SearchApiResult searchApiResult = new SearchApiResult(); 96 SearchApiResult searchApiResult = new SearchApiResult();
99 - Map<String, Object> results = searchKeyWordService.getLessKeyWords(limit, onlyShowKeyWord ? false : returnTodayRecords); 97 + Map<String, Object> results = searchKeyWordService.getLessKeyWords(limit, dateStr);
100 if (!onlyShowKeyWord) { 98 if (!onlyShowKeyWord) {
101 return searchApiResult.setData(results); 99 return searchApiResult.setData(results);
102 } 100 }
103 101
104 List<String> keywords = new ArrayList<>(); 102 List<String> keywords = new ArrayList<>();
105 - for (KeyWordWithCount keyWordWithCount : (List<KeyWordWithCount>) results.get("-1")) { 103 + for (KeyWordWithCount keyWordWithCount : (List<KeyWordWithCount>) results.get("keywords")) {
  104 + keywords.add(keyWordWithCount.getKeyWord());
  105 + }
  106 + return searchApiResult.setData(keywords);
  107 + }
  108 +
  109 + /**
  110 + * 获取需要推荐的关键词
  111 + *
  112 + * @return
  113 + */
  114 + @RequestMapping(method = RequestMethod.GET, value = "/recomKeyWords")
  115 + @ResponseBody
  116 + public SearchApiResult recomKeyWords(@RequestParam(defaultValue = "1000") int limit,
  117 + @RequestParam(defaultValue = "false") boolean onlyShowKeyWord,
  118 + @RequestParam(defaultValue = "") String dateStr) {
  119 + SearchApiResult searchApiResult = new SearchApiResult();
  120 + Map<String, Object> results = searchKeyWordService.getNeedRecomKeyWords(limit, dateStr);
  121 + if (!onlyShowKeyWord) {
  122 + return searchApiResult.setData(results);
  123 + }
  124 +
  125 + List<String> keywords = new ArrayList<>();
  126 + for (KeyWordWithCount keyWordWithCount : (List<KeyWordWithCount>) results.get("keywords")) {
106 keywords.add(keyWordWithCount.getKeyWord()); 127 keywords.add(keyWordWithCount.getKeyWord());
107 } 128 }
108 return searchApiResult.setData(keywords); 129 return searchApiResult.setData(keywords);
@@ -124,7 +145,6 @@ public class ToolsController { @@ -124,7 +145,6 @@ public class ToolsController {
124 /** 145 /**
125 * 获取分词结果 146 * 获取分词结果
126 * 147 *
127 - * @param request  
128 * @return 148 * @return
129 */ 149 */
130 @RequestMapping(method = RequestMethod.GET, value = "/analyzeTokens") 150 @RequestMapping(method = RequestMethod.GET, value = "/analyzeTokens")
@@ -138,7 +158,6 @@ public class ToolsController { @@ -138,7 +158,6 @@ public class ToolsController {
138 /** 158 /**
139 * 清除本地缓存 159 * 清除本地缓存
140 * 160 *
141 - * @param request 请求  
142 * @return 161 * @return
143 */ 162 */
144 @RequestMapping(method = RequestMethod.GET, value = "/clearLocalCache") 163 @RequestMapping(method = RequestMethod.GET, value = "/clearLocalCache")
1 package com.yoho.search.service.service; 1 package com.yoho.search.service.service;
2 2
3 -import java.util.ArrayList;  
4 -import java.util.Arrays;  
5 -import java.util.List;  
6 -import java.util.Map;  
7 - 3 +import com.alibaba.fastjson.JSONObject;
  4 +import com.yoho.error.event.SearchEvent;
  5 +import com.yoho.search.base.utils.EventReportEnum;
  6 +import com.yoho.search.base.utils.ISearchConstants;
  7 +import com.yoho.search.core.es.agg.IAggregation;
  8 +import com.yoho.search.core.es.model.SearchParam;
  9 +import com.yoho.search.core.es.model.SearchResult;
  10 +import com.yoho.search.core.es.utils.IgnoreSomeException;
  11 +import com.yoho.search.service.aggregations.impls.AggregationFactoryService;
  12 +import com.yoho.search.service.service.helper.SearchServiceHelper;
  13 +import com.yoho.search.service.utils.SearchRequestParams;
8 import org.apache.commons.lang.StringUtils; 14 import org.apache.commons.lang.StringUtils;
9 import org.elasticsearch.index.query.BoolQueryBuilder; 15 import org.elasticsearch.index.query.BoolQueryBuilder;
10 import org.elasticsearch.index.query.QueryBuilder; 16 import org.elasticsearch.index.query.QueryBuilder;
@@ -17,17 +23,10 @@ import org.springframework.context.ApplicationEventPublisher; @@ -17,17 +23,10 @@ import org.springframework.context.ApplicationEventPublisher;
17 import org.springframework.context.ApplicationEventPublisherAware; 23 import org.springframework.context.ApplicationEventPublisherAware;
18 import org.springframework.stereotype.Service; 24 import org.springframework.stereotype.Service;
19 25
20 -import com.alibaba.fastjson.JSONObject;  
21 -import com.yoho.error.event.SearchEvent;  
22 -import com.yoho.search.base.utils.EventReportEnum;  
23 -import com.yoho.search.base.utils.ISearchConstants;  
24 -import com.yoho.search.core.es.agg.IAggregation;  
25 -import com.yoho.search.core.es.model.SearchParam;  
26 -import com.yoho.search.core.es.model.SearchResult;  
27 -import com.yoho.search.core.es.utils.IgnoreSomeException;  
28 -import com.yoho.search.service.aggregations.impls.AggregationFactoryService;  
29 -import com.yoho.search.service.service.helper.SearchServiceHelper;  
30 -import com.yoho.search.service.utils.SearchRequestParams; 26 +import java.util.ArrayList;
  27 +import java.util.Arrays;
  28 +import java.util.List;
  29 +import java.util.Map;
31 30
32 @Service 31 @Service
33 public class AggregationService implements ApplicationEventPublisherAware { 32 public class AggregationService implements ApplicationEventPublisherAware {
@@ -324,4 +323,29 @@ public class AggregationService implements ApplicationEventPublisherAware { @@ -324,4 +323,29 @@ public class AggregationService implements ApplicationEventPublisherAware {
324 return this.getAggNameAndResponse(isSecialofferAggregation, searchParam, paramMap, filterParamName); 323 return this.getAggNameAndResponse(isSecialofferAggregation, searchParam, paramMap, filterParamName);
325 } 324 }
326 325
  326 + /**
  327 + * 获取商品关键词的聚合,来源与风格、款式和属性。
  328 + *
  329 + * @param searchParam
  330 + * @param paramMap
  331 + * @return
  332 + * @throws Exception
  333 + */
  334 + public JSONObject getKeywordAggregationResult(SearchParam searchParam, Map<String, String> paramMap, int aggCount) throws Exception {
  335 + IAggregation keywordAggregation = aggregationFactoryService.getKeywordAggregation(aggCount);
  336 + return this.getAggNameAndResponse(keywordAggregation, searchParam, paramMap, null);
  337 + }
  338 +
  339 + /**
  340 + * 获取商品关键词的聚合,来源与风格、款式和属性。
  341 + *
  342 + * @param searchParam
  343 + * @param paramMap
  344 + * @return
  345 + * @throws Exception
  346 + */
  347 + public JSONObject getShopAggregationResult(SearchParam searchParam, Map<String, String> paramMap, int aggCount) throws Exception {
  348 + IAggregation keywordAggregation = aggregationFactoryService.getShopAggregation(aggCount);
  349 + return this.getAggNameAndResponse(keywordAggregation, searchParam, paramMap, null);
  350 + }
327 } 351 }
@@ -22,7 +22,6 @@ import org.springframework.stereotype.Service; @@ -22,7 +22,6 @@ import org.springframework.stereotype.Service;
22 import org.springframework.util.Assert; 22 import org.springframework.util.Assert;
23 23
24 import javax.annotation.Resource; 24 import javax.annotation.Resource;
25 -import java.text.SimpleDateFormat;  
26 import java.util.*; 25 import java.util.*;
27 import java.util.concurrent.ExecutionException; 26 import java.util.concurrent.ExecutionException;
28 import java.util.concurrent.ExecutorService; 27 import java.util.concurrent.ExecutorService;
@@ -40,8 +39,6 @@ public class SearchKeyWordService { @@ -40,8 +39,6 @@ public class SearchKeyWordService {
40 39
41 private static final Logger logger = LoggerFactory.getLogger(SearchKeyWordService.class); 40 private static final Logger logger = LoggerFactory.getLogger(SearchKeyWordService.class);
42 41
43 - private static final Logger EMPTY_RESULT = LoggerFactory.getLogger("EMPTY_RESULT");  
44 -  
45 @Resource(name = "yhNoSyncZSetOperations") 42 @Resource(name = "yhNoSyncZSetOperations")
46 private YHZSetOperations<String, String> yhNoSyncZSetOperations; 43 private YHZSetOperations<String, String> yhNoSyncZSetOperations;
47 44
@@ -118,10 +115,6 @@ public class SearchKeyWordService { @@ -118,10 +115,6 @@ public class SearchKeyWordService {
118 } 115 }
119 } 116 }
120 117
121 - public void recordSuggestTip(String queryWord) {  
122 - recordKeyWord(RedisKeys.YOHO_SEARCH_KEYWORDS_TIPS, queryWord);  
123 - }  
124 -  
125 // 异步的做法是防止redis报错影响搜索主流程 118 // 异步的做法是防止redis报错影响搜索主流程
126 private void recordKeyWord(String redisKeyTemplate, String queryWord) { 119 private void recordKeyWord(String redisKeyTemplate, String queryWord) {
127 service.submit(new Runnable() { 120 service.submit(new Runnable() {
@@ -183,79 +176,61 @@ public class SearchKeyWordService { @@ -183,79 +176,61 @@ public class SearchKeyWordService {
183 } 176 }
184 } 177 }
185 178
186 - public Double getKeywordCount(String redisKeyTemplate, String queryWord){ 179 + public void recordSuggestRecom(String queryWord) {
  180 + recordKeyWord(RedisKeys.YOHO_SEARCH_KEYWORDS_TIPS, queryWord);
  181 + }
  182 +
  183 + public Double getKeywordCount(String redisKeyTemplate, String queryWord) {
187 try { 184 try {
188 return yhNoSyncZSetOperations.score(RedisKeys.getRedisKey4Yesterday(redisKeyTemplate), queryWord); 185 return yhNoSyncZSetOperations.score(RedisKeys.getRedisKey4Yesterday(redisKeyTemplate), queryWord);
189 - }catch (Exception e){ 186 + } catch (Exception e) {
190 return null; 187 return null;
191 } 188 }
192 } 189 }
193 190
194 // 获取【热搜】toplist 191 // 获取【热搜】toplist
195 - public Map<String, Object> getHotkeyWords(int limit, boolean isReturnTodayRecords) {  
196 - return this.getListByScoreDesc(RedisKeys.YOHO_SEARCH_KEYWORDS_HOT, limit, isReturnTodayRecords); 192 + public Map<String, Object> getHotkeyWords(int limit, String dateStr) {
  193 + return this.getListByScoreDesc(RedisKeys.YOHO_SEARCH_KEYWORDS_HOT, limit, dateStr);
197 } 194 }
198 195
199 // 获取空结果的toplist 196 // 获取空结果的toplist
200 - public Map<String, Object> getEmptyKeyWords(int limit, boolean isReturnTodayRecords) {  
201 - return this.getListByScoreDesc(RedisKeys.YOHO_SEARCH_KEYWORDS_EMPTY, limit, isReturnTodayRecords); 197 + public Map<String, Object> getEmptyKeyWords(int limit, String dateStr) {
  198 + return this.getListByScoreDesc(RedisKeys.YOHO_SEARCH_KEYWORDS_EMPTY, limit, dateStr);
202 } 199 }
203 200
204 // 获取只有一页结果的toplist 201 // 获取只有一页结果的toplist
205 - public Map<String, Object> getLessKeyWords(int limit, boolean isReturnTodayRecords) {  
206 - return this.getListByScoreDesc(RedisKeys.YOHO_SEARCH_KEYWORDS_LESS, limit, isReturnTodayRecords); 202 + public Map<String, Object> getLessKeyWords(int limit, String dateStr) {
  203 + return this.getListByScoreDesc(RedisKeys.YOHO_SEARCH_KEYWORDS_LESS, limit, dateStr);
  204 + }
  205 +
  206 + // 获取需要搜索推荐的关键词
  207 + public Map<String, Object> getNeedRecomKeyWords(int limit, String dateStr) {
  208 + return this.getListByScoreDesc(RedisKeys.YOHO_SEARCH_KEYWORDS_TIPS, limit, dateStr);
207 } 209 }
208 210
209 - private Map<String, Object> getListByScoreDesc(String redisKeyTemplate, int limit, boolean isReturnTodayRecords) { 211 + private Map<String, Object> getListByScoreDesc(String redisKeyTemplate, int limit, String dateStr) {
210 Map<String, Object> resultMap = new HashMap<>(3); 212 Map<String, Object> resultMap = new HashMap<>(3);
211 - resultMap.put("dateForRedisKey", dateForRedisKey);  
212 - if (this.dateForRedisKey == null) {  
213 - return resultMap; 213 +
  214 + String date = dateStr;
  215 + if (StringUtils.isEmpty(date)) {
  216 + date = this.dateForRedisKey;
  217 + }
  218 + if (StringUtils.isEmpty(date)) {
  219 + date = DateUtil.DateToString(new Date(), DateStyle.YYYYMMDD);
214 } 220 }
215 221
216 - String redisKey = RedisKeys.getRedisKey4Yesterday(redisKeyTemplate); 222 + String redisKey = String.format(redisKeyTemplate, date);
217 Set<ZSetOperations.TypedTuple<String>> redisResults = yhNoSyncZSetOperations.reverseRangeWithScores(redisKey, 0, limit); 223 Set<ZSetOperations.TypedTuple<String>> redisResults = yhNoSyncZSetOperations.reverseRangeWithScores(redisKey, 0, limit);
218 List<KeyWordWithCount> results = new ArrayList<KeyWordWithCount>(); 224 List<KeyWordWithCount> results = new ArrayList<KeyWordWithCount>();
219 for (TypedTuple<String> typedTuple : redisResults) { 225 for (TypedTuple<String> typedTuple : redisResults) {
220 results.add(new KeyWordWithCount(typedTuple.getValue(), (int) typedTuple.getScore().doubleValue())); 226 results.add(new KeyWordWithCount(typedTuple.getValue(), (int) typedTuple.getScore().doubleValue()));
221 } 227 }
222 228
223 - if (isReturnTodayRecords) {  
224 - // 也返回今天的数据  
225 - String redisKey4Today = RedisKeys.getRedisKey4Today(redisKeyTemplate);  
226 - Set<ZSetOperations.TypedTuple<String>> redisResults4Today = yhNoSyncZSetOperations.reverseRangeWithScores(redisKey4Today, 0, limit);  
227 - List<KeyWordWithCount> results4Today = new ArrayList<KeyWordWithCount>();  
228 - for (TypedTuple<String> typedTuple : redisResults4Today) {  
229 - results4Today.add(new KeyWordWithCount(typedTuple.getValue(), (int) typedTuple.getScore().doubleValue()));  
230 - }  
231 -  
232 - resultMap.put("0", results4Today);  
233 - }  
234 -  
235 resultMap.put("redisKey", redisKey); 229 resultMap.put("redisKey", redisKey);
236 - resultMap.put("-1", results); 230 + resultMap.put("keywords", results);
237 return resultMap; 231 return resultMap;
238 } 232 }
239 233
240 - public void handleEmptyRecords(Map<String, String> paramMap) {  
241 - StringBuilder paramStringBuilder = new StringBuilder();  
242 - for (Map.Entry<String, String> entry : paramMap.entrySet()) {  
243 - paramStringBuilder.append("&").append(entry.getKey()).append("=").append(entry.getValue());  
244 - }  
245 - String paramString = paramStringBuilder.toString().replaceFirst("&", "");  
246 - EMPTY_RESULT.info("empty records for search.json: time[{}], param [{}]", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(System.currentTimeMillis()), paramString);  
247 -  
248 - // 商品池或品类列表 为空,则告警  
249 - if (paramMap.get("filter_poolId") != null) {// ||  
250 - // paramMap.get("msort")!=null  
251 - // ||  
252 - // paramMap.get("misort")!=null  
253 - // ||  
254 - // paramMap.get("sort")!=null  
255 - // /TODO  
256 - }  
257 - }  
258 -  
259 public String deleteRedisKey(String redisKey) { 234 public String deleteRedisKey(String redisKey) {
260 if (yhNoSyncRedisTemplate.hasKey(redisKey)) { 235 if (yhNoSyncRedisTemplate.hasKey(redisKey)) {
261 yhNoSyncRedisTemplate.delete(redisKey); 236 yhNoSyncRedisTemplate.delete(redisKey);
1 package com.yoho.search.service.servicenew; 1 package com.yoho.search.service.servicenew;
2 2
3 -import java.util.Map;  
4 -  
5 import com.yoho.search.service.vo.SearchApiResult; 3 import com.yoho.search.service.vo.SearchApiResult;
6 4
  5 +import java.util.Map;
  6 +
7 public interface IProductIndexService { 7 public interface IProductIndexService {
8 8
9 /** 9 /**
@@ -83,4 +83,13 @@ public interface IProductIndexService { @@ -83,4 +83,13 @@ public interface IProductIndexService {
83 * @return 83 * @return
84 */ 84 */
85 public SearchApiResult aggSpecialoffer(Map<String, String> paramMap); 85 public SearchApiResult aggSpecialoffer(Map<String, String> paramMap);
  86 +
  87 + /**
  88 + * 商品关键词的聚合,来源与风格、款式和属性。
  89 + * @param paramMap
  90 + * @return
  91 + */
  92 + SearchApiResult aggKeywords(Map<String, String> paramMap);
  93 +
  94 + SearchApiResult aggShops(Map<String, String> paramMap);
86 } 95 }
@@ -29,4 +29,6 @@ public interface IShopsService { @@ -29,4 +29,6 @@ public interface IShopsService {
29 * @return 29 * @return
30 */ 30 */
31 public SearchApiResult searchShopsNew(Map<String, String> paramMap); 31 public SearchApiResult searchShopsNew(Map<String, String> paramMap);
  32 +
  33 + SearchApiResult getShopsInfo(Map<String, String> paramMap);
32 } 34 }
1 package com.yoho.search.service.servicenew.impl; 1 package com.yoho.search.service.servicenew.impl;
2 2
3 -import java.util.ArrayList;  
4 -import java.util.List;  
5 -import java.util.Map;  
6 - 3 +import com.alibaba.fastjson.JSONObject;
  4 +import com.yoho.error.event.SearchEvent;
  5 +import com.yoho.search.base.utils.CollectionUtils;
7 import com.yoho.search.base.utils.EventReportEnum; 6 import com.yoho.search.base.utils.EventReportEnum;
8 import com.yoho.search.base.utils.JsonUtil; 7 import com.yoho.search.base.utils.JsonUtil;
  8 +import com.yoho.search.core.es.model.SearchParam;
  9 +import com.yoho.search.core.es.utils.IgnoreSomeException;
9 import com.yoho.search.service.service.AggregationService; 10 import com.yoho.search.service.service.AggregationService;
10 import com.yoho.search.service.service.SearchCommonService; 11 import com.yoho.search.service.service.SearchCommonService;
11 import com.yoho.search.service.service.helper.SearchServiceHelper; 12 import com.yoho.search.service.service.helper.SearchServiceHelper;
12 import com.yoho.search.service.servicenew.IProductIndexService; 13 import com.yoho.search.service.servicenew.IProductIndexService;
13 -import com.yoho.search.core.es.utils.IgnoreSomeException;  
14 import com.yoho.search.service.vo.SearchApiResult; 14 import com.yoho.search.service.vo.SearchApiResult;
15 -  
16 import org.apache.commons.lang.StringUtils; 15 import org.apache.commons.lang.StringUtils;
17 import org.slf4j.Logger; 16 import org.slf4j.Logger;
18 import org.slf4j.LoggerFactory; 17 import org.slf4j.LoggerFactory;
@@ -21,9 +20,11 @@ import org.springframework.context.ApplicationEventPublisher; @@ -21,9 +20,11 @@ import org.springframework.context.ApplicationEventPublisher;
21 import org.springframework.context.ApplicationEventPublisherAware; 20 import org.springframework.context.ApplicationEventPublisherAware;
22 import org.springframework.stereotype.Service; 21 import org.springframework.stereotype.Service;
23 22
24 -import com.alibaba.fastjson.JSONObject;  
25 -import com.yoho.error.event.SearchEvent;  
26 -import com.yoho.search.core.es.model.SearchParam; 23 +import java.util.ArrayList;
  24 +import java.util.List;
  25 +import java.util.Map;
  26 +import java.util.Random;
  27 +import java.util.stream.Collectors;
27 28
28 @Service 29 @Service
29 public class ProductIndexServiceImpl implements IProductIndexService,ApplicationEventPublisherAware { 30 public class ProductIndexServiceImpl implements IProductIndexService,ApplicationEventPublisherAware {
@@ -245,4 +246,45 @@ public class ProductIndexServiceImpl implements IProductIndexService,Application @@ -245,4 +246,45 @@ public class ProductIndexServiceImpl implements IProductIndexService,Application
245 } 246 }
246 }); 247 });
247 } 248 }
  249 +
  250 + @Override
  251 + public SearchApiResult aggKeywords(Map<String, String> paramMap) {
  252 + final int randomKeywordCount = StringUtils.isBlank(paramMap.get("keyword_count")) ? 8 : Integer.parseInt(paramMap.get("keyword_count"));
  253 + return this.getSearchApiResult("aggKeywords", paramMap, new Searcher() {
  254 + @Override
  255 + public Object getResult() throws Exception {
  256 + SearchParam searchParam = getSearchParamFromMap(paramMap);
  257 + JSONObject jsonObject = aggregationService.getKeywordAggregationResult(searchParam, paramMap, 50);
  258 + List<String> keywordList = (List<String>) jsonObject.get("keywordAgg");
  259 + return getRandomKeywords(keywordList, randomKeywordCount);
  260 + }
  261 + });
  262 + }
  263 +
  264 + private List<String> getRandomKeywords(List<String> keywordList, int randomKeywordCount) {
  265 + if (keywordList == null || keywordList.size() <= randomKeywordCount) {
  266 + return keywordList;
  267 + }
  268 +
  269 + return new Random().ints(0, keywordList.size())
  270 + .distinct()
  271 + .limit(randomKeywordCount)
  272 + .mapToObj(index -> keywordList.get(index))
  273 + .collect(Collectors.toList());
  274 + }
  275 +
  276 + @Override
  277 + public SearchApiResult aggShops(Map<String, String> paramMap) {
  278 + final int page = StringUtils.isBlank(paramMap.get("shop_page")) ? 1 : Integer.parseInt(paramMap.get("shop_page"));
  279 + final int count = StringUtils.isBlank(paramMap.get("shop_count")) ? 1 : Integer.parseInt(paramMap.get("shop_count"));
  280 + return this.getSearchApiResult("aggShops", paramMap, new Searcher() {
  281 + @Override
  282 + public Object getResult() throws Exception {
  283 + SearchParam searchParam = getSearchParamFromMap(paramMap);
  284 + JSONObject jsonObject = aggregationService.getShopAggregationResult(searchParam, paramMap, 30);
  285 + List<Map<String, Object>> shopList = (List<Map<String, Object>>) jsonObject.get("shopAgg");
  286 + return CollectionUtils.memoryPaging(shopList, page, count);
  287 + }
  288 + });
  289 + }
248 } 290 }
@@ -145,6 +145,8 @@ public class SearchRecommendServiceImpl implements ISearchRecommendService { @@ -145,6 +145,8 @@ public class SearchRecommendServiceImpl implements ISearchRecommendService {
145 } catch (Exception e) { 145 } catch (Exception e) {
146 logger.error("[func=recommend][queryWord=" + queryWord + "]", e); 146 logger.error("[func=recommend][queryWord=" + queryWord + "]", e);
147 return defaultSuggestRecommendation(); 147 return defaultSuggestRecommendation();
  148 + } finally {
  149 + searchKeyWordService.recordSuggestRecom(queryWord);
148 } 150 }
149 } 151 }
150 152
@@ -493,7 +493,7 @@ public class ShopsServiceImpl extends BaseService implements IShopsService, Appl @@ -493,7 +493,7 @@ public class ShopsServiceImpl extends BaseService implements IShopsService, Appl
493 * @param paramMap 493 * @param paramMap
494 * @return 494 * @return
495 */ 495 */
496 - private SearchApiResult getShopsInfo(Map<String, String> paramMap) { 496 + public SearchApiResult getShopsInfo(Map<String, String> paramMap) {
497 try { 497 try {
498 logger.info("[func=getShopsInfo][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis()); 498 logger.info("[func=getShopsInfo][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
499 // 1、构建SearchParam 499 // 1、构建SearchParam
@@ -271,7 +271,12 @@ public class SuggestServiceImpl implements ISuggestService, ApplicationEventPubl @@ -271,7 +271,12 @@ public class SuggestServiceImpl implements ISuggestService, ApplicationEventPubl
271 if (StringUtils.isNotEmpty(queryWord)) { 271 if (StringUtils.isNotEmpty(queryWord)) {
272 // 是否精确匹配 272 // 是否精确匹配
273 String accurateQuery = paramMap.get("accurate"); 273 String accurateQuery = paramMap.get("accurate");
274 - queryBuilder = "Y".equalsIgnoreCase(accurateQuery) ? QueryBuilders.matchQuery("standardKeyword", CharUtils.standardized(queryWord)) : QueryBuilders.matchQuery("keyword.keyword_ik", queryWord); 274 + if ("Y".equalsIgnoreCase(accurateQuery)) {
  275 + queryBuilder = QueryBuilders.matchQuery("standardKeyword", CharUtils.standardized(queryWord));
  276 + } else {
  277 + queryBuilder = QueryBuilders.multiMatchQuery(queryWord.trim().toLowerCase(), "keyword", "keyword.keyword_lowercase",
  278 + "keyword.keyword_pinyin", "keyword.keyword_jianpin", "keyword.keyword_ik");
  279 + }
275 } 280 }
276 281
277 searchParam.setQuery(queryBuilder); 282 searchParam.setQuery(queryBuilder);