Authored by hugufei

Merge branch 'cache_fix' into brandproduct

... ... @@ -2,10 +2,13 @@ package com.yoho.search.cache.beans;
import com.alibaba.fastjson.JSON;
import com.yoho.core.redis.cluster.operations.serializer.RedisKeyBuilder;
import com.yoho.search.base.utils.MD5Util;
import com.yoho.search.cache.impls.EhCache;
import com.yoho.search.cache.impls.SearchRedis;
import com.yoho.search.cache.model.CacheObject;
import com.yoho.search.service.recall.models.common.ParamQueryFilter;
import com.yoho.search.core.es.model.SearchParam;
import com.yoho.search.core.es.utils.SearchParamUtils;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import java.lang.reflect.ParameterizedType;
... ... @@ -19,9 +22,9 @@ public abstract class AbstractCacheComponent<T> {
@Autowired
private SearchRedis searchRedis;
public T queryWithCache(ParamQueryFilter paramQueryFilter, Map<String, String> paramMap) throws Exception {
public T queryWithCache(SearchParam searchParam, Map<String, String> paramMap) throws Exception {
//1、生成RedisKeyBuilder
RedisKeyBuilder redisKeyBuilder = this.genRedisKeyBuilder(paramQueryFilter,paramMap);
RedisKeyBuilder redisKeyBuilder = this.genRedisKeyBuilder(searchParam, paramMap);
if (redisKeyBuilder == null) {
return null;
}
... ... @@ -36,11 +39,11 @@ public abstract class AbstractCacheComponent<T> {
this.addValueToEhcache(redisKeyBuilder, result);
return result;
}
return this.doInnerQuery(redisKeyBuilder, paramQueryFilter, paramMap);
return this.doInnerQuery(redisKeyBuilder, searchParam, paramMap);
}
private T doInnerQuery(RedisKeyBuilder redisKeyBuilder, ParamQueryFilter paramQueryFilter, Map<String, String> paramMap) throws Exception {
T result = this.doRealQuery(paramQueryFilter, paramMap);
private T doInnerQuery(RedisKeyBuilder redisKeyBuilder, SearchParam searchParam, Map<String, String> paramMap) throws Exception {
T result = this.doRealQuery(searchParam, paramMap);
if (result == null) {
return result;
}
... ... @@ -49,7 +52,7 @@ public abstract class AbstractCacheComponent<T> {
return result;
}
protected abstract T doRealQuery(ParamQueryFilter paramQueryFilter, Map<String, String> paramMap) throws Exception;
protected abstract T doRealQuery(SearchParam searchParam, Map<String, String> paramMap) throws Exception;
private T getValueFromEhcache(RedisKeyBuilder redisKeyBuilder) throws Exception {
if (!useEhcache()) {
... ... @@ -64,14 +67,14 @@ public abstract class AbstractCacheComponent<T> {
}
private void addValueToEhcache(RedisKeyBuilder redisKeyBuilder, T result) {
if(!useEhcache()){
if (!useEhcache()) {
return;
}
ehCache.addOrUpdate(redisKeyBuilder, new CacheObject(result), this.cacheTimeInMinute());
}
private void addValueToRedis(RedisKeyBuilder redisKeyBuilder, T result) {
if(!useRedis()){
if (!useRedis()) {
return;
}
String jsonString = JSON.toJSONString(result);
... ... @@ -84,10 +87,10 @@ public abstract class AbstractCacheComponent<T> {
return null;
}
CacheObject cacheObject = searchRedis.get(redisKeyBuilder);
if (cacheObject == null || cacheObject.getValue()==null) {
if (cacheObject == null || cacheObject.getValue() == null) {
return null;
}
if(! (cacheObject.getValue() instanceof String)){
if (!(cacheObject.getValue() instanceof String)) {
return null;
}
String redisValue = (String) cacheObject.toObject();
... ... @@ -100,12 +103,20 @@ public abstract class AbstractCacheComponent<T> {
protected abstract String cacheSceneKey();
protected RedisKeyBuilder genRedisKeyBuilder(ParamQueryFilter paramQueryFilter,Map<String,String> paramMap){
RedisKeyBuilder redisKeyBuilder = RedisKeyBuilder.newInstance();
redisKeyBuilder.appendFixed("YOHOSEARCH").appendFixed(":");//前缀
redisKeyBuilder.appendFixed(cacheSceneKey()).appendFixed(":");//场景
redisKeyBuilder.appendFixed(cacheTimeInMinute()).appendFixed(":");//缓存时间
redisKeyBuilder.appendVar(paramQueryFilter.getParamMd5Key());//报文
protected RedisKeyBuilder defaultRedisKeyBuilder() {
RedisKeyBuilder redisKeyBuilder = RedisKeyBuilder.newInstance();
redisKeyBuilder.appendFixed("YOHOSEARCH");//前缀
redisKeyBuilder.appendFixed(":").appendFixed(cacheSceneKey());//场景
redisKeyBuilder.appendFixed(":").appendFixed(cacheTimeInMinute());//缓存时间
return redisKeyBuilder;
}
protected RedisKeyBuilder genRedisKeyBuilder(SearchParam searchParam, Map<String, String> paramMap) {
RedisKeyBuilder redisKeyBuilder = defaultRedisKeyBuilder();
if (searchParam != null) {
SearchSourceBuilder searchSourceBuilder = SearchParamUtils.genSearchSourceBuilderFromSearchParam(searchParam);
redisKeyBuilder.appendFixed(":").appendVar(MD5Util.string2MD5(searchSourceBuilder.toString()));//报文
}
return redisKeyBuilder;
}
... ...
... ... @@ -24,9 +24,9 @@ public class ProductIndexController {
@Autowired
private ProductIndexAggService productIndexAggService;
@Autowired
private SelectionsForPcService selectionsWithAdvanceService;
private SelectionsForPcService selectionsForPcService;
@Autowired
private SelectionsForAppService selectionsWithOutAdvanceService;
private SelectionsForAppService selectionsForAppService;
@Autowired
private ProductCountService productCountService;
... ... @@ -157,7 +157,7 @@ public class ProductIndexController {
@ResponseBody
public SearchApiResult selections(HttpServletRequest request) {
Map<String, String> paramMap = HttpServletRequestUtils.transParamType(request);
return selectionsWithAdvanceService.getSelectionsForPc(paramMap);
return selectionsForPcService.getSelectionsForPc(paramMap);
}
/**
... ... @@ -167,7 +167,7 @@ public class ProductIndexController {
@ResponseBody
public SearchApiResult selectionsForApp(HttpServletRequest request) {
Map<String, String> paramMap = HttpServletRequestUtils.transParamType(request);
return selectionsWithOutAdvanceService.getSelectionsForApp(paramMap);
return selectionsForAppService.getSelectionsForApp(paramMap);
}
/**
... ...
... ... @@ -54,18 +54,6 @@ public class SearchParamHelper {
return buildParamQueryFilter(paramMap,false,null,null);
}
public ParamQueryFilter buildParamQueryFilter(Map<String, String> paramMap,String filterParamName) throws Exception {
return buildParamQueryFilter(paramMap,false,null,filterParamName);
}
public ParamQueryFilter buildParamQueryFilter(Map<String, String> paramMap,BoolQueryBuilder mustFilter) throws Exception {
return buildParamQueryFilter(paramMap,false,mustFilter,null);
}
public ParamQueryFilter buildParamQueryFilter(Map<String, String> paramMap,BoolQueryBuilder mustFilter,String filterParamName) throws Exception {
return buildParamQueryFilter(paramMap,false,mustFilter,filterParamName);
}
public ParamQueryFilter buildParamQueryFilter(Map<String, String> paramMap, boolean needPersional, BoolQueryBuilder mustFilter,String filterParamName) throws Exception {
// 1、构造filter
BoolQueryBuilder filter = searchQueryHelper.constructFilterBuilder(paramMap, filterParamName);
... ...
... ... @@ -8,6 +8,7 @@ import com.yoho.search.common.SearchCommonService;
import com.yoho.search.core.es.model.SearchParam;
import com.yoho.search.core.es.model.SearchResult;
import com.yoho.search.core.personalized.models.SortBrand;
import com.yoho.search.service.helper.SearchParamHelper;
import com.yoho.search.service.recall.beans.helper.ExtendFilterHelper;
import com.yoho.search.service.recall.models.common.ParamQueryFilter;
import com.yoho.search.service.recall.models.personal.PagePersonalFactor;
... ... @@ -32,6 +33,8 @@ public class CachePersionalFactorComponent extends AbstractCacheComponent<PagePe
@Autowired
private SearchCommonService searchCommonService;
@Autowired
private SearchParamHelper searchParamHelper;
/**
* 查询个性化因子
... ... @@ -41,7 +44,8 @@ public class CachePersionalFactorComponent extends AbstractCacheComponent<PagePe
*/
public PagePersonalFactor queryPagePersionalFactor(ParamQueryFilter paramQueryFilter) {
try {
return super.queryWithCache(paramQueryFilter, null);
SearchParam searchParam = searchParamHelper.buildSearchParam(paramQueryFilter);
return super.queryWithCache(searchParam, null);
} catch (Exception e) {
logger.error(e.getMessage(), e);
return new PagePersonalFactor();
... ... @@ -64,13 +68,13 @@ public class CachePersionalFactorComponent extends AbstractCacheComponent<PagePe
}
@Override
protected PagePersonalFactor doRealQuery(ParamQueryFilter paramQueryFilter, Map<String, String> paramMap) throws Exception {
protected PagePersonalFactor doRealQuery(SearchParam old, Map<String, String> paramMap) throws Exception {
//1、构造参数
SearchParam searchParam = new SearchParam();
searchParam.setQuery(paramQueryFilter.getParamQuery());
searchParam.setQuery(old.getQuery());
BoolQueryBuilder filter = QueryBuilders.boolQuery();
filter.must(paramQueryFilter.getParamFilter());
filter.must(old.getFiter());
filter.mustNot(ExtendFilterHelper.notRecallFilter());//聚合的时候带上不召回的数据
searchParam.setFiter(filter);
... ...
package com.yoho.search.service.scene.activity;
import com.yoho.core.redis.cluster.operations.serializer.RedisKeyBuilder;
import com.yoho.search.base.utils.ISearchConstants;
import com.yoho.search.base.utils.ProductIndexEsField;
import com.yoho.search.cache.CacheTimeConstants;
import com.yoho.search.cache.beans.AbstractCacheComponent;
import com.yoho.search.common.SearchCommonService;
import com.yoho.search.core.es.model.SearchParam;
import com.yoho.search.core.es.model.SearchResult;
import com.yoho.search.service.recall.beans.builder.UserRecallRequestBuilder;
import com.yoho.search.service.recall.models.common.ParamQueryFilter;
import com.yoho.search.common.SearchCommonService;
import com.yoho.search.service.helper.AggCommonHelper;
import com.yoho.search.models.aggregations.AggKeyCount;
import com.yoho.search.models.aggregations.AggKeyCountTwoLevel;
import com.yoho.search.service.helper.AggCommonHelper;
import com.yoho.search.service.helper.SearchParamHelper;
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
... ... @@ -30,7 +28,7 @@ public class ActivityShopBrandListService extends AbstractCacheComponent<List<Ac
private static final Logger logger = LoggerFactory.getLogger(ActivityShopBrandListService.class);
@Autowired
private UserRecallRequestBuilder userRecallRequestBuilder;
private SearchParamHelper searchParamHelper;
@Autowired
private SearchCommonService searchCommonService;
... ... @@ -42,8 +40,8 @@ public class ActivityShopBrandListService extends AbstractCacheComponent<List<Ac
*/
public List<ActivityShopBrand> queryActivityShopBrandList(Map<String, String> paramMap) {
try {
ParamQueryFilter paramQueryFilter = userRecallRequestBuilder.buildParamQueryFilter(paramMap);
List<ActivityShopBrand> value = super.queryWithCache(paramQueryFilter,null);
SearchParam searchParam = searchParamHelper.buildDefault(paramMap);
List<ActivityShopBrand> value = super.queryWithCache(searchParam,paramMap);
if(value==null){
return new ArrayList<>();
}
... ... @@ -65,11 +63,8 @@ public class ActivityShopBrandListService extends AbstractCacheComponent<List<Ac
}
@Override
protected List<ActivityShopBrand> doRealQuery(ParamQueryFilter paramQueryFilter,Map<String, String> paramMap) throws Exception {
protected List<ActivityShopBrand> doRealQuery(SearchParam searchParam,Map<String, String> paramMap) throws Exception {
//1、构造参数
SearchParam searchParam = new SearchParam();
searchParam.setQuery(paramQueryFilter.getParamQuery());
searchParam.setFiter(paramQueryFilter.getParamFilter());
searchParam.setSize(0);
//2、构造聚合参数
... ...
... ... @@ -54,8 +54,8 @@ public class DiscountService extends AbstractCacheComponent<JSONObject> implemen
public JSONObject discount(Map<String, String> paramMap, BoolQueryBuilder mustFilter) {
try {
ParamQueryFilter paramQueryFilter = searchParamHelper.buildParamQueryFilter(paramMap, mustFilter);
return super.queryWithCache(paramQueryFilter,paramMap);
SearchParam searchParam = searchParamHelper.buildWithMustFilter(paramMap, mustFilter);
return super.queryWithCache(searchParam,paramMap);
} catch (Exception e) {
logger.error(e.getMessage(), e);
publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_DISCOUNT.getEventName(), EventReportEnum.SEARCHCONTROLLER_DISCOUNT.getFunctionName(),
... ... @@ -75,10 +75,7 @@ public class DiscountService extends AbstractCacheComponent<JSONObject> implemen
}
@Override
protected JSONObject doRealQuery(ParamQueryFilter paramQueryFilter,Map<String, String> paramMap) throws Exception{
// 构造查询参数
SearchParam searchParam = searchParamHelper.buildSearchParam(paramQueryFilter);
protected JSONObject doRealQuery(SearchParam searchParam,Map<String, String> paramMap) throws Exception{
// 按1-3,4-6,7-10折的规则进行聚合[按区间聚合]
IAggregation discountAggregation = aggregationFactory.getDiscountAggregation();
searchParam.setAggregationBuilders(Arrays.asList(discountAggregation.getBuilder()));
... ...
... ... @@ -13,7 +13,6 @@ import com.yoho.search.core.es.model.SearchResult;
import com.yoho.search.models.SearchApiResult;
import com.yoho.search.service.helper.SearchCommonHelper;
import com.yoho.search.service.helper.SearchParamHelper;
import com.yoho.search.service.recall.models.common.ParamQueryFilter;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
... ... @@ -47,13 +46,13 @@ public class ProductCountService extends AbstractCacheComponent<Long> {
public SearchApiResult productCount(Map<String, String> paramMap) {
try {
// 1、构造ParamQueryFilter
ParamQueryFilter paramQueryFilter = searchParamHelper.buildParamQueryFilter(paramMap);
SearchParam searchParam = searchParamHelper.buildDefault(paramMap);
// 2、执行查询
Long count = super.queryWithCache(paramQueryFilter, paramMap);
Long count = super.queryWithCache(searchParam, paramMap);
long countValue = count == null ? 0 : count.longValue();
//3、构造返回结果
JSONObject result = new JSONObject();
result.put("total", count);
result.put("total", countValue);
return new SearchApiResult().setData(result);
} catch (Exception e) {
return SearchApiResultUtils.errorSearchApiResult(logger, paramMap, e);
... ... @@ -73,7 +72,7 @@ public class ProductCountService extends AbstractCacheComponent<Long> {
if (StringUtils.isBlank(query)) {
return 0;
}
// 2、构造ParamQueryFilter
// 2、构造mustFilter
BoolQueryBuilder mustFilter = QueryBuilders.boolQuery();
mustFilter.must(QueryBuilders.termQuery(ProductIndexEsField.status, 1));
mustFilter.mustNot(QueryBuilders.termQuery(ProductIndexEsField.attribute, 2));
... ... @@ -82,10 +81,12 @@ public class ProductCountService extends AbstractCacheComponent<Long> {
if (!searchCommonHelper.containGlobal(paramMap)) {
mustFilter.mustNot(QueryBuilders.termQuery(ProductIndexEsField.isGlobal, "Y"));
}
ParamQueryFilter paramQueryFilter = searchParamHelper.buildParamQueryFilter(paramMap, mustFilter);
// 3、执行查询
Long count = super.queryWithCache(paramQueryFilter, paramMap);
// 3、构造searchParam
SearchParam searchParam = searchParamHelper.buildWithMustFilter(paramMap, mustFilter);
// 4、执行查询
Long count = super.queryWithCache(searchParam, paramMap);
// 4、返回结果
return count == null ? 0 : count.longValue();
... ... @@ -140,10 +141,12 @@ public class ProductCountService extends AbstractCacheComponent<Long> {
BoolQueryBuilder filter = new BoolQueryBuilder();
filter.must(paramFilter);
filter.must(scoreFilter);
ParamQueryFilter paramQueryFilter = new ParamQueryFilter(QueryBuilders.matchAllQuery(), filter);
SearchParam searchParam = new SearchParam();
searchParam.setFiter(filter);
// 2、执行查询
Long count = super.queryWithCache(paramQueryFilter, null);
Long count = super.queryWithCache(searchParam, null);
// 3、返回结果
return count == null ? 0 : count.longValue();
... ... @@ -154,16 +157,12 @@ public class ProductCountService extends AbstractCacheComponent<Long> {
}
@Override
protected Long doRealQuery(ParamQueryFilter paramQueryFilter, Map<String, String> paramMap) throws Exception {
// 1、构造SearchParam
SearchParam searchParam = searchParamHelper.buildSearchParam(paramQueryFilter);
searchParam.setSize(0);
// 2、 执行检索
protected Long doRealQuery(SearchParam searchParam, Map<String, String> paramMap) throws Exception {
// 1、 执行检索
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
// 3、 构造返回结果
// 2、 构造返回结果
return searchResult == null ? 0 : searchResult.getTotal();
}
... ...
package com.yoho.search.service.scene.general;
import java.util.*;
import java.util.Map.Entry;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yoho.search.base.utils.ISearchConstants;
import com.yoho.search.cache.beans.AbstractCacheAbleService;
import com.yoho.search.cache.log.SearchCacheMatchLogger;
import com.yoho.search.cache.model.SearchCache;
import com.yoho.search.cache.CacheTimeConstants;
import com.yoho.search.cache.beans.AbstractCacheComponent;
import com.yoho.search.common.SearchCommonService;
import com.yoho.search.common.SearchRequestParams;
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.SearchApiResult;
import com.yoho.search.service.aggregations.impls.AggregationFactory;
import com.yoho.search.common.SearchCommonService;
import com.yoho.search.common.SearchRequestParams;
import com.yoho.search.service.helper.SearchParamHelper;
import com.yoho.search.service.helper.SearchQueryHelper;
import com.yoho.search.service.index.BrandIndexBaseService;
import com.yoho.search.service.index.ColorIndexBaseService;
import com.yoho.search.service.index.SizeIndexBaseService;
import com.yoho.search.service.index.StyleIndexBaseService;
import com.yoho.search.service.helper.SearchAfterCacheHelper;
import com.yoho.search.service.helper.SearchParamHelper;
import com.yoho.search.service.helper.SearchQueryHelper;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import com.yoho.search.models.SearchApiResult;
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.bucket.MultiBucketsAggregation;
... ... @@ -35,381 +29,379 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.Map.Entry;
@Service
public class SelectionsForPcService extends AbstractCacheAbleService {
public class SelectionsForPcService extends AbstractCacheComponent<JSONObject> {
@Autowired
private SearchParamHelper searchParamHelper;
@Autowired
private SearchQueryHelper searchQueryHelper;
@Autowired
private AggregationFactory aggregationFactory;
@Autowired
private SearchCommonService searchCommonService;
@Autowired
private SearchAfterCacheHelper searchAfterCacheService;
@Autowired
private BrandIndexBaseService brandIndexBaseService;
@Autowired
private ColorIndexBaseService colorIndexBaseService;
@Autowired
private StyleIndexBaseService styleIndexBaseService;
@Autowired
private SizeIndexBaseService sizeIndexBaseService;
@Autowired
private SearchParamHelper searchParamHelper;
@Autowired
private SearchQueryHelper searchQueryHelper;
@Autowired
private AggregationFactory aggregationFactory;
@Autowired
private SearchCommonService searchCommonService;
@Autowired
private BrandIndexBaseService brandIndexBaseService;
@Autowired
private ColorIndexBaseService colorIndexBaseService;
@Autowired
private StyleIndexBaseService styleIndexBaseService;
@Autowired
private SizeIndexBaseService sizeIndexBaseService;
@Override
public SearchCache getSearchCache() {
return searchCacheFactory.getSelectionsForPcCache();
}
private static Logger logger = LoggerFactory.getLogger(SelectionsForPcService.class);
private static Logger logger = LoggerFactory.getLogger(SelectionsForPcService.class);
public SearchApiResult getSelectionsForPc(Map<String, String> paramMap) {
try {
return this.getSelectionsForPc(paramMap, null);
} catch (Exception e) {
logger.error(e.getMessage(), e);
return new SearchApiResult().setCode(500).setMessage("getSelectionsForPc Exception:" + e.getMessage());
}
}
public SearchApiResult getSelectionsForPc(Map<String, String> paramMap) {
try {
return this.getSelectionsForPc(paramMap, null);
} catch (Exception e) {
logger.error(e.getMessage(), e);
return new SearchApiResult().setCode(500).setMessage("getSelectionsForPc Exception:" + e.getMessage());
}
}
public SearchApiResult getSelectionsForPc(Map<String, String> paramMap, BoolQueryBuilder mustFilter) throws Exception {
// 1)构造searchParam
SearchParam searchParam = searchParamHelper.buildWithMustFilter(paramMap, mustFilter);
// 2)调父类查询
JSONObject result = super.queryWithCache(searchParam, paramMap);
// 3)生成结果
return new SearchApiResult().setData(result);
}
public SearchApiResult getSelectionsForPc(Map<String, String> paramMap, BoolQueryBuilder mustFilter) throws Exception {
// 1)构造SearchParam
SearchParam searchParam = searchParamHelper.buildWithMustFilter(paramMap, mustFilter);
searchParam.setOffset(3);// just for cache
searchParam.setSize(0);
@Override
protected JSONObject doRealQuery(SearchParam searchParam, Map<String, String> paramMap) throws Exception {
//1)获取【提前聚合】的结果[必须用searchParam.clone(),因为外层的方法会传mustFilter]
Map<String, Object> preAggregationResult = this.preAggregationSearch(searchParam.clone(), paramMap);
SearchParam searchParamClone = searchParam.clone();// 用来缓存
String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
//2)获取【非提前聚合的结果】
Map<String, Aggregation> aggMaps = new HashMap<String, Aggregation>();
searchParam.setAggregationBuilders(this.getOtherAggregations(paramMap));
SearchResult searchResult = searchCommonService.doSearch(ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
if (searchResult != null && searchResult.getAggMaps() != null) {
aggMaps = searchResult.getAggMaps();
}
//3)构造返回结果,并将结果缓存
JSONObject result = new JSONObject();
result.put("filter", buildFilterResult(aggMaps, preAggregationResult, paramMap));
return result;
}
// 2)从缓存里获取,取到则直接返回
JSONObject cacheObject = searchCacheService.getJSONObjectFromCache(this.searchCache, indexName, searchParamClone);
if (cacheObject != null) {
Object newCacheObject = searchAfterCacheService.dealFilterCacheObject(cacheObject);
SearchCacheMatchLogger.doSearchCacheMatchLog("/productindex/selectionsForPc.json", paramMap);
return new SearchApiResult().setData(newCacheObject);
}
@Override
protected int cacheTimeInMinute() {
return CacheTimeConstants.CACHE_15_MINUTE;
}
// 3)获取【提前聚合】的结果
Map<String, Object> preAggregationResult = this.preAggregationSearch(searchParam.clone(), paramMap);
@Override
protected String cacheSceneKey() {
return "SELECTIONS_FOR_PC";
}
// 4)获取【非提前聚合的结果】
Map<String, Aggregation> aggMaps = new HashMap<String, Aggregation>();
searchParam.setAggregationBuilders(this.getOtherAggregations(paramMap));
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
if (searchResult != null && searchResult.getAggMaps() != null) {
aggMaps = searchResult.getAggMaps();
}
// 5)构造返回结果,并将结果缓存
JSONObject result = new JSONObject();
result.put("filter", buildFilterResult(aggMaps, preAggregationResult, paramMap));
searchCacheService.addJSONObjectToCache(this.searchCache, indexName, searchParamClone, result);
return new SearchApiResult().setData(result);
}
/**
* 预聚合的属性,参数里有这些参数则优先聚合[因为filter的参数不同,聚合包含了一定的业务逻辑]
*
* @param searchParam
* @param paramMap
* @return
* @throws Exception
*/
private Map<String, Object> preAggregationSearch(SearchParam searchParam, Map<String, String> paramMap) throws Exception {
Map<String, Object> preAggregationResult = new HashMap<String, Object>();
// 1)年龄层
if (paramMap.containsKey(SearchRequestParams.PARAM_SEARCH_AGELEVEL) && StringUtils.isNotBlank(paramMap.get(SearchRequestParams.PARAM_SEARCH_AGELEVEL))) {
IAggregation aggregation = aggregationFactory.getAgeLevelAggregation();
searchParam.setAggregationBuilders(Arrays.asList(aggregation.getBuilder()));
searchParam.setFiter(searchQueryHelper.constructFilterBuilder(paramMap, SearchRequestParams.PARAM_SEARCH_AGELEVEL));
preAggregationResult.put(aggregation.aggName(), doPreSearch(searchParam.clone(), paramMap));
}
// 2)性别
if (paramMap.containsKey(SearchRequestParams.PARAM_SEARCH_GENDER) && StringUtils.isNotBlank(paramMap.get(SearchRequestParams.PARAM_SEARCH_GENDER))) {
IAggregation genderAggregation = aggregationFactory.getGenderAggregation(paramMap);
searchParam.setAggregationBuilders(Arrays.asList(genderAggregation.getBuilder()));
searchParam.setFiter(searchQueryHelper.constructFilterBuilder(paramMap, SearchRequestParams.PARAM_SEARCH_GENDER));
preAggregationResult.put(genderAggregation.aggName(), doPreSearch(searchParam.clone(), paramMap));
}
// 3)价格
if (paramMap.containsKey(SearchRequestParams.PARAM_SEARCH_PRICE) && StringUtils.isNotBlank(paramMap.get(SearchRequestParams.PARAM_SEARCH_PRICE))) {
IAggregation priceAggregation = aggregationFactory.getPriceAggregation();
searchParam.setAggregationBuilders(Arrays.asList(priceAggregation.getBuilder()));
searchParam.setFiter(searchQueryHelper.constructFilterBuilder(paramMap, SearchRequestParams.PARAM_SEARCH_PRICE));
preAggregationResult.put(priceAggregation.aggName(), doPreSearch(searchParam.clone(), paramMap));
}
// 4)颜色
if (paramMap.containsKey(SearchRequestParams.PARAM_SEARCH_COLOR) && StringUtils.isNotBlank(paramMap.get(SearchRequestParams.PARAM_SEARCH_COLOR))) {
IAggregation colorAggregation = aggregationFactory.getColorAggregation(paramMap);
searchParam.setAggregationBuilders(Arrays.asList(colorAggregation.getBuilder()));
searchParam.setFiter(searchQueryHelper.constructFilterBuilder(paramMap, SearchRequestParams.PARAM_SEARCH_COLOR));
preAggregationResult.put(colorAggregation.aggName(), doPreSearch(searchParam.clone(), paramMap));
}
// 5)风格
if (paramMap.containsKey(SearchRequestParams.PARAM_SEARCH_STYLE) && StringUtils.isNotBlank(paramMap.get(SearchRequestParams.PARAM_SEARCH_STYLE))) {
IAggregation styleAggregation = aggregationFactory.getStyleAggregation(paramMap);
searchParam.setAggregationBuilders(Arrays.asList(styleAggregation.getBuilder()));
searchParam.setFiter(searchQueryHelper.constructFilterBuilder(paramMap, SearchRequestParams.PARAM_SEARCH_STYLE));
preAggregationResult.put(styleAggregation.aggName(), doPreSearch(searchParam.clone(), paramMap));
}
// 6)品牌
if (paramMap.containsKey(SearchRequestParams.PARAM_SEARCH_BRAND) && StringUtils.isNotBlank(paramMap.get(SearchRequestParams.PARAM_SEARCH_BRAND))) {
IAggregation brandAggregation = aggregationFactory.getBrandAggregation(paramMap, 10);
searchParam.setAggregationBuilders(Arrays.asList(brandAggregation.getBuilder()));
searchParam.setFiter(searchQueryHelper.constructFilterBuilder(paramMap, SearchRequestParams.PARAM_SEARCH_BRAND));
preAggregationResult.put(brandAggregation.aggName(), doPreSearch(searchParam.clone(), paramMap));
}
return preAggregationResult;
}
/**
* 预聚合的属性,参数里有这些参数则优先聚合[因为filter的参数不同,聚合包含了一定的业务逻辑]
*
* @param searchParam
* @param paramMap
* @return
* @throws Exception
*/
private Map<String, Object> preAggregationSearch(SearchParam searchParam, Map<String, String> paramMap) throws Exception {
Map<String, Object> preAggregationResult = new HashMap<>();
// 1)年龄层
if (paramMap.containsKey(SearchRequestParams.PARAM_SEARCH_AGELEVEL) && StringUtils.isNotBlank(paramMap.get(SearchRequestParams.PARAM_SEARCH_AGELEVEL))) {
IAggregation aggregation = aggregationFactory.getAgeLevelAggregation();
searchParam.setAggregationBuilders(Arrays.asList(aggregation.getBuilder()));
searchParam.setFiter(searchQueryHelper.constructFilterBuilder(paramMap, SearchRequestParams.PARAM_SEARCH_AGELEVEL));
preAggregationResult.put(aggregation.aggName(), doPreSearch(searchParam.clone(), paramMap));
}
// 2)性别
if (paramMap.containsKey(SearchRequestParams.PARAM_SEARCH_GENDER) && StringUtils.isNotBlank(paramMap.get(SearchRequestParams.PARAM_SEARCH_GENDER))) {
IAggregation genderAggregation = aggregationFactory.getGenderAggregation(paramMap);
searchParam.setAggregationBuilders(Arrays.asList(genderAggregation.getBuilder()));
searchParam.setFiter(searchQueryHelper.constructFilterBuilder(paramMap, SearchRequestParams.PARAM_SEARCH_GENDER));
preAggregationResult.put(genderAggregation.aggName(), doPreSearch(searchParam.clone(), paramMap));
}
// 3)价格
if (paramMap.containsKey(SearchRequestParams.PARAM_SEARCH_PRICE) && StringUtils.isNotBlank(paramMap.get(SearchRequestParams.PARAM_SEARCH_PRICE))) {
IAggregation priceAggregation = aggregationFactory.getPriceAggregation();
searchParam.setAggregationBuilders(Arrays.asList(priceAggregation.getBuilder()));
searchParam.setFiter(searchQueryHelper.constructFilterBuilder(paramMap, SearchRequestParams.PARAM_SEARCH_PRICE));
preAggregationResult.put(priceAggregation.aggName(), doPreSearch(searchParam.clone(), paramMap));
}
// 4)颜色
if (paramMap.containsKey(SearchRequestParams.PARAM_SEARCH_COLOR) && StringUtils.isNotBlank(paramMap.get(SearchRequestParams.PARAM_SEARCH_COLOR))) {
IAggregation colorAggregation = aggregationFactory.getColorAggregation(paramMap);
searchParam.setAggregationBuilders(Arrays.asList(colorAggregation.getBuilder()));
searchParam.setFiter(searchQueryHelper.constructFilterBuilder(paramMap, SearchRequestParams.PARAM_SEARCH_COLOR));
preAggregationResult.put(colorAggregation.aggName(), doPreSearch(searchParam.clone(), paramMap));
}
// 5)风格
if (paramMap.containsKey(SearchRequestParams.PARAM_SEARCH_STYLE) && StringUtils.isNotBlank(paramMap.get(SearchRequestParams.PARAM_SEARCH_STYLE))) {
IAggregation styleAggregation = aggregationFactory.getStyleAggregation(paramMap);
searchParam.setAggregationBuilders(Arrays.asList(styleAggregation.getBuilder()));
searchParam.setFiter(searchQueryHelper.constructFilterBuilder(paramMap, SearchRequestParams.PARAM_SEARCH_STYLE));
preAggregationResult.put(styleAggregation.aggName(), doPreSearch(searchParam.clone(), paramMap));
}
// 6)品牌
if (paramMap.containsKey(SearchRequestParams.PARAM_SEARCH_BRAND) && StringUtils.isNotBlank(paramMap.get(SearchRequestParams.PARAM_SEARCH_BRAND))) {
IAggregation brandAggregation = aggregationFactory.getBrandAggregation(paramMap, 10);
searchParam.setAggregationBuilders(Arrays.asList(brandAggregation.getBuilder()));
searchParam.setFiter(searchQueryHelper.constructFilterBuilder(paramMap, SearchRequestParams.PARAM_SEARCH_BRAND));
preAggregationResult.put(brandAggregation.aggName(), doPreSearch(searchParam.clone(), paramMap));
}
return preAggregationResult;
}
/**
* 预聚合,并获取聚合结果[因为filter的参数不同,包含了一定的业务逻辑][针对这里做一下缓存]
*
* @param searchParam
* @param paramMap
* @return
* @throws Exception
*/
private Object doPreSearch(SearchParam searchParam, Map<String, String> paramMap) {
String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
/**
* 预聚合,并获取聚合结果[因为filter的参数不同,包含了一定的业务逻辑][针对这里做一下缓存]
*
* @param searchParam
* @param paramMap
* @return
* @throws Exception
*/
private Object doPreSearch(SearchParam searchParam, Map<String, String> paramMap) {
String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
Map<String, Aggregation> aggMaps = searchResult.getAggMaps();
if (aggMaps == null) {
return null;
}
// 1)获取年龄层的聚合结果
IAggregation ageLevelAggregation = aggregationFactory.getAgeLevelAggregation();
if (aggMaps.containsKey(ageLevelAggregation.aggName())) {
return ageLevelAggregation.getAggregationResponseMap(aggMaps);
}
// 2)获取性别层的聚合结果
IAggregation genderAggregation = aggregationFactory.getGenderAggregation(paramMap);
if (aggMaps.containsKey(genderAggregation.aggName())) {
Object genderResult = genderAggregation.getAggregationResponseMap(aggMaps);
return genderResult;
}
// 3)获取价格层的聚合结果
IAggregation priceAggregation = aggregationFactory.getPriceAggregation();
if (aggMaps.containsKey(priceAggregation.aggName())) {
return priceAggregation.getAggregationResponseMap(aggMaps);
}
// 4)获取颜色层的聚合结果
IAggregation collorAggregation = aggregationFactory.getColorAggregation(paramMap);
if (aggMaps.containsKey(collorAggregation.aggName())) {
return collorAggregation.getAggregationResponseMap(aggMaps);
}
// 5)获取风格层面的聚合结果
IAggregation styleAggregation = aggregationFactory.getStyleAggregation(paramMap);
if (aggMaps.containsKey(styleAggregation.aggName())) {
return styleAggregation.getAggregationResponseMap(aggMaps);
}
// 6)获取品牌层面的聚合结果
IAggregation brandaAggregation = aggregationFactory.getBrandAggregation(paramMap, 10);
if (aggMaps.containsKey(brandaAggregation.aggName())) {
return brandaAggregation.getAggregationResponseMap(aggMaps);
}
return null;
}
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
Map<String, Aggregation> aggMaps = searchResult.getAggMaps();
if (aggMaps == null) {
return null;
}
// 1)获取年龄层的聚合结果
IAggregation ageLevelAggregation = aggregationFactory.getAgeLevelAggregation();
if (aggMaps.containsKey(ageLevelAggregation.aggName())) {
return ageLevelAggregation.getAggregationResponseMap(aggMaps);
}
// 2)获取性别层的聚合结果
IAggregation genderAggregation = aggregationFactory.getGenderAggregation(paramMap);
if (aggMaps.containsKey(genderAggregation.aggName())) {
Object genderResult = genderAggregation.getAggregationResponseMap(aggMaps);
return genderResult;
}
// 3)获取价格层的聚合结果
IAggregation priceAggregation = aggregationFactory.getPriceAggregation();
if (aggMaps.containsKey(priceAggregation.aggName())) {
return priceAggregation.getAggregationResponseMap(aggMaps);
}
// 4)获取颜色层的聚合结果
IAggregation collorAggregation = aggregationFactory.getColorAggregation(paramMap);
if (aggMaps.containsKey(collorAggregation.aggName())) {
return collorAggregation.getAggregationResponseMap(aggMaps);
}
// 5)获取风格层面的聚合结果
IAggregation styleAggregation = aggregationFactory.getStyleAggregation(paramMap);
if (aggMaps.containsKey(styleAggregation.aggName())) {
return styleAggregation.getAggregationResponseMap(aggMaps);
}
// 6)获取品牌层面的聚合结果
IAggregation brandaAggregation = aggregationFactory.getBrandAggregation(paramMap, 10);
if (aggMaps.containsKey(brandaAggregation.aggName())) {
return brandaAggregation.getAggregationResponseMap(aggMaps);
}
return null;
}
/**
* 构造所有的聚合参数
*
* @param paramMap
* @return
*/
private List<AbstractAggregationBuilder<?>> getOtherAggregations(Map<String, String> paramMap) {
List<AbstractAggregationBuilder<?>> list = new ArrayList<AbstractAggregationBuilder<?>>();
// 1)年龄层
if (!paramMap.containsKey("ageLevel") || StringUtils.isBlank(paramMap.get("ageLevel"))) {
list.add(aggregationFactory.getAgeLevelAggregation().getBuilder());
}
// 2)性别
if (!paramMap.containsKey("gender") || StringUtils.isBlank(paramMap.get("gender"))) {
list.add(aggregationFactory.getGenderAggregation(paramMap).getBuilder());
}
// 3)价格
if (!paramMap.containsKey("price") || StringUtils.isBlank(paramMap.get("price"))) {
list.add(aggregationFactory.getPriceAggregation().getBuilder());
}
// 4)颜色
if (!paramMap.containsKey("color") || StringUtils.isBlank(paramMap.get("color"))) {
list.add(aggregationFactory.getColorAggregation(paramMap).getBuilder());
}
// 5)风格
if (!paramMap.containsKey("style") || StringUtils.isBlank(paramMap.get("style"))) {
list.add(aggregationFactory.getStyleAggregation(paramMap).getBuilder());
}
// 5)品牌
if (!paramMap.containsKey("brand") || StringUtils.isBlank(paramMap.get("brand"))) {
list.add(aggregationFactory.getBrandAggregation(paramMap, 10).getBuilder());
}
// ************************************以下聚合只有不传相关参数的时候才会去聚合********************************/
// 7)【领型】【衣长】【袖长】【版型】【袖型】
list.add(aggregationFactory.getStandardAggregation(paramMap).getBuilder());
/**
* 构造所有的聚合参数
*
* @param paramMap
* @return
*/
private List<AbstractAggregationBuilder<?>> getOtherAggregations(Map<String, String> paramMap) {
List<AbstractAggregationBuilder<?>> list = new ArrayList<AbstractAggregationBuilder<?>>();
// 1)年龄层
if (!paramMap.containsKey("ageLevel") || StringUtils.isBlank(paramMap.get("ageLevel"))) {
list.add(aggregationFactory.getAgeLevelAggregation().getBuilder());
}
// 2)性别
if (!paramMap.containsKey("gender") || StringUtils.isBlank(paramMap.get("gender"))) {
list.add(aggregationFactory.getGenderAggregation(paramMap).getBuilder());
}
// 3)价格
if (!paramMap.containsKey("price") || StringUtils.isBlank(paramMap.get("price"))) {
list.add(aggregationFactory.getPriceAggregation().getBuilder());
}
// 4)颜色
if (!paramMap.containsKey("color") || StringUtils.isBlank(paramMap.get("color"))) {
list.add(aggregationFactory.getColorAggregation(paramMap).getBuilder());
}
// 5)风格
if (!paramMap.containsKey("style") || StringUtils.isBlank(paramMap.get("style"))) {
list.add(aggregationFactory.getStyleAggregation(paramMap).getBuilder());
}
// 5)品牌
if (!paramMap.containsKey("brand") || StringUtils.isBlank(paramMap.get("brand"))) {
list.add(aggregationFactory.getBrandAggregation(paramMap, 10).getBuilder());
}
// ************************************以下聚合只有不传相关参数的时候才会去聚合********************************/
// 7)【领型】【衣长】【袖长】【版型】【袖型】
list.add(aggregationFactory.getStandardAggregation(paramMap).getBuilder());
// 8)尺码
if (!paramMap.containsKey("size") || StringUtils.isBlank(paramMap.get("size"))) {
list.add(aggregationFactory.getSizeAggregation().getBuilder());
}
// 9)新品
if (!paramMap.containsKey("new") || StringUtils.isBlank(paramMap.get("new"))) {
list.add(aggregationFactory.getIsNewAggregation().getBuilder());
}
// 10)限量
if (!paramMap.containsKey("limited") || StringUtils.isBlank(paramMap.get("limited"))) {
list.add(aggregationFactory.getIsLimitedAggregation().getBuilder());
}
// 11)折扣
if (!paramMap.containsKey("specialoffer") || StringUtils.isBlank(paramMap.get("specialoffer"))) {
list.add(aggregationFactory.getIsSecialofferAggregation().getBuilder());
}
// 12)全球购
if (!paramMap.containsKey("is_global") || StringUtils.isBlank(paramMap.get("is_global"))) {
list.add(aggregationFactory.getIsGlobalAggregation().getBuilder());
}
return list;
}
// 8)尺码
if (!paramMap.containsKey("size") || StringUtils.isBlank(paramMap.get("size"))) {
list.add(aggregationFactory.getSizeAggregation().getBuilder());
}
// 9)新品
if (!paramMap.containsKey("new") || StringUtils.isBlank(paramMap.get("new"))) {
list.add(aggregationFactory.getIsNewAggregation().getBuilder());
}
// 10)限量
if (!paramMap.containsKey("limited") || StringUtils.isBlank(paramMap.get("limited"))) {
list.add(aggregationFactory.getIsLimitedAggregation().getBuilder());
}
// 11)折扣
if (!paramMap.containsKey("specialoffer") || StringUtils.isBlank(paramMap.get("specialoffer"))) {
list.add(aggregationFactory.getIsSecialofferAggregation().getBuilder());
}
// 12)全球购
if (!paramMap.containsKey("is_global") || StringUtils.isBlank(paramMap.get("is_global"))) {
list.add(aggregationFactory.getIsGlobalAggregation().getBuilder());
}
return list;
}
private Object getResponseByIAggregation(IAggregation aggregation, Map<String, Object> preAggregationResult, Map<String, Aggregation> aggMaps) {
boolean containedInPreResult = preAggregationResult.containsKey(aggregation.aggName());
Object ageLevelResponse = containedInPreResult ? preAggregationResult.get(aggregation.aggName()) : aggregation.getAggregationResponseMap(aggMaps);
return ageLevelResponse;
}
private Object getResponseByIAggregation(IAggregation aggregation, Map<String, Object> preAggregationResult, Map<String, Aggregation> aggMaps) {
boolean containedInPreResult = preAggregationResult.containsKey(aggregation.aggName());
Object ageLevelResponse = containedInPreResult ? preAggregationResult.get(aggregation.aggName()) : aggregation.getAggregationResponseMap(aggMaps);
return ageLevelResponse;
}
@SuppressWarnings("unchecked")
private Map<String, Object> buildFilterResult(Map<String, Aggregation> aggMaps, Map<String, Object> preAggregationResult, Map<String, String> paramMap) {
Map<String, Object> filter = new HashMap<String, Object>();
// 1)获取年龄的聚合结果
IAggregation ageLevelAggregation = aggregationFactory.getAgeLevelAggregation();
Object ageLevelResponse = this.getResponseByIAggregation(ageLevelAggregation, preAggregationResult, aggMaps);
if (ageLevelResponse != null) {
filter.put("ageLevel", ageLevelResponse);
}
// 2)获取性别的聚合结果
IAggregation genderAggregation = aggregationFactory.getGenderAggregation(paramMap);
Object genderResponse = this.getResponseByIAggregation(genderAggregation, preAggregationResult, aggMaps);
if (genderResponse != null) {
filter.put("gender", genderResponse);
}
// 3)获取价格层面的聚合结果
IAggregation priceAggregation = aggregationFactory.getPriceAggregation();
Object priceResponse = this.getResponseByIAggregation(priceAggregation, preAggregationResult, aggMaps);
if (priceResponse != null) {
filter.put("price", priceResponse);
} else {
filter.put("price", this.getDeaultPriceMap());
}
// 4)获取颜色层面的聚合结果
IAggregation colorAggregation = aggregationFactory.getColorAggregation(paramMap);
Object colorResponse = this.getResponseByIAggregation(colorAggregation, preAggregationResult, aggMaps);
if (colorResponse != null) {
filter.put("color", colorResponse);
} else {
filter.put("color", colorIndexBaseService.getColorListByIdStr(paramMap.get("color")));
}
// 5)获取风格层面的聚合结果
IAggregation styleAggregation = aggregationFactory.getStyleAggregation(paramMap);
Object styleResponse = this.getResponseByIAggregation(styleAggregation, preAggregationResult, aggMaps);
if (styleResponse != null) {
filter.put("style", styleResponse);
} else {
filter.put("style", styleIndexBaseService.getStyleListByIdStr(paramMap.get("style")));
}
// 6)获取品牌层面的聚合结果
IAggregation brandAggregation = aggregationFactory.getBrandAggregation(paramMap, 10);
Object brandResponse = this.getResponseByIAggregation(brandAggregation, preAggregationResult, aggMaps);
if (brandResponse != null) {
filter.put("brand", brandResponse);
} else {
filter.put("brand", brandIndexBaseService.getBrandListByIdStr(paramMap.get("brand")));
}
// 7) 如果参数里面有brand,则将此brand返回给PC
if (StringUtils.isNotBlank(paramMap.get("brand"))) {
filter.put("paramBrand", brandIndexBaseService.getBrandListByIdStr(paramMap.get("brand")));
} else {
filter.put("paramBrand", new JSONArray());
}
@SuppressWarnings("unchecked")
private Map<String, Object> buildFilterResult(Map<String, Aggregation> aggMaps, Map<String, Object> preAggregationResult, Map<String, String> paramMap) {
Map<String, Object> filter = new HashMap<String, Object>();
// 1)获取年龄的聚合结果
IAggregation ageLevelAggregation = aggregationFactory.getAgeLevelAggregation();
Object ageLevelResponse = this.getResponseByIAggregation(ageLevelAggregation, preAggregationResult, aggMaps);
if (ageLevelResponse != null) {
filter.put("ageLevel", ageLevelResponse);
}
// 2)获取性别的聚合结果
IAggregation genderAggregation = aggregationFactory.getGenderAggregation(paramMap);
Object genderResponse = this.getResponseByIAggregation(genderAggregation, preAggregationResult, aggMaps);
if (genderResponse != null) {
filter.put("gender", genderResponse);
}
// 3)获取价格层面的聚合结果
IAggregation priceAggregation = aggregationFactory.getPriceAggregation();
Object priceResponse = this.getResponseByIAggregation(priceAggregation, preAggregationResult, aggMaps);
if (priceResponse != null) {
filter.put("price", priceResponse);
} else {
filter.put("price", this.getDeaultPriceMap());
}
// 4)获取颜色层面的聚合结果
IAggregation colorAggregation = aggregationFactory.getColorAggregation(paramMap);
Object colorResponse = this.getResponseByIAggregation(colorAggregation, preAggregationResult, aggMaps);
if (colorResponse != null) {
filter.put("color", colorResponse);
} else {
filter.put("color", colorIndexBaseService.getColorListByIdStr(paramMap.get("color")));
}
// 5)获取风格层面的聚合结果
IAggregation styleAggregation = aggregationFactory.getStyleAggregation(paramMap);
Object styleResponse = this.getResponseByIAggregation(styleAggregation, preAggregationResult, aggMaps);
if (styleResponse != null) {
filter.put("style", styleResponse);
} else {
filter.put("style", styleIndexBaseService.getStyleListByIdStr(paramMap.get("style")));
}
// 6)获取品牌层面的聚合结果
IAggregation brandAggregation = aggregationFactory.getBrandAggregation(paramMap, 10);
Object brandResponse = this.getResponseByIAggregation(brandAggregation, preAggregationResult, aggMaps);
if (brandResponse != null) {
filter.put("brand", brandResponse);
} else {
filter.put("brand", brandIndexBaseService.getBrandListByIdStr(paramMap.get("brand")));
}
// 7) 如果参数里面有brand,则将此brand返回给PC
if (StringUtils.isNotBlank(paramMap.get("brand"))) {
filter.put("paramBrand", brandIndexBaseService.getBrandListByIdStr(paramMap.get("brand")));
} else {
filter.put("paramBrand", new JSONArray());
}
// 8)获取尺码聚合结果[尺码不会提前聚合]
IAggregation sizeAggregation = aggregationFactory.getSizeAggregation();
Object sizeResponse = this.getResponseByIAggregation(sizeAggregation, preAggregationResult, aggMaps);
if (sizeResponse != null) {
filter.put("size", sizeResponse);
} else {
filter.put("size", sizeIndexBaseService.getSizeListByIdStr(paramMap.get("size")));
}
// 8)获取尺码聚合结果[尺码不会提前聚合]
IAggregation sizeAggregation = aggregationFactory.getSizeAggregation();
Object sizeResponse = this.getResponseByIAggregation(sizeAggregation, preAggregationResult, aggMaps);
if (sizeResponse != null) {
filter.put("size", sizeResponse);
} else {
filter.put("size", sizeIndexBaseService.getSizeListByIdStr(paramMap.get("size")));
}
// 9)获取规则的聚合结果[规格不会提前聚合]
IAggregation standardAggregation = aggregationFactory.getStandardAggregation(paramMap);
Object standardResponse = this.getResponseByIAggregation(standardAggregation, preAggregationResult, aggMaps);
if (standardResponse != null) {
Iterator<Entry<String, Object>> entryStandard = ((Map<String, Object>) standardResponse).entrySet().iterator();
while (entryStandard.hasNext()) {
Entry<String, Object> entry = entryStandard.next();
if (paramMap.containsKey(entry.getKey())) {
filter.put(entry.getKey(), entry.getValue());
} else {
filter.put(entry.getKey(), entry.getValue());
}
}
}
// 返回最新、限量、折扣
this.setNLS(aggMaps, filter);
return filter;
}
// 9)获取规则的聚合结果[规格不会提前聚合]
IAggregation standardAggregation = aggregationFactory.getStandardAggregation(paramMap);
Object standardResponse = this.getResponseByIAggregation(standardAggregation, preAggregationResult, aggMaps);
if (standardResponse != null) {
Iterator<Entry<String, Object>> entryStandard = ((Map<String, Object>) standardResponse).entrySet().iterator();
while (entryStandard.hasNext()) {
Entry<String, Object> entry = entryStandard.next();
if (paramMap.containsKey(entry.getKey())) {
filter.put(entry.getKey(), entry.getValue());
} else {
filter.put(entry.getKey(), entry.getValue());
}
}
}
// 返回最新、限量、折扣
this.setNLS(aggMaps, filter);
return filter;
}
/**
* 获取默认的价格区间
*
* @return
*/
public Map<String, Object> getDeaultPriceMap() {
Map<String, Object> priceMap = new LinkedHashMap<String, Object>();
priceMap.put("0,300", "¥0-300");
priceMap.put("300,600", "¥300-600");
priceMap.put("600,1000", "¥600-1000");
priceMap.put("1000,2000", "¥1000-2000");
priceMap.put("2000,99999", "¥2000以上");
return priceMap;
}
/**
* 获取默认的价格区间
*
* @return
*/
public Map<String, Object> getDeaultPriceMap() {
Map<String, Object> priceMap = new LinkedHashMap<String, Object>();
priceMap.put("0,300", "¥0-300");
priceMap.put("300,600", "¥300-600");
priceMap.put("600,1000", "¥600-1000");
priceMap.put("1000,2000", "¥1000-2000");
priceMap.put("2000,99999", "¥2000以上");
return priceMap;
}
// 返回最新、限量、折扣的聚合结果
public void setNLS(Map<String, Aggregation> aggMaps, Map<String, Object> result) {
if (aggMaps.containsKey("isnewAgg")) {
if (getNLSMap((MultiBucketsAggregation) aggMaps.get("isnewAgg"))) {
result.put("new", "Y");
}
}
if (aggMaps.containsKey("islimitedAgg")) {
if (getNLSMap((MultiBucketsAggregation) aggMaps.get("islimitedAgg"))) {
result.put("limited", "Y");
}
}
if (aggMaps.containsKey("specialofferAgg")) {
if (getNLSMap((MultiBucketsAggregation) aggMaps.get("specialofferAgg"))) {
result.put("specialoffer", "Y");
}
}
if (aggMaps.containsKey("isGlobalAgg")) {
if (getNLSMap((MultiBucketsAggregation) aggMaps.get("isGlobalAgg"))) {
result.put("is_global", "Y");
}
}
}
// 返回最新、限量、折扣的聚合结果
public void setNLS(Map<String, Aggregation> aggMaps, Map<String, Object> result) {
if (aggMaps.containsKey("isnewAgg")) {
if (getNLSMap((MultiBucketsAggregation) aggMaps.get("isnewAgg"))) {
result.put("new", "Y");
}
}
if (aggMaps.containsKey("islimitedAgg")) {
if (getNLSMap((MultiBucketsAggregation) aggMaps.get("islimitedAgg"))) {
result.put("limited", "Y");
}
}
if (aggMaps.containsKey("specialofferAgg")) {
if (getNLSMap((MultiBucketsAggregation) aggMaps.get("specialofferAgg"))) {
result.put("specialoffer", "Y");
}
}
if (aggMaps.containsKey("isGlobalAgg")) {
if (getNLSMap((MultiBucketsAggregation) aggMaps.get("isGlobalAgg"))) {
result.put("is_global", "Y");
}
}
}
private boolean getNLSMap(MultiBucketsAggregation aggregation) {
Iterator<? extends Bucket> itAgg = aggregation.getBuckets().iterator();
while (itAgg.hasNext()) {
Bucket bucket = itAgg.next();
// String bool = bucket.getKexy();
String bool = bucket.getKeyAsString();
if ("Y".equals(bool)) {
return true;
}
}
return false;
}
private boolean getNLSMap(MultiBucketsAggregation aggregation) {
Iterator<? extends Bucket> itAgg = aggregation.getBuckets().iterator();
while (itAgg.hasNext()) {
Bucket bucket = itAgg.next();
String bool = bucket.getKeyAsString();
if ("Y".equals(bool)) {
return true;
}
}
return false;
}
}
... ...
package com.yoho.search.service.scene.general;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yoho.core.redis.cluster.operations.serializer.RedisKeyBuilder;
import com.yoho.error.event.SearchEvent;
import com.yoho.search.base.utils.ConvertUtils;
import com.yoho.search.base.utils.EventReportEnum;
import com.yoho.search.base.utils.ISearchConstants;
import com.yoho.search.base.utils.ProductIndexEsField;
import com.yoho.search.cache.beans.AbstractCacheAbleService;
import com.yoho.search.cache.model.SearchCache;
import com.yoho.search.common.utils.HttpServletRequestUtils;
import com.yoho.search.cache.CacheTimeConstants;
import com.yoho.search.cache.beans.AbstractCacheComponent;
import com.yoho.search.common.SearchCommonService;
import com.yoho.search.common.SearchRequestParams;
import com.yoho.search.common.utils.SearchApiResultUtils;
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.core.es.utils.IgnoreSomeException;
import com.yoho.search.models.SearchApiResult;
import com.yoho.search.service.aggregations.impls.AggregationFactory;
import com.yoho.search.common.SearchCommonService;
import com.yoho.search.common.SearchRequestParams;
import com.yoho.search.service.helper.SearchCommonHelper;
import com.yoho.search.service.helper.SearchParamHelper;
import org.apache.commons.collections.MapUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import com.alibaba.fastjson.JSONArray;
import com.yoho.search.models.SearchApiResult;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
import org.slf4j.Logger;
... ... @@ -35,166 +32,141 @@ import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Service
public class SortGroupService extends AbstractCacheAbleService implements ApplicationEventPublisherAware {
private static Logger logger = LoggerFactory.getLogger(SortGroupService.class);
private static Logger CACHE_MATCH_REQUEST = LoggerFactory.getLogger("CACHE_MATCH_REQUEST");
@Autowired
private SearchCommonHelper searchCommonHelper;
@Autowired
private SearchCommonService searchCommonService;
@Autowired
private AggregationFactory aggregationFactory;
@Autowired
private SearchParamHelper searchParamHelper;
@Override
public SearchCache getSearchCache() {
return searchCacheFactory.getAggregationSearchCache();
}
ApplicationEventPublisher publisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
/**
* 对分类进行分组查询
*
* @needAllSort=1时过滤条件status和gender生效
* @否则其他参数也会生效
* @param paramMap
* @return
* @throws Exception
*/
public SearchApiResult sortGroup(Map<String, String> paramMap) {
try {
long begin = System.currentTimeMillis();
logger.info("[model=SearchSortGroupService][func=sortGroup][param={}][begin={}]", paramMap.toString(), begin);
// 如果包含参数needAllSort=1
SearchParam searchParam = new SearchParam();
if (!paramMap.containsKey("needAllSort") || !"1".equals(paramMap.get("needAllSort"))) {
searchParam = searchParamHelper.buildDefault(paramMap);
} else {
// needAllSort=1时过滤条件只有status和gender生效
searchParam.setQuery(QueryBuilders.matchAllQuery());
BoolQueryBuilder boolFilter = QueryBuilders.boolQuery();
if (paramMap.containsKey(SearchRequestParams.PARAM_SEARCH_STATUS)) {
boolFilter.must(QueryBuilders.termQuery(SearchRequestParams.PARAM_SEARCH_STATUS, paramMap.get(SearchRequestParams.PARAM_SEARCH_STATUS)));
}
// 性别
if (paramMap.containsKey(SearchRequestParams.PARAM_SEARCH_GENDER)) {
String[] genders = paramMap.get(SearchRequestParams.PARAM_SEARCH_GENDER).split(",");
boolFilter.must(QueryBuilders.termsQuery(ProductIndexEsField.gender, genders));
}
// 如果contain_global!=Y,则过滤掉全球购的商品[全球购商品融合需求]
if (!searchCommonHelper.containGlobal(paramMap)) {
boolFilter.mustNot(QueryBuilders.termQuery(ProductIndexEsField.isGlobal, "Y"));
}
if (boolFilter.hasClauses()) {
searchParam.setFiter(boolFilter);
}
}
// 构造聚合条件
List<AbstractAggregationBuilder<?>> sortGroupBuilders = new ArrayList<AbstractAggregationBuilder<?>>();
IAggregation sortGroupAggregation = aggregationFactory.getSortGroupAggregation(paramMap);
sortGroupBuilders.add(sortGroupAggregation.getBuilder());
searchParam.setAggregationBuilders(sortGroupBuilders);
// 设置查询结果
searchParam.setOffset(1);// just for cache
searchParam.setSize(0);
// 构造返回结果
SearchApiResult searchApiResult = new SearchApiResult();
searchApiResult.setCode(200);
searchApiResult.setMessage("sort List.");
// 先从缓存中获取,如果能取到,则直接返回
JSONObject cacheObject = searchCacheService.getJSONObjectFromCache(this.searchCache, ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
if (cacheObject != null) {
searchApiResult.setData(cacheObject);
CACHE_MATCH_REQUEST.info("match cache , url is :/sortgroup.json?" + HttpServletRequestUtils.genParamString(paramMap));
return searchApiResult;
}
// 进行检索
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
if (searchResult == null || searchResult.getAggMaps() == null || !searchResult.getAggMaps().containsKey("maxAgg")) {
searchApiResult.setData("");
return searchApiResult;
}
// 获取品类聚合结果
JSONArray sortGroups = (JSONArray) sortGroupAggregation.getAggregationResponseMap(searchResult.getAggMaps());
if (sortGroups == null) {
searchApiResult.setData("");
return searchApiResult;
}
// 构造data并加入缓存
JSONObject sortResult = new JSONObject();
sortResult.put("sort", sortGroups);
searchCacheService.addJSONObjectToCache(this.searchCache, indexName, searchParam, sortResult);
return searchApiResult.setData(sortResult);
} catch (Exception e) {
publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_SORTGROUP.getEventName(), EventReportEnum.SEARCHCONTROLLER_SORTGROUP.getFunctionName(),
EventReportEnum.SEARCHCONTROLLER_SORTGROUP.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
return SearchApiResultUtils.errorSearchApiResult(logger, paramMap, e);
}
}
public JSONArray sortGroup(Map<String, String> paramMap, BoolQueryBuilder mustFilter) {
try {
long begin = System.currentTimeMillis();
logger.info("[model=SearchSortGroupService][func=sortGroup][param={}][begin={}]", paramMap.toString(), begin);
SearchParam searchParam = searchParamHelper.buildWithMustFilter(paramMap, mustFilter);
// 构造聚合条件
List<AbstractAggregationBuilder<?>> sortGroupBuilders = new ArrayList<AbstractAggregationBuilder<?>>();
IAggregation sortGroupAggregation = aggregationFactory.getSortGroupAggregation(paramMap);
sortGroupBuilders.add(sortGroupAggregation.getBuilder());
searchParam.setAggregationBuilders(sortGroupBuilders);
// 设置返回结果为0
searchParam.setSize(0);
// 先从缓存中获取,如果能取到,则直接返回
JSONObject cacheObject = searchCacheService.getJSONObjectFromCache(this.searchCache, ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
if (cacheObject != null) {
return cacheObject.getJSONArray("sort");
}
// 进行检索
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
if (searchResult == null || searchResult.getAggMaps() == null || !searchResult.getAggMaps().containsKey("maxAgg")) {
return new JSONArray();
}
// 获取品类聚合结果
JSONArray sortGroups = (JSONArray) sortGroupAggregation.getAggregationResponseMap(searchResult.getAggMaps());
if (sortGroups == null) {
return new JSONArray();
}
JSONObject sortResult = new JSONObject();
sortResult.put("sort", sortGroups);
searchCacheService.addJSONObjectToCache(this.searchCache, indexName, searchParam, sortResult);
return sortGroups;
} catch (Exception e) {
publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_SORTGROUP.getEventName(), EventReportEnum.SEARCHCONTROLLER_SORTGROUP.getFunctionName(),
EventReportEnum.SEARCHCONTROLLER_SORTGROUP.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
return new JSONArray();
}
}
public class SortGroupService extends AbstractCacheComponent<JSONArray> implements ApplicationEventPublisherAware {
private static Logger logger = LoggerFactory.getLogger(SortGroupService.class);
private ApplicationEventPublisher publisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
@Autowired
private SearchCommonHelper searchCommonHelper;
@Autowired
private SearchCommonService searchCommonService;
@Autowired
private AggregationFactory aggregationFactory;
@Autowired
private SearchParamHelper searchParamHelper;
/**
* 对分类进行分组查询
*
* @param paramMap
* @return
* @throws Exception
* @needAllSort=1时过滤条件status和gender生效
* @否则其他参数也会生效
*/
public SearchApiResult sortGroup(Map<String, String> paramMap) {
try {
//1、构建paramQueryFilter
SearchParam searchParam;
if ("1".equals(MapUtils.getString(paramMap, "needAllSort"))) {
searchParam = this.buildSearchParamForNeedAllSort(paramMap);
} else {
searchParam = searchParamHelper.buildDefault(paramMap);
}
//2、调父类执行查询
JSONArray sortGroupResult = super.queryWithCache(searchParam, paramMap);
// 3、构造返回结果
SearchApiResult searchApiResult = new SearchApiResult();
searchApiResult.setCode(200);
searchApiResult.setMessage("sort List.");
JSONObject sortResult = new JSONObject();
sortResult.put("sort", sortGroupResult);
return searchApiResult.setData(sortResult);
} catch (Exception e) {
publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_SORTGROUP.getEventName(), EventReportEnum.SEARCHCONTROLLER_SORTGROUP.getFunctionName(),
EventReportEnum.SEARCHCONTROLLER_SORTGROUP.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
return SearchApiResultUtils.errorSearchApiResult(logger, paramMap, e);
}
}
/**
* 当needAllSort=1时,只有status和gender参数生效
*
* @param paramMap
* @return
*/
private SearchParam buildSearchParamForNeedAllSort(Map<String, String> paramMap) {
// 状态
BoolQueryBuilder boolFilter = QueryBuilders.boolQuery();
if (paramMap.containsKey(SearchRequestParams.PARAM_SEARCH_STATUS)) {
boolFilter.must(QueryBuilders.termQuery(SearchRequestParams.PARAM_SEARCH_STATUS, paramMap.get(SearchRequestParams.PARAM_SEARCH_STATUS)));
}
// 性别
if (paramMap.containsKey(SearchRequestParams.PARAM_SEARCH_GENDER)) {
List<String> genders = ConvertUtils.stringToStringList(paramMap.get(SearchRequestParams.PARAM_SEARCH_GENDER), ",");
boolFilter.must(QueryBuilders.termsQuery(ProductIndexEsField.gender, genders));
}
// 如果contain_global!=Y,则过滤掉全球购的商品[全球购商品融合需求]
if (!searchCommonHelper.containGlobal(paramMap)) {
boolFilter.mustNot(QueryBuilders.termQuery(ProductIndexEsField.isGlobal, "Y"));
}
SearchParam searchParam = new SearchParam();
searchParam.setFiter(boolFilter);
return searchParam;
}
public JSONArray sortGroup(Map<String, String> paramMap, BoolQueryBuilder mustFilter) {
try {
SearchParam searchParam = searchParamHelper.buildWithMustFilter(paramMap, mustFilter);
return super.queryWithCache(searchParam, paramMap);
} catch (Exception e) {
publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_SORTGROUP.getEventName(), EventReportEnum.SEARCHCONTROLLER_SORTGROUP.getFunctionName(),
EventReportEnum.SEARCHCONTROLLER_SORTGROUP.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
return new JSONArray();
}
}
@Override
protected JSONArray doRealQuery(SearchParam searchParam, Map<String, String> paramMap) throws Exception {
// 1、构造聚合条件
List<AbstractAggregationBuilder<?>> sortGroupBuilders = new ArrayList<AbstractAggregationBuilder<?>>();
IAggregation sortGroupAggregation = aggregationFactory.getSortGroupAggregation(paramMap);
sortGroupBuilders.add(sortGroupAggregation.getBuilder());
searchParam.setAggregationBuilders(sortGroupBuilders);
// 2、设置返回结果为0
searchParam.setSize(0);
// 3、进行检索
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
if (searchResult == null || searchResult.getAggMaps() == null || !searchResult.getAggMaps().containsKey("maxAgg")) {
return new JSONArray();
}
// 4、获取品类聚合结果
JSONArray sortGroups = (JSONArray) sortGroupAggregation.getAggregationResponseMap(searchResult.getAggMaps());
return sortGroups == null ? new JSONArray() : sortGroups;
}
@Override
protected int cacheTimeInMinute() {
return CacheTimeConstants.CACHE_15_MINUTE;
}
@Override
protected String cacheSceneKey() {
return "SORT_GROUP";
}
@Override
protected RedisKeyBuilder genRedisKeyBuilder(SearchParam searchParam, Map<String, String> paramMap) {
RedisKeyBuilder redisKeyBuilder = super.genRedisKeyBuilder(searchParam, paramMap);
redisKeyBuilder.appendFixed(":").appendFixed(MapUtils.getString(paramMap, SearchRequestParams.PARAM_SEARCH_NEEDSMALLSORT));//是否需要返回小分类
return redisKeyBuilder;
}
}
... ...
package com.yoho.search.service.scene.others;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import com.alibaba.fastjson.JSONObject;
import com.yoho.core.redis.cluster.operations.serializer.RedisKeyBuilder;
import com.yoho.search.aop.cache.SearchCacheAble;
import com.yoho.search.base.utils.CollectionUtils;
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.cache.CacheTimeConstants;
import com.yoho.search.cache.beans.AbstractCacheComponent;
import com.yoho.search.common.SearchCommonService;
import com.yoho.search.common.utils.SearchApiResultUtils;
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.service.helper.ProductListHelper;
import com.yoho.search.service.helper.SearchQueryHelper;
import com.yoho.search.service.index.ProductIndexBaseService;
import com.yoho.search.service.scorer.IScorer;
import com.yoho.search.service.scorer.YohoFilterFunctionBuilders;
import com.yoho.search.service.scorer.impl.FirstProductSknScorer;
import com.yoho.search.service.scorer.impl.RandomScorer;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.common.lucene.search.function.CombineFunction;
... ... @@ -26,336 +37,318 @@ 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.CollectionUtils;
import com.yoho.search.base.utils.ISearchConstants;
import com.yoho.search.base.utils.ProductIndexEsField;
import com.yoho.search.aop.cache.SearchCacheAble;
import com.yoho.search.cache.model.SearchCache;
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.service.scorer.YohoFilterFunctionBuilders;
import com.yoho.search.common.SearchCommonService;
import com.yoho.search.service.index.ProductIndexBaseService;
import com.yoho.search.service.helper.SearchQueryHelper;
import com.yoho.search.cache.beans.AbstractCacheAbleService;
import com.yoho.search.service.scorer.IScorer;
import com.yoho.search.service.scorer.impl.FirstProductSknScorer;
import com.yoho.search.service.scorer.impl.RandomScorer;
import java.util.*;
@Service
public class NewGoodProductSceneService extends AbstractCacheAbleService {
private static final Logger logger = LoggerFactory.getLogger(NewGoodProductSceneService.class);
@Autowired
private SearchCommonService searchCommonService;
@Autowired
private SearchQueryHelper searchQueryHelper;
@Autowired
private ProductIndexBaseService productIndexBaseService;
@Autowired
private ProductListHelper productListHelper;
@Override
public SearchCache getSearchCache() {
return searchCacheFactory.goodProductListSearchCache();
}
private static final String rec_product_skn = "rec_product_skn";// 配置的skn
private static final String user_product_skn = "user_product_skn";// 大数据推荐的skn
/**
* 首页的有好货商品接口
*
* @param paramMap
* @return
* @throws Exception
*/
@SearchCacheAble(cacheInMinute = 10, cacheName = "GOOD_PRODUCT_BY_SKN",excludeParams={ "uid","udid"})
public SearchApiResult goodProductListBySkn(Map<String, String> paramMap) throws Exception {
try {
// 1、获取skn参数
List<String> recProductSkns = stringToList(paramMap.getOrDefault(rec_product_skn, ""), ",");// 【配置的,要插到1、5、8的位置】
List<String> userProductSkns = stringToList(paramMap.getOrDefault(user_product_skn, ""), ",");
// 2、获取全部SKN
List<String> productSkns = new ArrayList<String>();
productSkns.addAll(recProductSkns);
productSkns.addAll(userProductSkns);
// 3、构造SearchParam
SearchParam searchParam = new SearchParam();
// 3.1构造filter
BoolQueryBuilder paramFilter = searchQueryHelper.constructFilterBuilder(paramMap, null);
BoolQueryBuilder goodProductDefaultFilter = this.getDefaultBoolQueryBuilder();
goodProductDefaultFilter.must(paramFilter);
goodProductDefaultFilter.must(QueryBuilders.termsQuery(ProductIndexEsField.productSkn, productSkns));
searchParam.setFiter(goodProductDefaultFilter);
// 3.2构造分页参数
searchParam.setOffset(0);
searchParam.setSize(productSkns.size());
// 3.3设置返回参数,节省带宽
List<String> includeFields = productIndexBaseService.getProductIndexIncludeFields();
includeFields.add(ProductIndexEsField.phrase);
searchParam.setIncludeFields(includeFields);
// 4、执行搜索并获取搜索结果
SearchResult searchResult = searchCommonService.doSearch(ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
List<Map<String, Object>> esProductList = searchResult.getResultList();
// 5、排序【recProductSkns插到1、5、8的位置】以及条数截取
esProductList = this.sortEsProductList(esProductList, productSkns, recProductSkns);
int pageSize = StringUtils.isBlank(paramMap.get("viewNum")) ? 10 : Integer.parseInt(paramMap.get("viewNum"));
esProductList = CollectionUtils.safeSubList(esProductList, 0, pageSize);
// 6、构造返回结果
JSONObject dataMap = new JSONObject();
dataMap.put("total", esProductList.size());
dataMap.put("page", 1);
dataMap.put("page_size", searchParam.getSize());
dataMap.put("page_total", 1);
dataMap.put("product_list", productListHelper.buildReturnInfoByEsSourceList(esProductList));
return new SearchApiResult().setData(dataMap);
} catch (Exception e) {
logger.error(e.getMessage(),e);
return new SearchApiResult().setCode(500).setMessage("Exception");
}
}
public SearchApiResult goodProductList(Map<String, String> paramMap) throws Exception {
// 1、检测分页参数
int pageSize = StringUtils.isBlank(paramMap.get("viewNum")) ? 30 : Integer.parseInt(paramMap.get("viewNum"));
int page = StringUtils.isBlank(paramMap.get("page")) ? 1 : Integer.parseInt(paramMap.get("page"));
if (page < 1 || pageSize < 0) {
return new SearchApiResult().setCode(400).setMessage("分页参数不合法");
}
// 2、获取推荐的skn参数【插到1、5、8的位置】
List<String> recProductSkns = stringToList(paramMap.getOrDefault(rec_product_skn, ""), ",");// 【配置的,要插到1、5、8的位置】
List<String> userProductSkns = stringToList(paramMap.getOrDefault(user_product_skn, ""), ",");
List<String> firstProductSkns = new ArrayList<String>();// 这些skn统一放到前面
firstProductSkns.addAll(recProductSkns);
firstProductSkns.addAll(userProductSkns);
// 3、构造搜索参数
SearchParam searchParam = new SearchParam();
// 3.1构造filter
BoolQueryBuilder paramFilter = searchQueryHelper.constructFilterBuilder(paramMap, null);
BoolQueryBuilder goodProductDefaultFilter = this.getDefaultBoolQueryBuilder();
goodProductDefaultFilter.must(paramFilter);
searchParam.setFiter(goodProductDefaultFilter);
// 3.2构造query
searchParam.setQuery(this.builderGoodProductQueryBuilder(paramMap, firstProductSkns));
// 3.3构造分页参数
searchParam.setOffset((page - 1) * pageSize);
searchParam.setSize(pageSize);
// 3.4、设置返回字段【节省带宽】
List<String> includeFields = productIndexBaseService.getProductIndexIncludeFields();
includeFields.add(ProductIndexEsField.phrase);
searchParam.setIncludeFields(includeFields);
// 4、构造排序条件
List<SortBuilder<?>> sortBuilders = new ArrayList<SortBuilder<?>>();
sortBuilders.add(SortBuilders.scoreSort().order(SortOrder.DESC));
sortBuilders.add(SortBuilders.fieldSort(ProductIndexEsField.heatValue).order(SortOrder.DESC));
sortBuilders.add(SortBuilders.fieldSort(ProductIndexEsField.id).order(SortOrder.DESC));
searchParam.setSortBuilders(sortBuilders);
// 5、从缓存中获取数据
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
JSONObject cacheObject = searchCacheService.getJSONObjectFromCache(this.searchCache, indexName, searchParam);
if (cacheObject != null) {
return new SearchApiResult().setData(cacheObject);
}
// 6、查询ES
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
if (searchResult == null) {
return new SearchApiResult().setCode(500).setMessage("execption");
}
// 7、构造返回结果
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());
List<Map<String, Object>> esProductList = this.sortEsProductList(searchResult.getResultList(), firstProductSkns, recProductSkns);// 处理一下商品的顺序;
List<Map<String, Object>> product_list = productListHelper.buildReturnInfoByEsSourceList(esProductList);
dataMap.put("product_list", product_list);// 处理一下商品的顺序;
// 8)将结果存进缓存
searchCacheService.addJSONObjectToCache(this.searchCache, indexName, searchParam, dataMap);
return new SearchApiResult().setData(dataMap);
}
/**
* 获取随机种子[X分钟内为用户生成的随机种子是一样的]
*
* @param paramMap
* @return
*/
private String getRandomSeed(Map<String, String> paramMap) {
int uid = MapUtils.getIntValue(paramMap, "uid", 0);
RedisKeyBuilder redisKeyBuilder = RedisKeyBuilder.newInstance().appendFixed("YOHOSEARCH:UserGPRandomSeed:").appendVar(uid);
JSONObject jsonObject = searchCacheService.getJSONObjectFromCache(this.searchCache, redisKeyBuilder);
if (jsonObject != null) {
return jsonObject.getString("UserGoodProductRandomSeed");
}
jsonObject = new JSONObject();
int seed = (int) (1000 * Math.random());
String randomSeed = new StringBuilder().append(uid).append("_").append(seed).toString();
jsonObject.put("UserGoodProductRandomSeed", seed);
searchCacheService.addJSONObjectToCache(this.searchCache, redisKeyBuilder, jsonObject);
return randomSeed;
}
private QueryBuilder builderGoodProductQueryBuilder(Map<String, String> paramMap, List<String> firstProductSkns) {
List<IScorer> scorers = new ArrayList<IScorer>();
// 1、添加recProductSkns
scorers.add(new FirstProductSknScorer(firstProductSkns));
// 2、添加随机函数[不包含需要硬插入的skn]
BoolQueryBuilder randomScorerFilter = QueryBuilders.boolQuery().mustNot(QueryBuilders.termsQuery(ProductIndexEsField.productSkn, firstProductSkns));
scorers.add(new RandomScorer(this.getRandomSeed(paramMap), randomScorerFilter));
// 3、构建
YohoFilterFunctionBuilders yohoFilterFunctionBuilders = new YohoFilterFunctionBuilders();
for (IScorer iScorer : scorers) {
if (iScorer != null) {
iScorer.addScorer(yohoFilterFunctionBuilders);
}
}
// 4、主推 【上衣、裙装、裤装、鞋靴 】
yohoFilterFunctionBuilders.add(QueryBuilders.termsQuery(ProductIndexEsField.maxSortId, Arrays.asList("1", "3", "4", "6")), ScoreFunctionBuilders.weightFactorFunction(10));
// 5、设置打分模式
FunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(QueryBuilders.matchAllQuery(), yohoFilterFunctionBuilders.getFilterFunctionBuilders());
functionScoreQueryBuilder.boostMode(CombineFunction.MULTIPLY);
return functionScoreQueryBuilder;
}
/**
* 有好货默认的过滤规则
*
* @return
*/
private BoolQueryBuilder getDefaultBoolQueryBuilder() {
BoolQueryBuilder boolFilter = QueryBuilders.boolQuery();
boolFilter.mustNot(QueryBuilders.termsQuery(ProductIndexEsField.isSeckill, "Y"));// 非秒杀
boolFilter.mustNot(QueryBuilders.termQuery(ProductIndexEsField.isFobbiden, 1));// 非fobbdien
boolFilter.mustNot(QueryBuilders.termQuery(ProductIndexEsField.attribute, 2));// 非赠品
boolFilter.mustNot(QueryBuilders.termQuery(ProductIndexEsField.isGlobal, "Y"));// 非全球购
boolFilter.mustNot(QueryBuilders.rangeQuery(ProductIndexEsField.breakSizePercent).gt(50));// 断码率小于50%
boolFilter.must(QueryBuilders.termQuery(ProductIndexEsField.isOutlets, 2));// 非奥莱
boolFilter.must(QueryBuilders.termQuery(ProductIndexEsField.status, 1));// 上架
boolFilter.must(QueryBuilders.rangeQuery(ProductIndexEsField.storageNum).gte(2));// 库存>2
boolFilter.must(QueryBuilders.termQuery(ProductIndexEsField.isPhraseExist, "Y"));// 短评存在
return boolFilter;
}
private List<String> stringToList(String source, String split) {
if (StringUtils.isBlank(source)) {
return new ArrayList<String>();
}
List<String> result = new ArrayList<String>();
for (String part : source.split(split)) {
result.add(part);
}
return result;
}
private List<Map<String, Object>> sortEsProductList(List<Map<String, Object>> esProductList, List<String> orderProductSkns, List<String> recProductSkns) {
// 1、校验
if (esProductList == null || esProductList.isEmpty()) {
return esProductList;
}
// 2、按skn的顺序对esProductList进行第一遍排序
if (orderProductSkns != null && !orderProductSkns.isEmpty()) {
esProductList = this.sortEsProductListBySknSort(esProductList, orderProductSkns);
}
List<Map<String, Object>> results = new ArrayList<Map<String, Object>>();
Map<String, Integer> keyCount = new HashMap<String, Integer>();
Iterator<Map<String, Object>> iterator = esProductList.iterator();
// 3、非推荐skn的品牌品类打散
while (iterator.hasNext()) {
Map<String, Object> product = iterator.next();
if (recProductSkns.contains(MapUtils.getString(product, "productSkn"))) {
continue;
}
String key = this.getSortKey(product);
int count = keyCount.getOrDefault(key, 1);
if (count <= 1) {
results.add(product);
iterator.remove();
}
keyCount.put(key, count + 1);
}
// 4、处理剩余的非推荐skn
iterator = esProductList.iterator();
while (iterator.hasNext()) {
Map<String, Object> product = iterator.next();
if (recProductSkns.contains(MapUtils.getString(product, "productSkn"))) {
continue;
}
results.add(product);
iterator.remove();
}
// 5、将推荐的skn按顺序插到指定位置
Map<String, Map<String, Object>> productInfo = new HashMap<String, Map<String, Object>>();
for (Map<String, Object> product : esProductList) {
productInfo.put(MapUtils.getString(product, "productSkn"), product);
}
int orginSize = results.size();
for (int i = 0; i < recProductSkns.size(); i++) {
Map<String, Object> product = productInfo.get(recProductSkns.get(i));
if (product == null) {
continue;
}
int index = getIndex(orginSize, results);
results.add(index, product);
}
return results;
}
private List<Map<String, Object>> sortEsProductListBySknSort(List<Map<String, Object>> esProductList, List<String> orderProductSkns) {
Map<String, Map<String, Object>> productMap = new LinkedHashMap<String, Map<String, Object>>();
for (Map<String, Object> product : esProductList) {
productMap.put(MapUtils.getString(product, "productSkn"), product);
}
List<Map<String, Object>> results = new ArrayList<Map<String, Object>>();
for (String productSkn : orderProductSkns) {
if (productMap.containsKey(productSkn)) {
results.add(productMap.get(productSkn));
productMap.remove(productSkn);
}
}
if (!productMap.isEmpty()) {
results.addAll(productMap.values());
}
return results;
}
private String getSortKey(Map<String, Object> product) {
int brandId = MapUtils.getInteger(product, ProductIndexEsField.brandId, 0);
int small_sort_id = MapUtils.getInteger(product, ProductIndexEsField.smallSortId, 0);
return brandId + "_" + small_sort_id;
}
private int getIndex(int orginSize, List<Map<String, Object>> results) {
int currenSize = results.size();
if (currenSize == orginSize) {
return 0;
}
if (currenSize - orginSize == 1) {
return currenSize > 4 ? 4 : currenSize;
}
if (currenSize - orginSize == 2) {
return currenSize > 7 ? 7 : currenSize;
}
return currenSize;
}
public class NewGoodProductSceneService extends AbstractCacheComponent<String> {
private static final Logger logger = LoggerFactory.getLogger(NewGoodProductSceneService.class);
@Autowired
private SearchCommonService searchCommonService;
@Autowired
private SearchQueryHelper searchQueryHelper;
@Autowired
private ProductIndexBaseService productIndexBaseService;
@Autowired
private ProductListHelper productListHelper;
private static final String rec_product_skn = "rec_product_skn";// 配置的skn
private static final String user_product_skn = "user_product_skn";// 大数据推荐的skn
/**
* 首页的有好货商品接口
*
* @param paramMap
* @return
* @throws Exception
*/
@SearchCacheAble(cacheInMinute = 10, cacheName = "GOOD_PRODUCT_BY_SKN", excludeParams = {"uid", "udid"})
public SearchApiResult goodProductListBySkn(Map<String, String> paramMap) {
try {
// 1、获取skn参数
List<String> recProductSkns = ConvertUtils.stringToStringList(paramMap.getOrDefault(rec_product_skn, ""), ",");// 【配置的,要插到1、5、8的位置】
List<String> userProductSkns = ConvertUtils.stringToStringList(paramMap.getOrDefault(user_product_skn, ""), ",");
// 2、获取全部SKN
List<String> productSkns = new ArrayList<String>();
productSkns.addAll(recProductSkns);
productSkns.addAll(userProductSkns);
// 3、构造SearchParam
SearchParam searchParam = new SearchParam();
// 3.1构造filter
BoolQueryBuilder paramFilter = searchQueryHelper.constructFilterBuilder(paramMap, null);
BoolQueryBuilder goodProductDefaultFilter = this.getDefaultBoolQueryBuilder();
goodProductDefaultFilter.must(paramFilter);
goodProductDefaultFilter.must(QueryBuilders.termsQuery(ProductIndexEsField.productSkn, productSkns));
searchParam.setFiter(goodProductDefaultFilter);
// 3.2构造分页参数
searchParam.setOffset(0);
searchParam.setSize(productSkns.size());
// 3.3设置返回参数,节省带宽
List<String> includeFields = productIndexBaseService.getProductIndexIncludeFields();
includeFields.add(ProductIndexEsField.phrase);
searchParam.setIncludeFields(includeFields);
// 4、执行搜索并获取搜索结果
SearchResult searchResult = searchCommonService.doSearch(ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
List<Map<String, Object>> esProductList = searchResult.getResultList();
// 5、排序【recProductSkns插到1、5、8的位置】以及条数截取
esProductList = this.sortEsProductList(esProductList, productSkns, recProductSkns);
int pageSize = StringUtils.isBlank(paramMap.get("viewNum")) ? 10 : Integer.parseInt(paramMap.get("viewNum"));
esProductList = CollectionUtils.safeSubList(esProductList, 0, pageSize);
// 6、构造返回结果
JSONObject dataMap = new JSONObject();
dataMap.put("total", esProductList.size());
dataMap.put("page", 1);
dataMap.put("page_size", searchParam.getSize());
dataMap.put("page_total", 1);
dataMap.put("product_list", productListHelper.buildReturnInfoByEsSourceList(esProductList));
return new SearchApiResult().setData(dataMap);
} catch (Exception e) {
return SearchApiResultUtils.errorSearchApiResult(logger, paramMap, e);
}
}
@SearchCacheAble(cacheInMinute = 10, cacheName = "GOOD_PRODUCT_LIST")
public SearchApiResult goodProductList(Map<String, String> paramMap) {
try {
// 1、检测分页参数
int pageSize = StringUtils.isBlank(paramMap.get("viewNum")) ? 30 : Integer.parseInt(paramMap.get("viewNum"));
int page = StringUtils.isBlank(paramMap.get("page")) ? 1 : Integer.parseInt(paramMap.get("page"));
if (page < 1 || pageSize < 0) {
return new SearchApiResult().setCode(400).setMessage("分页参数不合法");
}
// 2、获取推荐的skn参数【插到1、5、8的位置】
List<String> recProductSkns = ConvertUtils.stringToStringList(paramMap.getOrDefault(rec_product_skn, ""), ",");// 【配置的,要插到1、5、8的位置】
List<String> userProductSkns = ConvertUtils.stringToStringList(paramMap.getOrDefault(user_product_skn, ""), ",");
List<String> firstProductSkns = new ArrayList<String>();// 这些skn统一放到前面
firstProductSkns.addAll(recProductSkns);
firstProductSkns.addAll(userProductSkns);
// 3、构造搜索参数
SearchParam searchParam = new SearchParam();
// 3.1构造filter
BoolQueryBuilder paramFilter = searchQueryHelper.constructFilterBuilder(paramMap, null);
BoolQueryBuilder goodProductDefaultFilter = this.getDefaultBoolQueryBuilder();
goodProductDefaultFilter.must(paramFilter);
searchParam.setFiter(goodProductDefaultFilter);
// 3.2构造query
searchParam.setQuery(this.builderGoodProductQueryBuilder(paramMap, firstProductSkns));
// 3.3构造分页参数
searchParam.setOffset((page - 1) * pageSize);
searchParam.setSize(pageSize);
// 3.4、设置返回字段【节省带宽】
List<String> includeFields = productIndexBaseService.getProductIndexIncludeFields();
includeFields.add(ProductIndexEsField.phrase);
searchParam.setIncludeFields(includeFields);
// 4、构造排序条件
List<SortBuilder<?>> sortBuilders = new ArrayList<SortBuilder<?>>();
sortBuilders.add(SortBuilders.scoreSort().order(SortOrder.DESC));
sortBuilders.add(SortBuilders.fieldSort(ProductIndexEsField.heatValue).order(SortOrder.DESC));
sortBuilders.add(SortBuilders.fieldSort(ProductIndexEsField.id).order(SortOrder.DESC));
searchParam.setSortBuilders(sortBuilders);
// 5、查询ES
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
// 6、构造返回结果
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());
List<Map<String, Object>> esProductList = this.sortEsProductList(searchResult.getResultList(), firstProductSkns, recProductSkns);// 处理一下商品的顺序;
List<Map<String, Object>> product_list = productListHelper.buildReturnInfoByEsSourceList(esProductList);
dataMap.put("product_list", product_list);// 处理一下商品的顺序;
return new SearchApiResult().setData(dataMap);
} catch (Exception e) {
return SearchApiResultUtils.errorSearchApiResult(logger, paramMap, e);
}
}
private QueryBuilder builderGoodProductQueryBuilder(Map<String, String> paramMap, List<String> firstProductSkns) {
List<IScorer> scorers = new ArrayList<IScorer>();
// 1、添加recProductSkns
scorers.add(new FirstProductSknScorer(firstProductSkns));
// 2、添加随机函数[不包含需要硬插入的skn]
BoolQueryBuilder randomScorerFilter = QueryBuilders.boolQuery().mustNot(QueryBuilders.termsQuery(ProductIndexEsField.productSkn, firstProductSkns));
scorers.add(new RandomScorer(this.getRandomSeed(paramMap), randomScorerFilter));
// 3、构建
YohoFilterFunctionBuilders yohoFilterFunctionBuilders = new YohoFilterFunctionBuilders();
for (IScorer iScorer : scorers) {
if (iScorer != null) {
iScorer.addScorer(yohoFilterFunctionBuilders);
}
}
// 4、主推 【上衣、裙装、裤装、鞋靴 】
yohoFilterFunctionBuilders.add(QueryBuilders.termsQuery(ProductIndexEsField.maxSortId, Arrays.asList("1", "3", "4", "6")), ScoreFunctionBuilders.weightFactorFunction(10));
// 5、设置打分模式
FunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(QueryBuilders.matchAllQuery(), yohoFilterFunctionBuilders.getFilterFunctionBuilders());
functionScoreQueryBuilder.boostMode(CombineFunction.MULTIPLY);
return functionScoreQueryBuilder;
}
/**
* 有好货默认的过滤规则
*
* @return
*/
private BoolQueryBuilder getDefaultBoolQueryBuilder() {
BoolQueryBuilder boolFilter = QueryBuilders.boolQuery();
boolFilter.mustNot(QueryBuilders.termsQuery(ProductIndexEsField.isSeckill, "Y"));// 非秒杀
boolFilter.mustNot(QueryBuilders.termQuery(ProductIndexEsField.isFobbiden, 1));// 非fobbdien
boolFilter.mustNot(QueryBuilders.termQuery(ProductIndexEsField.attribute, 2));// 非赠品
boolFilter.mustNot(QueryBuilders.termQuery(ProductIndexEsField.isGlobal, "Y"));// 非全球购
boolFilter.mustNot(QueryBuilders.rangeQuery(ProductIndexEsField.breakSizePercent).gt(50));// 断码率小于50%
boolFilter.must(QueryBuilders.termQuery(ProductIndexEsField.isOutlets, 2));// 非奥莱
boolFilter.must(QueryBuilders.termQuery(ProductIndexEsField.status, 1));// 上架
boolFilter.must(QueryBuilders.rangeQuery(ProductIndexEsField.storageNum).gte(2));// 库存>2
boolFilter.must(QueryBuilders.termQuery(ProductIndexEsField.isPhraseExist, "Y"));// 短评存在
return boolFilter;
}
private List<Map<String, Object>> sortEsProductList(List<Map<String, Object>> esProductList, List<String> orderProductSkns, List<String> recProductSkns) {
// 1、校验
if (esProductList == null || esProductList.isEmpty()) {
return esProductList;
}
// 2、按skn的顺序对esProductList进行第一遍排序
if (orderProductSkns != null && !orderProductSkns.isEmpty()) {
esProductList = this.sortEsProductListBySknSort(esProductList, orderProductSkns);
}
List<Map<String, Object>> results = new ArrayList<Map<String, Object>>();
Map<String, Integer> keyCount = new HashMap<String, Integer>();
Iterator<Map<String, Object>> iterator = esProductList.iterator();
// 3、非推荐skn的品牌品类打散
while (iterator.hasNext()) {
Map<String, Object> product = iterator.next();
if (recProductSkns.contains(MapUtils.getString(product, "productSkn"))) {
continue;
}
String key = this.getSortKey(product);
int count = keyCount.getOrDefault(key, 1);
if (count <= 1) {
results.add(product);
iterator.remove();
}
keyCount.put(key, count + 1);
}
// 4、处理剩余的非推荐skn
iterator = esProductList.iterator();
while (iterator.hasNext()) {
Map<String, Object> product = iterator.next();
if (recProductSkns.contains(MapUtils.getString(product, "productSkn"))) {
continue;
}
results.add(product);
iterator.remove();
}
// 5、将推荐的skn按顺序插到指定位置
Map<String, Map<String, Object>> productInfo = new HashMap<String, Map<String, Object>>();
for (Map<String, Object> product : esProductList) {
productInfo.put(MapUtils.getString(product, "productSkn"), product);
}
int originSize = results.size();
for (int i = 0; i < recProductSkns.size(); i++) {
Map<String, Object> product = productInfo.get(recProductSkns.get(i));
if (product == null) {
continue;
}
int index = getIndex(originSize, results);
results.add(index, product);
}
return results;
}
private List<Map<String, Object>> sortEsProductListBySknSort(List<Map<String, Object>> esProductList, List<String> orderProductSkns) {
Map<String, Map<String, Object>> productMap = new LinkedHashMap<String, Map<String, Object>>();
for (Map<String, Object> product : esProductList) {
productMap.put(MapUtils.getString(product, "productSkn"), product);
}
List<Map<String, Object>> results = new ArrayList<Map<String, Object>>();
for (String productSkn : orderProductSkns) {
if (productMap.containsKey(productSkn)) {
results.add(productMap.get(productSkn));
productMap.remove(productSkn);
}
}
if (!productMap.isEmpty()) {
results.addAll(productMap.values());
}
return results;
}
private String getSortKey(Map<String, Object> product) {
int brandId = MapUtils.getInteger(product, ProductIndexEsField.brandId, 0);
int small_sort_id = MapUtils.getInteger(product, ProductIndexEsField.smallSortId, 0);
return brandId + "_" + small_sort_id;
}
private int getIndex(int orginSize, List<Map<String, Object>> results) {
int currenSize = results.size();
if (currenSize == orginSize) {
return 0;
}
if (currenSize - orginSize == 1) {
return currenSize > 4 ? 4 : currenSize;
}
if (currenSize - orginSize == 2) {
return currenSize > 7 ? 7 : currenSize;
}
return currenSize;
}
/**
* 获取随机种子[X分钟内为用户生成的随机种子是一样的]
*
* @param paramMap
* @return
*/
private String getRandomSeed(Map<String, String> paramMap) {
try {
return super.queryWithCache(null, paramMap);
} catch (Exception e) {
return "-1";
}
}
@Override
protected String doRealQuery(SearchParam searchParam, Map<String, String> paramMap) throws Exception {
int uid = MapUtils.getIntValue(paramMap, "uid", 0);
int seed = (int) (1000 * Math.random());
String randomSeed = new StringBuilder().append(uid).append("_").append(seed).toString();
return randomSeed;
}
@Override
protected int cacheTimeInMinute() {
return CacheTimeConstants.CACHE_15_MINUTE;
}
@Override
protected String cacheSceneKey() {
return "GOOD_PRODUCT_RANDOM_SEED";
}
@Override
protected RedisKeyBuilder genRedisKeyBuilder(SearchParam searchParam, Map<String, String> paramMap) {
RedisKeyBuilder redisKeyBuilder = defaultRedisKeyBuilder();
int uid = MapUtils.getIntValue(paramMap, "uid", 0);
redisKeyBuilder.appendFixed(":").appendVar(uid);//uid
return redisKeyBuilder;
}
}
... ...
... ... @@ -12,7 +12,6 @@ import com.yoho.search.models.SearchApiResult;
import com.yoho.search.service.aggregations.AggregationsService;
import com.yoho.search.service.aggregations.impls.AggregationFactory;
import com.yoho.search.service.helper.SearchParamHelper;
import com.yoho.search.service.recall.models.common.ParamQueryFilter;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
... ... @@ -41,12 +40,13 @@ public class AggBrandService extends AbstractCacheComponent<JSONArray> {
try {
// 1、构造带filter和query的SearchParam
boolean needPreAggregation = "Y".equals(paramMap.getOrDefault(SearchRequestParams.PARAM_SEARCH_AGG_WITH_PARAM_BRAND, "N")) ? false : true;
String filterParamName = needPreAggregation ? "brand" : null;
ParamQueryFilter paramFilter = searchParamHelper.buildParamQueryFilter(paramMap, mustFilter, filterParamName);
JSONArray brandJSONArray = super.queryWithCache(paramFilter, paramMap);
SearchParam searchParam = searchParamHelper.buildSearchParam(paramMap, false, mustFilter, needPreAggregation ? "brand" : null);
// 2、调父类方法执行查询
JSONArray brandJSONArray = super.queryWithCache(searchParam, paramMap);
return new SearchApiResult().setData(brandJSONArray);
} catch (Exception e) {
return SearchApiResultUtils.defaultErrorSearchApiResult(logger,e);
return SearchApiResultUtils.defaultErrorSearchApiResult(logger, e);
}
}
... ... @@ -61,20 +61,15 @@ public class AggBrandService extends AbstractCacheComponent<JSONArray> {
}
@Override
protected JSONArray doRealQuery(ParamQueryFilter paramQueryFilter, Map<String, String> paramMap) throws Exception {
// 1、构造带filter和query的SearchParam
SearchParam searchParam = new SearchParam();
searchParam.setQuery(paramQueryFilter.getParamQuery());
searchParam.setFiter(paramQueryFilter.getParamFilter());
// 2、构造aggrations
protected JSONArray doRealQuery(SearchParam searchParam,Map<String, String> paramMap) throws Exception {
// 1、构造aggrations
IAggregation brandAggregation = aggregationFactory.getBrandAggregation(paramMap);
searchParam.setAggregationBuilders(Arrays.asList(brandAggregation.getBuilder()));
// 3、从ES中获取
// 2、从ES中获取
JSONObject jsonObject = aggregationsService.getAggNameAndResponse(brandAggregation, searchParam);
// 4、生成结果
// 3、生成结果
JSONArray brandJSONArray = jsonObject.getJSONArray(brandAggregation.aggName());
return brandJSONArray;
}
... ...
... ... @@ -53,13 +53,13 @@ public class RecommendBrandService extends AbstractCacheComponent<JSONArray> {
needPreAggregation = false;
}
// 3、构造paramQueryFilter
ParamQueryFilter paramQueryFilter = searchParamHelper.buildParamQueryFilter(paramMap, true, null, needPreAggregation ? "brand" : null);
// 3、构造searchParam
SearchParam searchParam = searchParamHelper.buildSearchParam(paramMap, true, null, needPreAggregation ? "brand" : null);
// 4、执行查询
JSONArray brandJSONArray = super.queryWithCache(paramQueryFilter, paramMap);
// 5、执行查询
JSONArray brandJSONArray = super.queryWithCache(searchParam, paramMap);
// 5、返回结果
// 6、返回结果
return new SearchApiResult().setData(brandJSONArray);
} catch (Exception e) {
return SearchApiResultUtils.defaultErrorSearchApiResult(logger,e);
... ... @@ -67,22 +67,18 @@ public class RecommendBrandService extends AbstractCacheComponent<JSONArray> {
}
@Override
protected JSONArray doRealQuery(ParamQueryFilter paramQueryFilter, Map<String, String> paramMap) throws Exception {
// 1、构建带queryBuilder和filter的SearchParam
SearchParam searchParam = searchParamHelper.buildSearchParam(paramQueryFilter);
// 2、构造聚合
protected JSONArray doRealQuery(SearchParam searchParam, Map<String, String> paramMap) throws Exception {
// 1、构造聚合
int recommendBrandCount = MapUtils.getIntValue(paramMap, SearchRequestParams.PARAM_SEARCH_VIEWNUM, 8);
IAggregation recommendBrandAgg = aggregationFactory.getRecommendBrandAggregation(paramMap, recommendBrandCount);
searchParam.setAggregationBuilders(Arrays.asList(recommendBrandAgg.getBuilder()));
// 3、查询es
// 2、查询es
JSONObject recommendBrandResult = aggregationsService.getAggNameAndResponse(recommendBrandAgg, searchParam);
if (recommendBrandResult == null) {
return new JSONArray();
}
// 4、生成结果
// 3、生成结果
return recommendBrandResult.getJSONArray(recommendBrandAgg.aggName());
}
... ... @@ -97,8 +93,8 @@ public class RecommendBrandService extends AbstractCacheComponent<JSONArray> {
}
@Override
protected RedisKeyBuilder genRedisKeyBuilder(ParamQueryFilter paramQueryFilter, Map<String,String> paramMap){
RedisKeyBuilder redisKeyBuilder = super.genRedisKeyBuilder(paramQueryFilter,paramMap);
protected RedisKeyBuilder genRedisKeyBuilder(SearchParam searchParam, Map<String,String> paramMap){
RedisKeyBuilder redisKeyBuilder = super.genRedisKeyBuilder(searchParam,paramMap);
int recommendBrandCount = MapUtils.getIntValue(paramMap, SearchRequestParams.PARAM_SEARCH_VIEWNUM, 8);
redisKeyBuilder.appendFixed(":").appendVar(recommendBrandCount);
return redisKeyBuilder;
... ...