FuzzySceneService.java 6.35 KB
package com.yoho.search.service.scene;

import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import com.yoho.search.service.list.FuzzySceneProductListService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.yoho.search.base.utils.SearchPageIdDefine;
import com.yoho.search.common.utils.SearchApiResultUtils;
import com.yoho.search.models.SearchApiResult;
import com.yoho.search.service.base.SearchDynamicConfigService;
import com.yoho.search.service.base.SearchRequestParams;
import com.yoho.search.service.helper.SearchCommonHelper;
import com.yoho.search.service.helper.SearchKeyWordHelper;
import com.yoho.search.service.scene.aggregations.SceneAggregationsHelper;
import com.yoho.search.service.scene.common.AbstractSceneService;
import com.yoho.search.service.scene.common.SceneSelectionsService;
import com.yoho.search.service.service.ISearchRecommendService;

@Service
public class FuzzySceneService extends AbstractSceneService {

	private static final Logger logger = LoggerFactory.getLogger(FuzzySceneService.class);

	@Autowired
	private SceneSelectionsService sceneSelectionsService;
	@Autowired
	private SearchCommonHelper searchCommonHelper;
	@Autowired
	private ISearchRecommendService searchRecommendService;
	@Autowired
	private SearchDynamicConfigService searchDynamicConfigService;
	@Autowired
	private SearchKeyWordHelper searchKeyWordService;
	@Autowired
	private SceneAggregationsHelper sceneAggregationsHelper;
	@Autowired
	private FuzzySceneProductListService fuzzySceneProductListService;

	private ExecutorService executor = Executors.newFixedThreadPool(100);

	// 当少于20个商品时 返回智能搜索词提示
	private static final int SMART_SUGGESTION_PRODUCT_LIMIT = 20;

	@Override
	public String pageId() {
		return SearchPageIdDefine.PAGE_ID_SEARCH;
	}

	@Override
	public void addParamsToParamMap(Map<String, String> paramMap) {
		super.addDefaultParamsToParamMap(paramMap);
		paramMap.put(SearchRequestParams.PARAM_SEARCH_NEED_SUGGESTION, "Y");// 返回建议词
		paramMap.put(SearchRequestParams.PARAM_SEARCH_CONTAIN_SECKILL, "Y");// 包含秒杀商品
		paramMap.put(SearchRequestParams.PARAM_SEARCH_CONTAIN_GLOBAL, "Y");// 包含全球购
	}

	/**
	 * @1、返回商品列表
	 * @2、数量太多则返回建议词
	 */
	@Override
	public SearchApiResult productList(Map<String, String> paramMap) {
		try {
			// 1、参数校验
			if (StringUtils.isBlank(paramMap.get(SearchRequestParams.PARAM_SEARCH_QUERY))) {
				return new SearchApiResult().setCode(400).setMessage("请传query参数");
			}
			// 2、添加默认参数
			this.addParamsToParamMap(paramMap);
			// 3、获取商品列表
			CompletableFuture<SearchApiResult> productListuture = CompletableFuture.supplyAsync(() -> fuzzySceneProductListService.productList(this.newParamMap(paramMap)), executor);
			// 4、获取自定义标签聚合结果
			CompletableFuture<SearchApiResult> customizeTagFuture = CompletableFuture.supplyAsync(() -> sceneAggregationsHelper.sceneAggCustomizeTag(this.newParamMap(paramMap)), executor);
			// 5、获取促销专题
			CompletableFuture<SearchApiResult> promotionsFuture = CompletableFuture.supplyAsync(() -> sceneAggregationsHelper.sceneAggPromotion(this.newParamMap(paramMap)),
					executor);

			// 6、加入建议词
			SearchApiResult productListResult = productListuture.get();
			this.addSuggestion(productListResult, paramMap);

			// 7、模糊搜索页记录关键字对应的查询结果
			String queryWord = paramMap.get("query");
			if (!StringUtils.isBlank(queryWord) && !searchCommonHelper.isQuerySknOrSku(queryWord)) {
				long total = ((JSONObject) productListResult.getData()).getLongValue("total");
				searchKeyWordService.recordKeyWordByResultCount(queryWord, total);
			}
			// 8、组合结果
			SearchApiResult customizeTags = customizeTagFuture.get();
			SearchApiResult promotions = promotionsFuture.get();
			JSONObject dataMap = (JSONObject) productListResult.getData();
			dataMap.put(CUSTOMIZE_TAG_LIST, customizeTags.getData());
			dataMap.put(RECOMMEND_PROMOTION_LIST, sceneAggregationsHelper.subRecommendPromotions(promotions.getData(),this.getPage(paramMap),1));
			return productListResult;
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			return SearchApiResultUtils.errorSearchApiResult("fuzzyProductList", paramMap, e);
		}
	}

	@Override
	public SearchApiResult aggregations(Map<String, String> paramMap) {
		try {
			// 0、参数校验
			if (StringUtils.isBlank(paramMap.get(SearchRequestParams.PARAM_SEARCH_QUERY))) {
				return new SearchApiResult().setCode(400).setMessage("请传query参数");
			}
			// 1、添加默认参数
			this.addParamsToParamMap(paramMap);
			// 2、返回聚合结果
			return sceneSelectionsService.aggregations(paramMap);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			return new SearchApiResult().setData(null).setMessage("FuzzyAggregations Exception").setCode(500);
		}
	}

	/**
	 * 获取模糊搜索的推荐词
	 * 
	 * @param paramMap
	 * @return
	 */
	private void addSuggestion(SearchApiResult searchResult, Map<String, String> paramMap) {
		if (searchResult == null || searchResult.getCode() != 200 || searchResult.getData() == null) {
			return;
		}
		// 1. 判断是否需要进行term推荐
		// 1.1 query不为空
		String queryWord = paramMap.get(SearchRequestParams.PARAM_SEARCH_QUERY);
		if (StringUtils.isEmpty(queryWord) || (queryWord.length() > 30 && !searchCommonHelper.isQuerySknOrSku(queryWord))) {
			return;
		}
		// 1.2不是第一页直接不返回
		int page = this.getPage(paramMap);
		if (page != 1) {
			return;
		}
		// 1.3请求制定需要返回term推荐
		if (!"Y".equalsIgnoreCase(paramMap.get(SearchRequestParams.PARAM_SEARCH_NEED_SUGGESTION))) {
			return;
		}

		// 1.4打开智能推荐全局开关
		if (!searchDynamicConfigService.isSearchSuggestionTipsOpen()) {
			return;
		}

		// 1.5 搜索的数量小于20条
		JSONObject dataMap = ((JSONObject) searchResult.getData());
		if (dataMap.getIntValue("total") >= SMART_SUGGESTION_PRODUCT_LIMIT) {
			return;
		}

		// 1.6加入推荐词
		dataMap.put("suggestion", searchRecommendService.recommend(searchResult, paramMap));
	}

}