Authored by wangnan

实时skn促销列表需求

... ... @@ -2,6 +2,7 @@ package com.yoho.search.service.aggregations.impls;
import com.yoho.search.core.es.agg.IAggregation;
import com.yoho.search.service.base.index.*;
import com.yoho.search.service.base.index.promotion.PromotionIndexBaseService;
import com.yoho.search.service.helper.SearchAfterCacheHelper;
import com.yoho.search.service.scorer.personal.PersonalVectorFeatureSearch;
import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -27,13 +28,15 @@ public class AggregationFactoryService {
@Autowired
private ShopsIndexBaseService shopsIndexBaseService;
@Autowired
private PromotionIndexBaseService promotionIndexBaseService;
private ZqNameIndexBaseService zqNameIndexBaseService;
@Autowired
private PersonalVectorFeatureSearch personalVectorFeatureSearch;
@Autowired
private ProductIndexBaseService productIndexBaseService;
@Autowired
private CustomizeTagBaseService customizeTagBaseService;
@Autowired
private PromotionIndexBaseService promotionIndexBaseService;
public IAggregation getAgeLevelAggregation() {
return new AgeLevelAggregation();
... ... @@ -124,7 +127,7 @@ public class AggregationFactoryService {
}
public IAggregation getPromotionAggregation(int aggCount) {
return new PromotionAggregation(promotionIndexBaseService, aggCount);
return new PromotionAggregation(zqNameIndexBaseService, aggCount);
}
public IAggregation getKeywordAggregation(Map<String, String> paramMap, int aggCount) {
... ...
package com.yoho.search.service.aggregations.impls;
import com.yoho.search.base.utils.ProductIndexEsField;
import com.yoho.search.service.base.index.ZqNameIndexBaseService;
import org.apache.commons.collections.CollectionUtils;
import org.elasticsearch.search.aggregations.Aggregation;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.commons.collections.CollectionUtils;
import org.elasticsearch.search.aggregations.Aggregation;
import com.yoho.search.base.utils.ProductIndexEsField;
import com.yoho.search.service.base.index.PromotionIndexBaseService;
/**
* Created by wangnan on 2017/5/11.
*/
public class PromotionAggregation extends AbstractSingleFieldAggregation {
private PromotionIndexBaseService promotionIndexBaseService;
private ZqNameIndexBaseService zqNameIndexBaseService;
public PromotionAggregation(PromotionIndexBaseService promotionIndexBaseService, int count) {
public PromotionAggregation(ZqNameIndexBaseService zqNameIndexBaseService, int count) {
super(count);
this.promotionIndexBaseService = promotionIndexBaseService;
this.zqNameIndexBaseService = zqNameIndexBaseService;
}
@Override
... ... @@ -49,10 +48,10 @@ public class PromotionAggregation extends AbstractSingleFieldAggregation {
if (CollectionUtils.isEmpty(promotionIdList)) {
return new ArrayList<>();
}
// 调用promotion索引查询title
// 调用zqname索引查询title
Map<String, String> promotionParam = new HashMap<>();
promotionParam.put("ids", promotionIdList.stream().collect(Collectors.joining(",")));
List<Map<String, Object>> promotionList = promotionIndexBaseService.queryListByParam(promotionParam);
List<Map<String, Object>> promotionList = zqNameIndexBaseService.queryZQNameListByParam(promotionParam);
// promotion_title去重,is_promotion用逗号连接
Map<String, Map<String, Object>> titleMap = new HashMap<>();
for (Map<String, Object> map : promotionList) {
... ...
package com.yoho.search.service.aggregations.impls;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import com.yoho.search.base.utils.DateUtil;
import com.yoho.search.base.utils.ISearchConstants;
import com.yoho.search.base.utils.ProductIndexEsField;
import com.yoho.search.core.es.agg.AbstractAggregation;
import com.yoho.search.models.RecommendPromotionAggVO;
import com.yoho.search.service.base.index.promotion.PromotionIndexBaseService;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
... ... @@ -17,12 +17,11 @@ import org.elasticsearch.search.aggregations.bucket.nested.NestedAggregationBuil
import org.elasticsearch.search.aggregations.bucket.terms.LongTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import com.yoho.search.base.utils.DateUtil;
import com.yoho.search.base.utils.ISearchConstants;
import com.yoho.search.base.utils.ProductIndexEsField;
import com.yoho.search.core.es.agg.AbstractAggregation;
import com.yoho.search.models.RecommendPromotionAggVO;
import com.yoho.search.service.base.index.PromotionIndexBaseService;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class RecommendPromotionAggregation extends AbstractAggregation {
private static final String TERM_AGGREGATION_NAME = "promotionIdAgg";
... ...
... ... @@ -5,6 +5,9 @@ import com.alibaba.fastjson.JSONObject;
import com.yoho.search.base.models.PromotionCond;
import com.yoho.search.base.utils.DateUtil;
import com.yoho.search.base.utils.ProductIndexEsField;
import com.yoho.search.service.base.index.promotion.PromotionCondService;
import com.yoho.search.service.base.index.promotion.PromotionMatchService;
import com.yoho.search.service.base.index.promotion.PromotionTypeService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
... ... @@ -28,7 +31,11 @@ public class ProductIndexBaseService {
@Autowired
private ProductPricePlanIndexBaseService productPricePlanIndexBaseService;
@Autowired
private PromotionIndexBaseService promotionIndexBaseService;
private PromotionCondService promotionCondService;
@Autowired
private PromotionMatchService promotionMatchService;
@Autowired
private PromotionTypeService promotionTypeService;
// 获取从source中不返回的字段定义,用以节省带宽
... ... @@ -348,48 +355,55 @@ public class ProductIndexBaseService {
/**
* 获取商品列表[并返回促销信息]
* 获取商品列表[并返回促销标签信息]
* add by wangnan in 2018/1/29
*/
public List<Map<String, Object>> getProductListWithPromotion(List<Map<String, Object>> productEsSourceList) {
if (productEsSourceList == null || productEsSourceList.isEmpty()) {
return new ArrayList<>();
}
//获取结果列表中的skn
//1.获取结果列表中的skn列表
String[] sknStr = new String[productEsSourceList.size()];
for (int i = 0; i < productEsSourceList.size(); i++) {
sknStr[i] = MapUtils.getString(productEsSourceList.get(i), "product_skn", "");
}
//全量查promotion索引内容,1分钟缓存
List<Map<String, Object>> results = new ArrayList<Map<String, Object>>();
List<PromotionCond> promotionCondList = promotionIndexBaseService.getPromotionCondList();
//处理每个skn匹配的促销
//2.全量查promotion索引内容,用于和每个skn匹配,1分钟缓存
List<PromotionCond> promotionCondList = promotionCondService.getPromotionCondList();
//3.构建每个skn匹配的促销
List<Map<String, Object>> results = new ArrayList<Map<String, Object>>();
for (Map<String, Object> productEsSource : productEsSourceList) {
//获取商品信息map
//3.1 获取skn字段信息
Map<String, Object> productMap = this.getProductMapFromEsSource(productEsSource);
//获取该skn匹配上的促销
//3.2 获取该skn匹配上的促销
List<PromotionCond> matchedPromotionCondList = promotionCondList.stream()
.filter(promotionCond -> promotionIndexBaseService.matchProduct(promotionCond, productMap)).collect(Collectors.toList());
//TODO: 查询促销类型->促销名映射的索引
Map<String, String> promotionTypeMap = new HashMap<>();
.filter(promotionCond -> promotionMatchService.matchProduct(promotionCond, productMap))
.collect(Collectors.toList());
//3.3 查询促销类型->促销名映射的索引获取map,用于填充促销标签名称,1分钟缓存
Map<String, String> promotionTypeMap = promotionTypeService.getPromotionTypeMap();
//3.4 生成促销标签对象列表
if (CollectionUtils.isNotEmpty(matchedPromotionCondList)) {
List<JSONObject> matchedPromotions = matchedPromotionCondList.stream().map(promotionCond -> {
JSONObject matchedPromotion = new JSONObject();
matchedPromotion.put("id", promotionCond.getPromotionId());
matchedPromotion.put("type", promotionCond.getPromotionType());
matchedPromotion.put("startTime", promotionCond.getStartTime());
matchedPromotion.put("endTime", promotionCond.getEndTime());
if (!promotionTypeMap.isEmpty() && promotionCond.getShowStatus() == 1) {
matchedPromotion.put("name", promotionTypeMap.get(promotionCond.getPromotionType()));
}
return matchedPromotion;
}).collect(Collectors.toList());
//插入促销信息
List<JSONObject> matchedPromotions = matchedPromotionCondList.stream()
.map(promotionCond -> {
JSONObject matchedPromotion = new JSONObject();
matchedPromotion.put("id", promotionCond.getPromotionId());
matchedPromotion.put("type", promotionCond.getPromotionType());
matchedPromotion.put("startTime", promotionCond.getStartTime());
matchedPromotion.put("endTime", promotionCond.getEndTime());
if (!promotionTypeMap.isEmpty() && promotionCond.getShowStatus() == 1) {
matchedPromotion.put("name", promotionTypeMap.get(promotionCond.getPromotionType()));
}else{
matchedPromotion.put("name", "undefined");
}
return matchedPromotion;
}).collect(Collectors.toList());
//3.5 列表中插入促销标签信息
productMap.put("promotion_tag", matchedPromotions);
}
results.add(productMap);
}
return results;
}
}
... ...
package com.yoho.search.service.base.index;
import com.yoho.search.base.utils.ConvertUtils;
import com.yoho.search.base.utils.ISearchConstants;
import com.yoho.search.core.es.model.SearchParam;
import com.yoho.search.core.es.model.SearchResult;
import com.yoho.search.service.base.SearchCommonService;
import com.yoho.search.service.base.index.promotion.PromotionIndexBaseService;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Author: wangnan
* @Date: Created in 2018/1/29
* 专区名称索引服务,用于促销标签聚合里面
*/
@Service
public class ZqNameIndexBaseService {
@Autowired
private SearchCommonService searchCommonService;
private static final Logger logger = LoggerFactory.getLogger(PromotionIndexBaseService.class);
private static final String INDEX_NAME = ISearchConstants.INDEX_NAME_ZQ_NAME;
public List<Map<String, Object>> queryZQNameListByParam(Map<String, String> paramMap) {
try {
// 1、构建SearchParam
SearchParam searchParam = new SearchParam();
BoolQueryBuilder boolFilterForShops = this.constructFilterBuilder(paramMap);
searchParam.setFiter(boolFilterForShops);
searchParam.setSize(10000);
searchParam.setQuery(QueryBuilders.matchAllQuery());
// 2、调搜索,并将结果加入缓存
List<Map<String, Object>> promotionsList = this.queryZQNameListByParam(searchParam);
return promotionsList;
} catch (Exception e) {
logger.error(e.getMessage(), e);
return new ArrayList<>();
}
}
private List<Map<String, Object>> queryZQNameListByParam(SearchParam searchParam) {
List<Map<String, Object>> results = new ArrayList<Map<String, Object>>();
SearchResult searchResult = searchCommonService.doSearch(INDEX_NAME, searchParam);
if (searchResult == null || searchResult.getResultList() == null || searchResult.getResultList().isEmpty()) {
return results;
}
for (Map<String, Object> esMap : searchResult.getResultList()) {
results.add(this.getMap(esMap));
}
return results;
}
private BoolQueryBuilder constructFilterBuilder(Map<String, String> paramMap) {
BoolQueryBuilder boolFilter = QueryBuilders.boolQuery();
if (paramMap.containsKey("ids") && StringUtils.isNotBlank(paramMap.get("ids"))) {
int[] ids = ConvertUtils.stringToIntArray(paramMap.get("ids"), ",");
boolFilter.must(QueryBuilders.termsQuery("id", ids));
}
return boolFilter;
}
private Map<String, Object> getMap(Map<String, Object> esMap) {
Map<String, Object> map = new HashMap<>();
int id = MapUtils.getIntValue(esMap, "id", 0);
map.put("is_promotion", id + "");
map.put("promotion_title", MapUtils.getString(esMap, "title", ""));
return map;
}
}
... ...
package com.yoho.search.service.base.index;
package com.yoho.search.service.base.index.promotion;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.yoho.search.base.helper.PromotionHelper;
import com.yoho.search.base.models.PromotionCond;
import com.yoho.search.base.models.PromotionIndexBO;
import com.yoho.search.base.models.PromotionMatchFactor;
import com.yoho.search.base.utils.ConvertUtils;
import com.yoho.search.base.utils.DateUtil;
import com.yoho.search.base.utils.ISearchConstants;
import com.yoho.search.base.utils.ProductIndexEsField;
import com.yoho.search.core.es.model.SearchParam;
import com.yoho.search.core.es.model.SearchResult;
import com.yoho.search.models.RecommendPromotionAggVO;
import com.yoho.search.service.base.SearchCommonService;
import com.yoho.search.service.base.SearchRequestParams;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.slf4j.Logger;
... ... @@ -27,52 +19,50 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* Created by wangnan on 2017/5/11.
* 用于生成promotionCondList列表,判断skn匹配的促销,1分钟缓存。
* @Author: wangnan
* @Date: Created in 2018/1/29
*/
@Service
public class PromotionIndexBaseService {
public class PromotionCondService {
@Autowired
private SearchCommonService searchCommonService;
private static final Logger logger = LoggerFactory.getLogger(PromotionIndexBaseService.class);
private static final String INDEX_NAME = ISearchConstants.INDEX_NAME_PROMOTION;
private static final String CACHEKEY = "CacheKey";
private static final String PROMOTIONCONDLISTCACHEKEY = "PromotionCondListCacheKey";
private static final Logger logger = LoggerFactory.getLogger(PromotionCondService.class);
private static final String CACHE_KEY = "CacheKey";
private static final String PROMOTION_COND_LIST_CACHE_KEY = "promotionCondListCacheKey";
private volatile List<PromotionCond> promotionCondList = new ArrayList<>();
//PromotionCondList Guava Cache
LoadingCache<String, JSONObject> PromotionCondListCache = CacheBuilder.newBuilder()
LoadingCache<String, JSONObject> promotionCondListCache = CacheBuilder.newBuilder()
.maximumSize(30000)
.expireAfterWrite(1, TimeUnit.MINUTES)
.build(new CacheLoader<String, JSONObject>() {
public JSONObject load(String key) {
JSONObject jsonObject = new JSONObject();
jsonObject.put(PROMOTIONCONDLISTCACHEKEY, buildPromotionCondList());
jsonObject.put(PROMOTION_COND_LIST_CACHE_KEY, buildPromotionCondList());
return jsonObject;
}
});
@Autowired
private SearchCommonService searchCommonService;
@Autowired
private PromotionHelper promotionHelper;
/*******************************以下方法用于生成商品列表中每个skn的促销列表逻辑**********************************************/
/**
* 获取PromotionCondList,走缓存,1分钟
*/
public List<PromotionCond> getPromotionCondList() {
try {
JSONObject jsonObject = PromotionCondListCache.get(CACHEKEY);
JSONObject jsonObject = promotionCondListCache.get(CACHE_KEY);
Assert.isTrue(jsonObject != null, "[cache jsonObject cannot be null][fun=getPromotionCondList]");
promotionCondList = (List<PromotionCond>) jsonObject.get(PROMOTIONCONDLISTCACHEKEY);
promotionCondList = (List<PromotionCond>) jsonObject.get(PROMOTION_COND_LIST_CACHE_KEY);
} catch (Exception e) {
logger.error(e.getMessage());
}
... ... @@ -171,15 +161,15 @@ public class PromotionIndexBaseService {
Assert.notEmpty(conditionParamJSONObj, "conditionParamJSONObj cannot be empty");
promotionCond.setAggregator(PromotionCond.Aggregator.from(conditionParamJSONObj.getString("aggregator")));
// conditions可能是数组或者对象
Object condtionsObj = conditionParamJSONObj.get("conditions");
if (condtionsObj instanceof JSONArray) {
JSONArray condtionsJSONArr = (JSONArray) condtionsObj;
Assert.notEmpty(condtionsJSONArr, "condtionsJSONArr is empty For " + promotionIndexBO.getId());
promotionCond.setCondDetailList(condtionsJSONArr.stream().map(obj -> (JSONObject) obj).map(e -> constructPromotionCondDetail(e)).collect(Collectors.toList()));
Object conditionsObject = conditionParamJSONObj.get("conditions");
if (conditionsObject instanceof JSONArray) {
JSONArray conditionsJSONArr = (JSONArray) conditionsObject;
Assert.notEmpty(conditionsJSONArr, "conditionsJSONArr is empty For " + promotionIndexBO.getId());
promotionCond.setCondDetailList(conditionsJSONArr.stream().map(obj -> (JSONObject) obj).map(e -> constructPromotionCondDetail(e)).collect(Collectors.toList()));
} else {
JSONObject condtionsJSONObj = (JSONObject) condtionsObj;
Assert.notEmpty(condtionsJSONObj, "condtionsJSONObj is empty For " + promotionIndexBO.getId());
promotionCond.setCondDetailList(condtionsJSONObj.keySet().stream().map(key -> condtionsJSONObj.getJSONObject(key)).map(e -> constructPromotionCondDetail(e)).collect(Collectors.toList()));
JSONObject conditionsJSONObj = (JSONObject) conditionsObject;
Assert.notEmpty(conditionsJSONObj, "conditionsJSONObj is empty For " + promotionIndexBO.getId());
promotionCond.setCondDetailList(conditionsJSONObj.keySet().stream().map(key -> conditionsJSONObj.getJSONObject(key)).map(e -> constructPromotionCondDetail(e)).collect(Collectors.toList()));
}
Assert.notEmpty(promotionCond.getCondDetailList(), "condDetailList cannot be empty");
return promotionCond;
... ... @@ -197,17 +187,17 @@ public class PromotionIndexBaseService {
PromotionCond.CondDetail condDetail = new PromotionCond.CondDetail();
condDetail.setAggregator(PromotionCond.Aggregator.from(condDetailJSONObj.getString("aggregator")));
// conditions可能是数组或者对象
Object condtionsObj = condDetailJSONObj.get("conditions");
if (condtionsObj == null) {
Object conditionsObj = condDetailJSONObj.get("conditions");
if (conditionsObj == null) {
condDetail.setCondItemList(new ArrayList<>());
return condDetail;
}
if (condtionsObj instanceof JSONArray) {
JSONArray condItemsJSONArray = (JSONArray) condtionsObj;
if (conditionsObj instanceof JSONArray) {
JSONArray condItemsJSONArray = (JSONArray) conditionsObj;
condDetail.setCondItemList(condItemsJSONArray.isEmpty() ? new ArrayList<>() :
condItemsJSONArray.stream().map(obj -> (JSONObject) obj).map(e -> constructPromotionCondItemBO(e)).collect(Collectors.toList()));
} else {
JSONObject condItemsJSONObj = (JSONObject) condtionsObj;
JSONObject condItemsJSONObj = (JSONObject) conditionsObj;
condDetail.setCondItemList(condItemsJSONObj.isEmpty() ? new ArrayList<>() :
condItemsJSONObj.keySet().stream().map(key -> condItemsJSONObj.getJSONObject(key)).map(e -> constructPromotionCondItemBO(e)).collect(Collectors.toList()));
}
... ... @@ -215,7 +205,7 @@ public class PromotionIndexBaseService {
}
/**
* 构建PromotionCondDetail中的CondItemB
* 构建PromotionCondDetail中的CondItem
*/
private PromotionCond.CondItem constructPromotionCondItemBO(JSONObject condItemJSONObj) {
Assert.notEmpty(condItemJSONObj, "condItemJSONObj cannot be empty");
... ... @@ -226,137 +216,4 @@ public class PromotionIndexBaseService {
Assert.notNull(condItem);
return condItem;
}
/**
* 用matchCondDetail
*/
public boolean matchProduct(PromotionCond promotionCond, Map<String, Object> productMap) {
boolean matchResult;
if (promotionCond == null) {
return false;
}
if (promotionCond.getAggregator() == PromotionCond.Aggregator.ALL) {
matchResult = promotionCond.getCondDetailList().stream().allMatch(condDetail -> matchCondDetail(condDetail, productMap));
} else {
matchResult = promotionCond.getCondDetailList().stream().anyMatch(condDetail -> matchCondDetail(condDetail, productMap));
}
if (matchResult) {
logger.debug("[func=PromotionCond.matchResult][skn={}][promotionId={}][promotionTitle={}]",
MapUtils.getIntValue(productMap, "id"), promotionCond.getPromotionId(), promotionCond.getPromotionTitle());
}
return matchResult;
}
/**
* 匹配matchCondDetail
*/
private boolean matchCondDetail(PromotionCond.CondDetail condDetail, Map<String, Object> productMap) {
if (CollectionUtils.isEmpty(condDetail.getCondItemList())) {
// 当没有具体条件,比如【全场满99元加5元换购YOHO!当期热销新刊】这种时所有productindex都匹配
return true;
} else if (condDetail.getAggregator() == PromotionCond.Aggregator.ALL) {
return condDetail.getCondItemList().stream().allMatch(condItem -> matchProduct(condItem, productMap));
} else {
return condDetail.getCondItemList().stream().anyMatch(condItem -> matchProduct(condItem, productMap));
}
}
/**
* 生成一个参数对象去匹配促销,逻辑抽到了core工程的helper中
*/
private boolean matchProduct(PromotionCond.CondItem condItem, Map<String, Object> productMap) {
PromotionMatchFactor promotionMatchFactor = new PromotionMatchFactor();
promotionMatchFactor.setBrandId(MapUtils.getIntValue(productMap, "brand_id"));
promotionMatchFactor.setSmallSortId(MapUtils.getIntValue(productMap, "smal_sort_id"));
promotionMatchFactor.setMiddleSortId(MapUtils.getIntValue(productMap, "middle_sort_id"));
promotionMatchFactor.setMaxSortId(MapUtils.getIntValue(productMap, "max_sort_id"));
promotionMatchFactor.setIspromotion(MapUtils.getIntValue(productMap, "is_promotion"));
promotionMatchFactor.setProductskn(MapUtils.getIntValue(productMap, "product_skn"));
return promotionHelper.matchProduct(condItem, promotionMatchFactor);
}
/*******************************以下方法用于促销标签聚合逻辑***************************************************/
public List<Map<String, Object>> queryListByParam(Map<String, String> paramMap) {
try {
// 1、构建SearchParam
SearchParam searchParam = new SearchParam();
BoolQueryBuilder boolFilterForShops = this.constructFilterBuilder(paramMap);
searchParam.setFiter(boolFilterForShops);
searchParam.setSize(10000);
searchParam.setQuery(QueryBuilders.matchAllQuery());
// 2、调搜索,并将结果加入缓存
List<Map<String, Object>> promotionsList = this.queryListByParam(searchParam);
return promotionsList;
} catch (Exception e) {
logger.error(e.getMessage(), e);
return new ArrayList<>();
}
}
public List<RecommendPromotionAggVO> getPromotionInfosByIds(String indexName, List<Integer> ids) {
SearchParam searchParam = new SearchParam();
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.must(QueryBuilders.termsQuery(ProductIndexEsField.id, ids));
boolQueryBuilder.must(QueryBuilders.termQuery(ProductIndexEsField.status, 1));
boolQueryBuilder.mustNot(QueryBuilders.termQuery(SearchRequestParams.PROMOTIONINDEX_ISDEL, "Y"));
boolQueryBuilder.mustNot(QueryBuilders.termQuery(SearchRequestParams.PROMOTIONINDEX_COMMONBANNER, ""));
searchParam.setFiter(boolQueryBuilder);
searchParam.setSize(ids.size());
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
if (searchResult == null || CollectionUtils.isEmpty(searchResult.getResultList())) {
return Collections.emptyList();
}
List<RecommendPromotionAggVO> resultList = new ArrayList<>();
long total = searchResult.getTotal();
for (Map<String, Object> esMap : searchResult.getResultList()) {
if (!CollectionUtils.isEmpty(esMap)) {
resultList.add(parsePromotionInfos(esMap, total));
}
}
return resultList;
}
private List<Map<String, Object>> queryListByParam(SearchParam searchParam) {
List<Map<String, Object>> results = new ArrayList<Map<String, Object>>();
SearchResult searchResult = searchCommonService.doSearch(INDEX_NAME, searchParam);
if (searchResult == null || searchResult.getResultList() == null || searchResult.getResultList().isEmpty()) {
return results;
}
for (Map<String, Object> esMap : searchResult.getResultList()) {
results.add(this.getMap(esMap));
}
return results;
}
private BoolQueryBuilder constructFilterBuilder(Map<String, String> paramMap) {
BoolQueryBuilder boolFilter = QueryBuilders.boolQuery();
if (paramMap.containsKey("ids") && StringUtils.isNotBlank(paramMap.get("ids"))) {
int[] ids = ConvertUtils.stringToIntArray(paramMap.get("ids"), ",");
boolFilter.must(QueryBuilders.termsQuery("id", ids));
}
return boolFilter;
}
private Map<String, Object> getMap(Map<String, Object> esMap) {
Map<String, Object> map = new HashMap<>();
int id = MapUtils.getIntValue(esMap, "id", 0);
map.put("is_promotion", id + "");
map.put("promotion_title", MapUtils.getString(esMap, "title", ""));
return map;
}
private RecommendPromotionAggVO parsePromotionInfos(Map<String, Object> esMap, long total) {
RecommendPromotionAggVO recommendPromotionAggVO = new RecommendPromotionAggVO();
recommendPromotionAggVO.setPromotion_info_id(MapUtils.getIntValue(esMap, "id", 0));
recommendPromotionAggVO.setTitle(MapUtils.getString(esMap, "title", ""));
recommendPromotionAggVO.setCoverimg_url(MapUtils.getString(esMap, "commonBanner", ""));
recommendPromotionAggVO.setTotal_count(total);
return recommendPromotionAggVO;
}
/***********************以下方法用于促销类型->促销名映射的索引****************************************/
}
... ...
package com.yoho.search.service.base.index.promotion;
import com.yoho.search.base.utils.ProductIndexEsField;
import com.yoho.search.core.es.model.SearchParam;
import com.yoho.search.core.es.model.SearchResult;
import com.yoho.search.models.RecommendPromotionAggVO;
import com.yoho.search.service.base.SearchCommonService;
import com.yoho.search.service.base.SearchRequestParams;
import org.apache.commons.collections.MapUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* Created by wangnan on 2017/5/11
* 促销索引服务,用于聚合促销
*/
@Service
public class PromotionIndexBaseService {
@Autowired
private SearchCommonService searchCommonService;
public List<RecommendPromotionAggVO> getPromotionInfosByIds(String indexName, List<Integer> ids) {
SearchParam searchParam = new SearchParam();
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.must(QueryBuilders.termsQuery(ProductIndexEsField.id, ids));
boolQueryBuilder.must(QueryBuilders.termQuery(ProductIndexEsField.status, 1));
boolQueryBuilder.mustNot(QueryBuilders.termQuery(SearchRequestParams.PROMOTIONINDEX_ISDEL, "Y"));
boolQueryBuilder.mustNot(QueryBuilders.termQuery(SearchRequestParams.PROMOTIONINDEX_COMMONBANNER, ""));
searchParam.setFiter(boolQueryBuilder);
searchParam.setSize(ids.size());
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
if (searchResult == null || CollectionUtils.isEmpty(searchResult.getResultList())) {
return Collections.emptyList();
}
List<RecommendPromotionAggVO> resultList = new ArrayList<>();
long total = searchResult.getTotal();
for (Map<String, Object> esMap : searchResult.getResultList()) {
if (!CollectionUtils.isEmpty(esMap)) {
resultList.add(parsePromotionInfos(esMap, total));
}
}
return resultList;
}
private RecommendPromotionAggVO parsePromotionInfos(Map<String, Object> esMap, long total) {
RecommendPromotionAggVO recommendPromotionAggVO = new RecommendPromotionAggVO();
recommendPromotionAggVO.setPromotion_info_id(MapUtils.getIntValue(esMap, "id", 0));
recommendPromotionAggVO.setTitle(MapUtils.getString(esMap, "title", ""));
recommendPromotionAggVO.setCoverimg_url(MapUtils.getString(esMap, "commonBanner", ""));
recommendPromotionAggVO.setTotal_count(total);
return recommendPromotionAggVO;
}
}
... ...
package com.yoho.search.service.base.index.promotion;
import com.yoho.search.base.helper.PromotionHelper;
import com.yoho.search.base.models.PromotionCond;
import com.yoho.search.base.models.PromotionMatchFactor;
import org.apache.commons.collections.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.Map;
/**
* 判断促销和skn是否匹配逻辑
* @Author: wangnan
* @Date: Created in 2018/1/29
*/
@Service
public class PromotionMatchService {
private static final Logger logger = LoggerFactory.getLogger(PromotionMatchService.class);
@Autowired
private PromotionHelper promotionHelper;
/**
* 判断促销和skn是否匹配
*/
public boolean matchProduct(PromotionCond promotionCond, Map<String, Object> productMap) {
boolean matchResult;
if (promotionCond == null) {
return false;
}
if (promotionCond.getAggregator() == PromotionCond.Aggregator.ALL) {
matchResult = promotionCond.getCondDetailList().stream().allMatch(condDetail -> matchCondDetail(condDetail, productMap));
} else {
matchResult = promotionCond.getCondDetailList().stream().anyMatch(condDetail -> matchCondDetail(condDetail, productMap));
}
if (matchResult) {
logger.debug("[func=PromotionCond.matchResult][skn={}][promotionId={}][promotionTitle={}]",
MapUtils.getIntValue(productMap, "id"), promotionCond.getPromotionId(), promotionCond.getPromotionTitle());
}
return matchResult;
}
/**
* 匹配matchCondDetail
*/
private boolean matchCondDetail(PromotionCond.CondDetail condDetail, Map<String, Object> productMap) {
if (CollectionUtils.isEmpty(condDetail.getCondItemList())) {
// 当没有具体条件,比如【全场满99元加5元换购YOHO!当期热销新刊】这种时所有productindex都匹配
return true;
} else if (condDetail.getAggregator() == PromotionCond.Aggregator.ALL) {
return condDetail.getCondItemList().stream().allMatch(condItem -> matchProduct(condItem, productMap));
} else {
return condDetail.getCondItemList().stream().anyMatch(condItem -> matchProduct(condItem, productMap));
}
}
/**
* 生成一个参数对象去匹配促销,逻辑抽到了core工程的helper中,暂时consumer和service都调用
*/
private boolean matchProduct(PromotionCond.CondItem condItem, Map<String, Object> productMap) {
PromotionMatchFactor promotionMatchFactor = new PromotionMatchFactor();
promotionMatchFactor.setBrandId(MapUtils.getIntValue(productMap, "brand_id"));
promotionMatchFactor.setSmallSortId(MapUtils.getIntValue(productMap, "smal_sort_id"));
promotionMatchFactor.setMiddleSortId(MapUtils.getIntValue(productMap, "middle_sort_id"));
promotionMatchFactor.setMaxSortId(MapUtils.getIntValue(productMap, "max_sort_id"));
promotionMatchFactor.setIspromotion(MapUtils.getIntValue(productMap, "is_promotion"));
promotionMatchFactor.setProductskn(MapUtils.getIntValue(productMap, "product_skn"));
return promotionHelper.matchProduct(condItem, promotionMatchFactor);
}
}
... ...
package com.yoho.search.service.base.index.promotion;
import com.alibaba.fastjson.JSONObject;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.yoho.search.base.utils.ISearchConstants;
import com.yoho.search.core.es.model.SearchParam;
import com.yoho.search.core.es.model.SearchResult;
import com.yoho.search.service.base.SearchCommonService;
import org.apache.commons.collections.MapUtils;
import org.elasticsearch.index.query.QueryBuilders;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* 查询promotiontype索引 用于生成 促销类型->促销名映射,1分钟缓存。
* @Author: wangnan
* @Date: Created in 2018/1/29
*/
@Service
public class PromotionTypeService {
@Autowired
private SearchCommonService searchCommonService;
private static final Logger logger = LoggerFactory.getLogger(PromotionTypeService.class);
private static final String PROMOTION_TYPE_MAP_CACHE_KEY = "promotionTypeMapCacheKey";
private volatile Map<String, String> promotionTypeMap = new HashMap<>();
private static final String CACHE_KEY = "CacheKey";
LoadingCache<String, JSONObject> promotionTypeMapCache = CacheBuilder.newBuilder()
.maximumSize(30000)
.expireAfterWrite(1, TimeUnit.MINUTES)
.build(new CacheLoader<String, JSONObject>() {
public JSONObject load(String key) {
JSONObject jsonObject = new JSONObject();
jsonObject.put(PROMOTION_TYPE_MAP_CACHE_KEY, buildPromotionTypeMap());
return jsonObject;
}
});
public Map<String, String> getPromotionTypeMap() {
try {
JSONObject jsonObject = promotionTypeMapCache.get(CACHE_KEY);
Assert.isTrue(jsonObject != null, "[cache jsonObject cannot be null]");
promotionTypeMap = (Map<String, String>) jsonObject.get(PROMOTION_TYPE_MAP_CACHE_KEY);
} catch (Exception e) {
logger.error(e.getMessage());
}
return promotionTypeMap;
}
private Map<String, String> buildPromotionTypeMap() {
try {
SearchParam searchPromotionParam = buildPromotionTypeSearchParam();
SearchResult searchPromotionResult = searchCommonService.doSearch(ISearchConstants.INDEX_NAME_PROMOTIONTYPE, searchPromotionParam);
return this.getPromotionTypeMap(searchPromotionResult);
} catch (Exception e) {
logger.error(e.getMessage(), e);
return new HashMap<>();
}
}
private SearchParam buildPromotionTypeSearchParam() {
SearchParam searchPromotionParam = new SearchParam();
searchPromotionParam.setSize(10000);
searchPromotionParam.setQuery(QueryBuilders.matchAllQuery());
return searchPromotionParam;
}
private Map<String, String> getPromotionTypeMap(SearchResult searchPromotionResult) {
if (searchPromotionResult == null || searchPromotionResult.getResultList() == null || searchPromotionResult.getResultList().size() == 0) {
return new HashMap<>();
}
Map<String, String> promotionTypeMap = new HashMap<>();
for (Map<String, Object> promotionEsSource : searchPromotionResult.getResultList()) {
promotionTypeMap.put(MapUtils.getString(promotionEsSource, "promotionType", ""), MapUtils.getString(promotionEsSource, "info", ""));
}
return promotionTypeMap;
}
}
... ...