Authored by hugufei

类重命名

package com.yoho.search.recall.scene;
import com.alibaba.fastjson.JSONObject;
import com.yoho.search.base.utils.CollectionUtils;
import com.yoho.search.base.utils.ISearchConstants;
import com.yoho.search.base.utils.ProductIndexEsField;
import com.yoho.search.core.es.model.SearchParam;
import com.yoho.search.core.es.model.SearchResult;
import com.yoho.search.models.SearchApiResult;
import com.yoho.search.recall.scene.beans.cache.QueryRecallResultCacheBean;
import com.yoho.search.recall.scene.beans.cache.QueryProductInfoCacheBean;
import com.yoho.search.recall.scene.beans.helper.SortBuilderHelper;
import com.yoho.search.recall.scene.models.*;
import com.yoho.search.recall.scene.beans.builder.RecallParamsBuilder;
import com.yoho.search.recall.scene.models.RecallParams;
import com.yoho.search.service.base.SearchCommonService;
import com.yoho.search.service.helper.SearchCommonHelper;
import org.apache.commons.collections.MapUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.SortBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@Component
public class SceneRecallService {
private static final Logger logger = LoggerFactory.getLogger(SceneRecallService.class);
@Autowired
private RecallParamsBuilder recallParamsBuilder;
@Autowired
private SearchCommonHelper searchCommonHelper;
@Autowired
private SearchCommonService searchCommonService;
@Autowired
private QueryRecallResultCacheBean queryRecallResultCacheBean;
@Autowired
private QueryProductInfoCacheBean queryProductInfoCacheBean;
public SearchApiResult sceneRecall(Map<String, String> paramMap) {
try {
//1、分页参数验证
int page = MapUtils.getIntValue(paramMap, "page", 1);
int pageSize = MapUtils.getIntValue(paramMap, "viewNum", 20);
if (page < 1 || pageSize < 0 || page * pageSize > 1000000) {
return new SearchApiResult().setCode(400).setMessage("分页参数不合法");
}
//2、构造召回相关参数
RecallParams recallParams = recallParamsBuilder.buildRecallParams(paramMap,pageSize);
//3、执行召回
RecallResult recallResult = queryRecallResultCacheBean.queryRecallResult(recallParams);
//4、根据召回结果查询商品信息
List<Map<String, Object>> productList = this.queryProductList(recallParams, recallResult,page,pageSize);
//5、构造返回结果
JSONObject dataMap = new JSONObject();
dataMap.put("total", recallResult.getTotal());
dataMap.put("page", page);
dataMap.put("page_size", recallParams.getPageSize());
dataMap.put("page_total", searchCommonHelper.getTotalPage(recallResult.getTotal(), recallParams.getPageSize()));
dataMap.put("product_list", productList);
return new SearchApiResult().setData(dataMap);
} catch (Exception e) {
logger.error(e.getMessage(), e);
return new SearchApiResult().setData(null).setCode(500).setMessage("Exception");
}
}
private List<Map<String, Object>> queryProductList(RecallParams recallParams, RecallResult recallResult, int page, int pageSize) {
//1、判断当前页码是否在召回的页码里
int recallTotalPage = recallResult.getRecallTotalPage();
//2、在召回结果中则直接根据skn去查询
List<Integer> productSkns = null;
if(page<=recallTotalPage){
productSkns = CollectionUtils.safeSubList(recallResult.getSknList(),(page-1)*pageSize,page*pageSize);
}else{
//3、过滤召回的skn,修改真实页码,执行查询
productSkns = this.queryProductSknByFilterSkn(recallParams, recallResult.getSknList(), recallTotalPage-page, pageSize);
}
return queryProductInfoCacheBean.queryProductListBySkn(productSkns,productSkns.size());
}
/**
* 过滤掉已召回的skn,并按人气排序
* @param notProductSkns
* @param realPage
* @param pageSize
* @return
*/
private List<Integer> queryProductSknByFilterSkn(RecallParams recallParams, List<Integer> notProductSkns, int realPage, int pageSize){
SearchParam searchParam = new SearchParam();
//1、设置query
searchParam.setQuery(recallParams.getParamQueryFilter().getParamQuery());
//2、设置filter
BoolQueryBuilder filter = recallParams.getParamQueryFilter().getParamFilter();
filter.mustNot(QueryBuilders.termsQuery(ProductIndexEsField.productSkn,notProductSkns));
searchParam.setFiter(filter);
//3、设置分页参数
searchParam.setOffset((realPage-1)*pageSize);
searchParam.setSize(pageSize);
//4、设置IncludeFields
searchParam.setIncludeFields(Arrays.asList(ProductIndexEsField.productSkn));
//5、设置排序
List<SortBuilder<?>> sortBuilders = new ArrayList<>();
sortBuilders.add(SortBuilderHelper.getSevendayMoneyDescSort());
sortBuilders.add(SortBuilderHelper.getIdDescSort());
searchParam.setSortBuilders(sortBuilders);
SearchResult searchResult = searchCommonService.doSearch(ISearchConstants.INDEX_NAME_PRODUCT_BASE_INDEX,searchParam);
List<Integer> results = new ArrayList<>();
for (Map<String, Object> product : searchResult.getResultList()) {
results.add(MapUtils.getIntValue(product,ProductIndexEsField.productSkn,0));
}
return results;
}
}
package com.yoho.search.service.scene;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
import org.elasticsearch.search.aggregations.Aggregation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yoho.search.base.utils.ConvertUtils;
import com.yoho.search.base.utils.ISearchConstants;
import com.yoho.search.base.utils.ProductIndexEsField;
import com.yoho.search.common.cache.SearchCacheMatchLogger;
import com.yoho.search.common.cache.model.SearchCache;
import com.yoho.search.core.es.agg.IAggregation;
import com.yoho.search.core.es.model.SearchParam;
import com.yoho.search.core.es.model.SearchResult;
import com.yoho.search.models.PromotionConditions;
import com.yoho.search.models.PromotionParam;
import com.yoho.search.models.SearchApiResult;
import com.yoho.search.service.aggregations.impls.AggregationFactoryService;
import com.yoho.search.service.base.SearchCommonService;
import com.yoho.search.service.base.index.ProductIndexBaseService;
import com.yoho.search.service.helper.SearchAfterCacheHelper;
import com.yoho.search.service.helper.SearchParamHelper;
import com.yoho.search.service.helper.SearchSortHelper;
import com.yoho.search.service.scene.common.AbstractCacheAbleService;
import com.yoho.search.service.scene.common.SceneSelectionsService;
import com.yoho.search.service.service.IBrandService;
import com.yoho.search.service.service.IDiscountService;
import com.yoho.search.service.service.ISearchSortGroupService;
import com.yoho.search.service.service.ISelectionsForApp;
import com.yoho.search.service.service.ISelectionsForPc;
@Service
public class PromotionSceneService extends AbstractCacheAbleService {
private static Logger logger = LoggerFactory.getLogger(PromotionSceneService.class);
@Autowired
private SearchSortHelper searchSortHelper;
@Autowired
private SearchCommonService searchCommonService;
@Autowired
private AggregationFactoryService aggregationFactoryService;
@Autowired
private ISelectionsForApp selectionsWithOutAdvanceService;
@Autowired
private SearchAfterCacheHelper searchAfterCacheService;
@Autowired
private ISelectionsForPc selectionsForPc;
@Autowired
private IBrandService brandService;
@Autowired
private ISearchSortGroupService searchSortGroupService;
@Autowired
private IDiscountService discountService;
@Autowired
private ProductIndexBaseService productIndexBaseService;
@Autowired
private SearchParamHelper searchParamHelper;
@Autowired
private SceneSelectionsService sceneSelectionsService;
@Override
public SearchCache getSearchCache() {
return searchCacheFactory.getPromotionSearchCache();
}
private BoolQueryBuilder genConditionFilter(PromotionParam param, boolean isAnd) {
BoolQueryBuilder conditionFilter = QueryBuilders.boolQuery();
// 判断品牌
if (StringUtils.isNotBlank(param.getBrand())) {
int[] brandids = ConvertUtils.stringToIntArray(param.getBrand(), ",");
BoolQueryBuilder brandFilter = QueryBuilders.boolQuery().must(QueryBuilders.termsQuery(ProductIndexEsField.brandId, brandids));
if (isAnd) {
conditionFilter.must(brandFilter);
} else {
conditionFilter.should(brandFilter);
}
}
// 判断不包含品牌
if (StringUtils.isNotBlank(param.getNotBrandId())) {
int[] notBrandids = ConvertUtils.stringToIntArray(param.getNotBrandId(), ",");
BoolQueryBuilder notBrandFilter = QueryBuilders.boolQuery();
notBrandFilter.mustNot(QueryBuilders.termsQuery(ProductIndexEsField.brandId, notBrandids));
if (isAnd) {
conditionFilter.must(notBrandFilter);
} else {
conditionFilter.should(notBrandFilter);
}
}
// 判断品类
if (StringUtils.isNotBlank(param.getSort())) {
int[] sortIds = ConvertUtils.stringToIntArray(param.getSort(), ",");
BoolQueryBuilder sortFilter = QueryBuilders.boolQuery();
sortFilter.should(QueryBuilders.termsQuery(ProductIndexEsField.maxSortId, sortIds));
sortFilter.should(QueryBuilders.termsQuery(ProductIndexEsField.middleSortId, sortIds));
sortFilter.should(QueryBuilders.termsQuery(ProductIndexEsField.smallSortId, sortIds));
if (isAnd) {
conditionFilter.must(QueryBuilders.boolQuery().must(sortFilter));
} else {
conditionFilter.should(QueryBuilders.boolQuery().must(sortFilter));
}
}
// 判断非品类
if (StringUtils.isNotBlank(param.getNotSort())) {
int[] notSortIds = ConvertUtils.stringToIntArray(param.getNotSort(), ",");
BoolQueryBuilder notSortFilter = QueryBuilders.boolQuery();
notSortFilter.mustNot(QueryBuilders.termsQuery(ProductIndexEsField.maxSortId, notSortIds));
notSortFilter.mustNot(QueryBuilders.termsQuery(ProductIndexEsField.middleSortId, notSortIds));
notSortFilter.mustNot(QueryBuilders.termsQuery(ProductIndexEsField.smallSortId, notSortIds));
if (isAnd) {
conditionFilter.must(notSortFilter);
} else {
conditionFilter.should(notSortFilter);
}
}
// 判断promotion
if (StringUtils.isNotBlank(param.getPromotion())) {
int[] promotionIds = ConvertUtils.stringToIntArray(param.getPromotion(), ",");
BoolQueryBuilder promotionFilter = QueryBuilders.boolQuery();
promotionFilter.must(QueryBuilders.termsQuery(ProductIndexEsField.ispromotion, promotionIds));
if (isAnd) {
conditionFilter.must(promotionFilter);
} else {
conditionFilter.should(promotionFilter);
}
}
// 判断非promotion
if (StringUtils.isNotBlank(param.getNotPromotion())) {
int[] notPromotionIds = ConvertUtils.stringToIntArray(param.getNotPromotion(), ",");
BoolQueryBuilder notPromotionFilter = QueryBuilders.boolQuery();
notPromotionFilter.mustNot(QueryBuilders.termsQuery(ProductIndexEsField.ispromotion, notPromotionIds));
if (isAnd) {
conditionFilter.must(notPromotionFilter);
} else {
conditionFilter.should(notPromotionFilter);
}
}
// 判断skn
if (StringUtils.isNotBlank(param.getProductSknStr())) {
BoolQueryBuilder sknFilter = QueryBuilders.boolQuery();
sknFilter.must(QueryBuilders.termsQuery(ProductIndexEsField.productSkn, param.getProductSknStr().split(",")));
if (isAnd) {
conditionFilter.must(sknFilter);
} else {
conditionFilter.should(sknFilter);
}
}
// 判断 非skn
if (StringUtils.isNotBlank(param.getNotProductSkn())) {
BoolQueryBuilder sknFilter = QueryBuilders.boolQuery();
sknFilter.mustNot(QueryBuilders.termsQuery(ProductIndexEsField.productSkn, param.getNotProductSkn().split(",")));
if (isAnd) {
conditionFilter.must(sknFilter);
} else {
conditionFilter.should(sknFilter);
}
}
return conditionFilter;
}
/**
* 根据促销列表参数生成过滤条件
*
* @return
*/
public BoolQueryBuilder getMustFilterByPromotion(PromotionConditions promotionConditions) {
if (promotionConditions == null) {
return null;
}
// 生成每种condition的filter列表
List<BoolQueryBuilder> conditionsFilter = new ArrayList<BoolQueryBuilder>();
List<PromotionParam> promotionParams = promotionConditions.getPromotionParams();
for (PromotionParam promotionParam : promotionParams) {
boolean isAnd = "any".equals(promotionParam.getAggregator()) ? false : true;
BoolQueryBuilder conditionFilter = this.genConditionFilter(promotionParam, isAnd);
conditionsFilter.add(conditionFilter);
}
// 处理总结果
String aggregator = promotionConditions.getAggregator();
boolean isTotalAnd = "any".equals(aggregator) ? false : true;
BoolQueryBuilder allBuilder = QueryBuilders.boolQuery();
for (BoolQueryBuilder conditionFilter : conditionsFilter) {
if (isTotalAnd) {
allBuilder.must(conditionFilter);
} else {
allBuilder.should(conditionFilter);
}
}
return allBuilder;
}
public SearchApiResult list(PromotionConditions promotionConditions, Map<String, String> paramMap) throws Exception {
// 1、获取mustFilterByPromotion
BoolQueryBuilder mustFilterByPromotion = this.getMustFilterByPromotion(promotionConditions);
// 2、构造带filter和Query的SearchParam
SearchParam searchParam = searchParamHelper.buildWithPersional(paramMap, true, mustFilterByPromotion);
// 3、设置聚合条件
searchParam.setAggregationBuilders(null);
// 4、设置分页参数
int pageSize = StringUtils.isBlank(paramMap.get("viewNum")) ? 10 : Integer.parseInt(paramMap.get("viewNum"));
int page = StringUtils.isBlank(paramMap.get("page")) ? 1 : Integer.parseInt(paramMap.get("page"));
if (page < 1 || pageSize < 0) {
throw new IllegalArgumentException("分页参数不合法");
}
if (pageSize > 100) {
pageSize = 100;
}
searchParam.setOffset((page - 1) * pageSize);
searchParam.setSize(pageSize);
// 5)设置排序字段
searchParam.setSortBuilders(searchSortHelper.buildSortList(paramMap));
// 6)从缓存中获取数据
final String productIndexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
JSONObject cacheObject = searchCacheService.getJSONObjectFromCache(this.searchCache, productIndexName, searchParam);
if (cacheObject != null) {
SearchCacheMatchLogger.doSearchCacheMatchLog("/promotion/list.json", paramMap);
return new SearchApiResult().setData(cacheObject);
}
// 7)查询ES
SearchResult searchResult = searchCommonService.doSearch(productIndexName, searchParam);
if (searchResult == null) {
return new SearchApiResult().setCode(500).setMessage("execption");
}
// 8)构造返回结果
JSONObject dataMap = new JSONObject();
dataMap.put("total", searchResult.getTotal());
dataMap.put("page", searchResult.getPage());
dataMap.put("page_size", searchParam.getSize());
dataMap.put("page_total", searchResult.getTotalPage());
dataMap.put("product_list", productIndexBaseService.getProductListWithPricePlan(searchResult.getResultList()));
// 10)将结果存进缓存
searchCacheService.addJSONObjectToCache(this.searchCache, productIndexName, searchParam, dataMap);
return new SearchApiResult().setData(dataMap);
}
public SearchApiResult selectionsForApp(PromotionConditions promotionConditions, Map<String, String> paramMap) throws Exception {
// 1、获取mustFilterByPromotion
BoolQueryBuilder mustFilterByPromotion = this.getMustFilterByPromotion(promotionConditions);
// 2、构造带filter和Query的SearchParam
SearchParam searchParam = searchParamHelper.buildWithMustFilter(paramMap, mustFilterByPromotion);
// 3、构造聚合条件【7种】
List<AbstractAggregationBuilder<?>> aggregationBuilders = new ArrayList<AbstractAggregationBuilder<?>>();
searchParam.setAggregationBuilders(aggregationBuilders);
// 3.1获取通用的聚合场景
aggregationBuilders.addAll(selectionsWithOutAdvanceService.getAllAggregationBuilders(paramMap));
// 3.2加上折扣聚合场景
IAggregation discountAggregation = aggregationFactoryService.getDiscountAggregation();
aggregationBuilders.add(discountAggregation.getBuilder());
// 3.3加上品类聚合场景
IAggregation sortGroupAggregation = aggregationFactoryService.getSortGroupAggregation(paramMap);
aggregationBuilders.add(sortGroupAggregation.getBuilder());
// 4、设置分页参数
searchParam.setOffset(0);
searchParam.setSize(0);
final String productIndexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
// 5、从缓存中取
JSONObject cacheObject = searchCacheService.getJSONObjectFromCache(this.searchCache, productIndexName, searchParam);
if (cacheObject != null) {
Object newCacheObject = searchAfterCacheService.dealFilterCacheObject(cacheObject);
newCacheObject = searchAfterCacheService.dealDiscountCacheObject((JSONObject) newCacheObject);
SearchCacheMatchLogger.doSearchCacheMatchLog("/promotion/selections.json", paramMap);
return new SearchApiResult().setData(newCacheObject);
}
// 6)查询ES
SearchResult searchResult = searchCommonService.doSearch(productIndexName, searchParam);
if (searchResult == null) {
return new SearchApiResult().setCode(500).setMessage("execption");
}
// 7)构造并返回聚合结果
Map<String, Aggregation> aggMaps = searchResult.getAggMaps();
if (aggMaps == null) {
return null;
}
// 8)先拿通用的聚合结果
Map<String, Object> commonAggResult = selectionsWithOutAdvanceService.getAggResultMap(paramMap, aggMaps);
// 9)获取折扣的聚合结果
Object discountAggResult = discountAggregation.getAggregationResponseMap(aggMaps);
// 10)获取品类的聚合结果
Object sortGroupAggResult = sortGroupAggregation.getAggregationResponseMap(aggMaps);
// 11)构造返回对象
JSONObject result = new JSONObject();
result.put("filter", commonAggResult);
result.put("discount", discountAggResult);
result.put("sort", sortGroupAggResult);
// 12)将结果加入缓存
searchCacheService.addJSONObjectToCache(this.searchCache, productIndexName, searchParam, result);
return new SearchApiResult().setData(result);
}
public SearchApiResult selectionsForPc(PromotionConditions promotionConditions, Map<String, String> paramMap) throws Exception {
// 1、获取默认的mustFilterByPromotion
BoolQueryBuilder mustFilterByPromotion = this.getMustFilterByPromotion(promotionConditions);
// 2、调通用的PC聚合逻辑
SearchApiResult apiResult = selectionsForPc.getSelectionsForPc(paramMap, mustFilterByPromotion);
if (apiResult == null || apiResult.getData() == null) {
return apiResult;
}
JSONObject result = (JSONObject) apiResult.getData();
// 3、加入品类聚合结果
JSONArray jsonArray = searchSortGroupService.sortGroup(paramMap, mustFilterByPromotion);
result.put("sort", jsonArray);
// 4、加入折扣聚合结果
JSONObject discount = discountService.discount(paramMap, mustFilterByPromotion);
result.put("dicount", discount);
return new SearchApiResult().setData(result);
}
public SearchApiResult aggPromotionBrands(PromotionConditions promotionConditions, Map<String, String> paramMap) throws Exception {
logger.info("[func=aggPromotionBrands][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
// 1、设置必须满足的过滤条件
BoolQueryBuilder mustFilterByPromotion = this.getMustFilterByPromotion(promotionConditions);
// 2、调聚合品牌的方法
SearchApiResult searchApiResult = brandService.aggBrand(paramMap, mustFilterByPromotion);
return searchApiResult;
}
/**
* 促销列表新版筛选项
*
* @param promotionConditions
* @param paramMap
* @return
*/
public SearchApiResult aggregations(PromotionConditions promotionConditions, Map<String, String> paramMap) {
try {
// 0、解析promotion的限制条件
BoolQueryBuilder mustFilter = this.getMustFilterByPromotion(promotionConditions);
return sceneSelectionsService.aggregations(paramMap, mustFilter);
} catch (Exception e) {
logger.error(e.getMessage(), e);
return new SearchApiResult().setData(null).setMessage("PromotionAggregations Exception").setCode(500);
}
}
}