Authored by wangnan9279

Merge branch 'master' into wn_tblproduct_new

Showing 33 changed files with 555 additions and 152 deletions
... ... @@ -85,6 +85,6 @@ fi
JAVA_OPTS=" $JAVA_OPTS $SERVER_BASE_DIR "
#jmx
export JMX_PORT=`expr 9600 + $SERVER_PORT`
export JMX_PORT=`expr 9900 + $SERVER_PORT`
export LOCAL_IP=`/sbin/ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v inet6|awk '{print $2}'|tr -d "addr:"|awk 'NR==1 {print}'`
export CATALINA_OPTS="$CATALINA_OPTS -Djava.rmi.server.hostname=$LOCAL_IP -Dcom.sun.management.jmxremote.port=$JMX_PORT -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false"
... ...
package com.yoho.search.recall.common;
import org.apache.commons.lang.StringUtils;
public class ABUserPartitionUtils {
public static boolean isAUser(int uid) {
int tail = uid % 1024;
return tail < 512 ? true : false;
}
public static boolean isAUser(String udid) {
if (StringUtils.isBlank(udid)) {
return false;
}
int tail = Math.abs(udid.hashCode() % 1024);
return tail < 512 ? true : false;
}
public static boolean isAUserComplete(int uid,String udid) {
if(uid>0){
return isAUser(uid);
}else{
return isAUser(udid);
}
}
}
... ...
... ... @@ -8,6 +8,7 @@ import com.yoho.search.base.utils.Transfer;
import com.yoho.search.core.es.model.SearchParam;
import com.yoho.search.core.es.model.SearchResult;
import com.yoho.search.models.SearchApiResult;
import com.yoho.search.recall.common.ABUserPartitionUtils;
import com.yoho.search.recall.scene.beans.builder.UserRecallRequestBuilder;
import com.yoho.search.recall.scene.beans.cache.SknReturnInfoCacheBean;
import com.yoho.search.recall.scene.beans.cache.UserRecallCacheBean;
... ... @@ -53,6 +54,7 @@ public class SceneRecallProductListService {
/**
* 个性化召回列表入口1
*
* @param paramMap
* @return
*/
... ... @@ -76,6 +78,7 @@ public class SceneRecallProductListService {
/**
* 个性化召回列表入口2
*
* @param userRecallRequest
* @param page
* @return
... ... @@ -83,17 +86,17 @@ public class SceneRecallProductListService {
public SearchApiResult recallProductList(UserRecallRequest userRecallRequest, int page) {
//1、判断第一页是要需要查缓存【不查询缓存时,只添加缓存,以保证用户数据的实时性】
boolean ignoreQueryCache = false;
if(page==1 && userRecallRequest.hasUidOrUdid() && !searchDynamicConfigService.searchPersionalNewStrategyFirstPageCacheOpen()){
if (page == 1 && userRecallRequest.hasUidOrUdid() && !searchDynamicConfigService.searchPersionalNewStrategyFirstPageCacheOpen()) {
ignoreQueryCache = true;
}
//2、执行召回
long begin = System.currentTimeMillis();
UserRecallResponse userRecallResponse = userRecallCacheBean.queryRecallResult(userRecallRequest,ignoreQueryCache);
RECALL_NEW_LOGGER.info("SceneRecallProductListService[1]-queryRecallResult,cost is [{}]", System.currentTimeMillis()-begin);
UserRecallResponse userRecallResponse = userRecallCacheBean.queryRecallResult(userRecallRequest, ignoreQueryCache);
RECALL_NEW_LOGGER.info("SceneRecallProductListService[1]-queryRecallResult,cost is [{}]", System.currentTimeMillis() - begin);
//3、根据召回结果查询商品信息
List<Map<String, Object>> productList = this.queryProductList(userRecallRequest, userRecallResponse,page, userRecallRequest.getPageSize());
List<Map<String, Object>> productList = this.queryProductList(userRecallRequest, userRecallResponse, page, userRecallRequest.getPageSize());
//4、构造返回结果
JSONObject dataMap = new JSONObject();
... ... @@ -107,6 +110,7 @@ public class SceneRecallProductListService {
/**
* 根据召回结果查询商品列表
*
* @param userRecallRequest
* @param userRecallResponse
* @param page
... ... @@ -118,33 +122,33 @@ public class SceneRecallProductListService {
int recallTotalPage = userRecallResponse.getRecallTotalPage();
//2、在召回结果中则直接根据skn去查询
List<RecallSknInfo> recallSknInfos = null;
if(page<=recallTotalPage){
recallSknInfos = CollectionUtils.safeSubList(userRecallResponse.getSknList(),(page-1)*pageSize,page*pageSize);
}else{
recallSknInfos = this.queryProductSknByFilterSkn(userRecallRequest, userRecallResponse.getSknList(), page-recallTotalPage, pageSize);
if (page <= recallTotalPage) {
recallSknInfos = CollectionUtils.safeSubList(userRecallResponse.getSknList(), (page - 1) * pageSize, page * pageSize);
} else {
recallSknInfos = this.queryProductSknByFilterSkn(userRecallRequest, userRecallResponse.getSknList(), page - recallTotalPage, pageSize);
}
//3、获取召回结果的skn
List<Integer> productSknList = this.getProductSknList(recallSknInfos);
//4、获取商品的返回信息
long begin = System.currentTimeMillis();
List<Map<String, Object>> productInfoList = sknReturnInfoCacheBean.queryProductListBySkn(productSknList,productSknList.size());
RECALL_NEW_LOGGER.info("SceneRecallProductListService[2].queryProductListBySkn,cost is [{}]", System.currentTimeMillis()-begin);
List<Map<String, Object>> productInfoList = sknReturnInfoCacheBean.queryProductListBySkn(productSknList, productSknList.size());
RECALL_NEW_LOGGER.info("SceneRecallProductListService[2].queryProductListBySkn,cost is [{}]", System.currentTimeMillis() - begin);
//5、填充召回类型
Map<Integer,RecallSknInfo> sknRecallTypeMap = CollectionUtils.toMap(recallSknInfos, new Transfer<RecallSknInfo, Integer>() {
Map<Integer, RecallSknInfo> sknRecallTypeMap = CollectionUtils.toMap(recallSknInfos, new Transfer<RecallSknInfo, Integer>() {
@Override
public Integer transfer(RecallSknInfo recallSknInfo) {
return recallSknInfo.getProductSkn();
}
});
for(Map<String, Object> productInfo: productInfoList){
int productSkn = MapUtils.getIntValue(productInfo,"product_skn",0);
for (Map<String, Object> productInfo : productInfoList) {
int productSkn = MapUtils.getIntValue(productInfo, "product_skn", 0);
RecallSknInfo recallSknInfo = sknRecallTypeMap.get(productSkn);
if(recallSknInfo==null || recallSknInfo.getRecallType()==null){
productInfo.put("recall_type", StrategyEnum.DEFAULT.name());
}else{
productInfo.put("recall_type",recallSknInfo.getRecallType());
if (recallSknInfo == null || recallSknInfo.getRecallType() == null) {
productInfo.put("recall_type", StrategyEnum.DEFAULT_HEAT_VALUE.name());
} else {
productInfo.put("recall_type", recallSknInfo.getRecallType());
}
}
return productInfoList;
... ... @@ -152,53 +156,57 @@ public class SceneRecallProductListService {
/**
* 过滤掉已召回的skn,并按人气排序
*
* @param recallSknInfos
* @param realPage
* @param pageSize
* @return
*/
private List<RecallSknInfo> queryProductSknByFilterSkn(UserRecallRequest userRecallRequest, List<RecallSknInfo> recallSknInfos, int realPage, int pageSize){
private List<RecallSknInfo> queryProductSknByFilterSkn(UserRecallRequest userRecallRequest, List<RecallSknInfo> recallSknInfos, int realPage, int pageSize) {
long begin = System.currentTimeMillis();
SearchParam searchParam = new SearchParam();
//0、策略区分
StrategyEnum strategyEnum = ABUserPartitionUtils.isAUserComplete(userRecallRequest.getUid(), userRecallRequest.getUdid()) ? StrategyEnum.DEFAULT_HEAT_VALUE : StrategyEnum.DEFAULT_CTR_VALUE;
//1、设置query
SearchParam searchParam = new SearchParam();
searchParam.setQuery(userRecallRequest.getParamQueryFilter().getParamQuery());
//2、设置filter
List<Integer> notProductSkns = new ArrayList<>();
for (RecallSknInfo recallSknInfo:recallSknInfos ){
for (RecallSknInfo recallSknInfo : recallSknInfos) {
notProductSkns.add(recallSknInfo.getProductSkn());
}
BoolQueryBuilder filter = userRecallRequest.getParamQueryFilter().getParamFilter();
filter.mustNot(QueryBuilders.termsQuery(ProductIndexEsField.productSkn,notProductSkns));
filter.mustNot(QueryBuilders.termsQuery(ProductIndexEsField.productSkn, notProductSkns));
searchParam.setFiter(filter);
//3、设置分页参数
searchParam.setOffset((realPage-1)*pageSize);
searchParam.setOffset((realPage - 1) * pageSize);
searchParam.setSize(pageSize);
//4、设置IncludeFields
searchParam.setIncludeFields(Arrays.asList(ProductIndexEsField.productSkn));
//5、设置排序
List<SortBuilder<?>> sortBuilders = new ArrayList<>();
if (strategyEnum.equals(StrategyEnum.DEFAULT_HEAT_VALUE)) {
sortBuilders.add(SortBuilderHelper.getHeatValueDescSort());
} else {
sortBuilders.add(SortBuilderHelper.getCtrValueDescSort());
}
sortBuilders.add(SortBuilderHelper.getSevendayMoneyDescSort());
sortBuilders.add(SortBuilderHelper.getIdDescSort());
searchParam.setSortBuilders(sortBuilders);
SearchResult searchResult = searchCommonService.doSearch(ISearchConstants.INDEX_NAME_PRODUCT_INDEX,searchParam);
SearchResult searchResult = searchCommonService.doSearch(ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
//6、构造返回结果
List<RecallSknInfo> results = new ArrayList<>();
for (Map<String, Object> product : searchResult.getResultList()) {
results.add(new RecallSknInfo(MapUtils.getIntValue(product,ProductIndexEsField.productSkn,0), StrategyEnum.DEFAULT.name()));
results.add(new RecallSknInfo(MapUtils.getIntValue(product, ProductIndexEsField.productSkn, 0), strategyEnum.name()));
}
RECALL_NEW_LOGGER.info("SceneRecallProductListService[1.5].queryProductSknByFilterSkn,cost is [{}]", System.currentTimeMillis()-begin);
RECALL_NEW_LOGGER.info("SceneRecallProductListService[1.5].queryProductSknByFilterSkn,cost is [{}]", System.currentTimeMillis() - begin);
return results;
}
private List<Integer> getProductSknList(List<RecallSknInfo> recallSknInfos){
private List<Integer> getProductSknList(List<RecallSknInfo> recallSknInfos) {
List<Integer> productSknList = new ArrayList<>();
for (RecallSknInfo recallSknInfo:recallSknInfos ){
for (RecallSknInfo recallSknInfo : recallSknInfos) {
productSknList.add(recallSknInfo.getProductSkn());
}
return productSknList;
... ...
package com.yoho.search.recall.scene.beans.builder;
import com.yoho.search.recall.common.ABUserPartitionUtils;
import com.yoho.search.recall.scene.beans.strategy.impls.*;
import com.yoho.search.recall.scene.constants.SknCountConstants;
import com.yoho.search.recall.scene.models.common.ParamQueryFilter;
import com.yoho.search.recall.scene.models.req.RecallRequest;
import com.yoho.search.recall.scene.models.req.UserRecallRequest;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
... ... @@ -16,11 +18,12 @@ public class CommonRecallRequestBuilder {
/**
* 批量召回业务需求
*
* @param paramQueryFilter
* @param userRecallRequest
* @param firstProductSkns
* @return
*/
public List<RecallRequest> buildCommonRecallRequests(ParamQueryFilter paramQueryFilter, int pageSize, List<String> firstProductSkns) {
public List<RecallRequest> buildCommonRecallRequests(UserRecallRequest userRecallRequest, int pageSize, List<String> firstProductSkns) {
ParamQueryFilter paramQueryFilter = userRecallRequest.getParamQueryFilter();
//1、构造召回请求
List<RecallRequest> requests = new ArrayList<>();
//1.1) firstSkn的召回
... ... @@ -32,83 +35,84 @@ public class CommonRecallRequestBuilder {
//1.4) 流量补偿的召回
requests.add(this.buildAddFlowRequest(paramQueryFilter, SknCountConstants.ADD_FLOW));
//1.5) 页面的兜底召回
requests.add(this.buildCommonRecallValueRequest(paramQueryFilter, SknCountConstants.COMMON_RECALL_VALUE_RECALL_COUNT));
//1.6) 真正的兜底的召回,不带任何过滤条件
requests.add(this.buildCommonRequest(paramQueryFilter, pageSize));
if (ABUserPartitionUtils.isAUserComplete(userRecallRequest.getUid(), userRecallRequest.getUdid())) {
requests.add(this.buildCommonHeatValueStrategy(paramQueryFilter, pageSize));
} else {
requests.add(this.buildCommonCtrValueStrategy(paramQueryFilter, pageSize));
}
return requests;
}
/**
* 构建【按兜底召回】的请求参数
* 构造【按FIRST_SKN召回】的请求参数
*
* @param paramQueryFilter
* @param firstProductSkns
* @param size
* @return
*/
private RecallRequest buildCommonRequest(ParamQueryFilter paramQueryFilter, int size) {
CommonStrategy strategy = new CommonStrategy(size);
private RecallRequest buildFirstSknRequest(ParamQueryFilter paramQueryFilter, List<String> firstProductSkns, int size) {
CommonFirstSknStrategy strategy = new CommonFirstSknStrategy(size, firstProductSkns);
return new RecallRequest(paramQueryFilter, strategy);
}
/**
* 构建【按兜底召回】的请求参数
* 构建【按直通车召回】的请求参数
*
* @param paramQueryFilter
* @param size
* @return
*/
private RecallRequest buildCommonRecallValueRequest(ParamQueryFilter paramQueryFilter, int size) {
CommonRecallValueStrategy strategy = new CommonRecallValueStrategy(size);
private RecallRequest buildDirectTrainRequest(ParamQueryFilter paramQueryFilter, int size) {
CommonDirectTrainStrategy strategy = new CommonDirectTrainStrategy(size);
return new RecallRequest(paramQueryFilter, strategy);
}
/**
* 构造【按FIRST_SKN召回】的请求参数
* 构建【按新开店铺召回】的请求参数
*
* @param paramQueryFilter
* @param firstProductSkns
* @param size
* @return
*/
private RecallRequest buildFirstSknRequest(ParamQueryFilter paramQueryFilter, List<String> firstProductSkns, int size) {
CommonFirstSknStrategy strategy = new CommonFirstSknStrategy(size, firstProductSkns);
private RecallRequest buildNewShopRequest(ParamQueryFilter paramQueryFilter, int size) {
CommonNewShopStrategy strategy = new CommonNewShopStrategy(size);
return new RecallRequest(paramQueryFilter, strategy);
}
/**
* 构建【按直通车召回】的请求参数
* 构建【流量补偿】的请求参数
*
* @param paramQueryFilter
* @param size
* @return
*/
private RecallRequest buildDirectTrainRequest(ParamQueryFilter paramQueryFilter, int size) {
CommonDirectTrainStrategy strategy = new CommonDirectTrainStrategy(size);
private RecallRequest buildAddFlowRequest(ParamQueryFilter paramQueryFilter, int size) {
CommonAddFlowStrategy strategy = new CommonAddFlowStrategy(size);
return new RecallRequest(paramQueryFilter, strategy);
}
/**
* 构建【按新开店铺召回】的请求参数
* 构建【按兜底召回】的请求参数
*
* @param paramQueryFilter
* @param size
* @return
*/
private RecallRequest buildNewShopRequest(ParamQueryFilter paramQueryFilter, int size) {
CommonNewShopStrategy strategy = new CommonNewShopStrategy(size);
private RecallRequest buildCommonHeatValueStrategy(ParamQueryFilter paramQueryFilter, int size) {
CommonHeatValueStrategy strategy = new CommonHeatValueStrategy(size);
return new RecallRequest(paramQueryFilter, strategy);
}
/**
* 构建【流量补偿】的请求参数
* 构建【按兜底召回】的请求参数
*
* @param paramQueryFilter
* @param size
* @return
*/
private RecallRequest buildAddFlowRequest(ParamQueryFilter paramQueryFilter, int size) {
CommonAddFlowStrategy strategy = new CommonAddFlowStrategy(size);
private RecallRequest buildCommonCtrValueStrategy(ParamQueryFilter paramQueryFilter, int size) {
CommonCtrValueStrategy strategy = new CommonCtrValueStrategy(size);
return new RecallRequest(paramQueryFilter, strategy);
}
... ...
package com.yoho.search.recall.scene.beans.builder;
import com.yoho.search.recall.scene.beans.helper.StrategyHelper;
import com.yoho.search.recall.scene.beans.strategy.StrategyEnum;
import com.yoho.search.recall.scene.models.common.RecallMergerResult;
import com.yoho.search.recall.scene.models.req.RecallRequest;
... ... @@ -41,7 +42,7 @@ public class RecallMergerResultBuilder {
if (request == null || response == null) {
continue;
}
if (StrategyEnum.COMMON.equals(request.requestStrategy())) {
if(StrategyHelper.isCommonStrategy(request.requestStrategy())){
total = response.getTotal();
break;
}
... ...
... ... @@ -7,6 +7,7 @@ import com.yoho.search.core.personalized.models.SortPriceAreas;
import com.yoho.search.recall.common.ProductFeatureFactorHepler;
import com.yoho.search.recall.common.UserFeatureFactor;
import com.yoho.search.recall.scene.beans.cache.SknBaseInfoCacheBean;
import com.yoho.search.recall.scene.beans.helper.StrategyHelper;
import com.yoho.search.recall.scene.beans.strategy.StrategyEnum;
import com.yoho.search.recall.scene.constants.SknCountConstants;
import com.yoho.search.recall.scene.models.common.RecallMergerResult;
... ... @@ -227,7 +228,7 @@ public class UserRecallResponseBuilder {
score = score * sknResult.getHeatValue();
}
//5)如果当前skn不是兜底召回的,则加分【将兜底和非兜底的拆分】
if (!this.isCommonStrategy(strategy)) {
if (!StrategyHelper.isCommonStrategy(strategy)) {
score = score + 1000;
}
// //6)如果满足品类价格带偏好,则加分
... ... @@ -243,10 +244,6 @@ public class UserRecallResponseBuilder {
return sknResultList;
}
private boolean isCommonStrategy(StrategyEnum strategy) {
return strategy.equals(StrategyEnum.COMMON) || strategy.equals(StrategyEnum.COMMON_RECALL_VALUE);
}
/**
* 兜底数据处理
*
... ... @@ -256,28 +253,17 @@ public class UserRecallResponseBuilder {
//1、兜底数据移除
Iterator<RecallMergerResult.SknResult> iterator = sknResultList.iterator();
List<RecallMergerResult.SknResult> commonResultList = new ArrayList<>();
List<RecallMergerResult.SknResult> commonRecallValueResultList = new ArrayList<>();
while (iterator.hasNext()) {
RecallMergerResult.SknResult sknResult = iterator.next();
if (sknResult.getStrategy().equals(StrategyEnum.COMMON)) {
if (StrategyHelper.isCommonStrategy(sknResult.getStrategy())) {
commonResultList.add(sknResult);
iterator.remove();
}
if (sknResult.getStrategy().equals(StrategyEnum.COMMON_RECALL_VALUE)) {
commonRecallValueResultList.add(sknResult);
iterator.remove();
}
}
//2、兜底数据排序并截取
Collections.sort(commonRecallValueResultList, (o1, o2) -> o2.getScore().compareTo(o1.getScore()));
commonRecallValueResultList = CollectionUtils.safeSubList(commonRecallValueResultList, 0, SknCountConstants.COMMON_RECALL_VALUE_RETURN_COUNT);
sknResultList.addAll(commonRecallValueResultList);
//3、如果是数量少于一页,则加回真正用来兜底的数据
if (sknResultList.size() < pageSize) {
sknResultList.addAll(commonResultList);
}
Collections.sort(commonResultList, (o1, o2) -> o2.getScore().compareTo(o1.getScore()));
commonResultList = CollectionUtils.safeSubList(commonResultList, 0, Math.max(SknCountConstants.COMMON_RECALL_VALUE_RETURN_COUNT, pageSize));
sknResultList.addAll(commonResultList);
}
/**
... ...
... ... @@ -155,7 +155,7 @@ public class UserRecallCacheBean extends AbstractCacheBean<UserRecallRequest, Us
private CompletableFuture<List<RecallRequestResponse>> doRecallCommon(UserRecallRequest userRecallRequest, UserPersonalFactor userPersonalFactor) {
return CompletableFuture.supplyAsync(() -> {
long begin = System.currentTimeMillis();
List<RecallRequest> commonRequests = commonRequestBuilder.buildCommonRecallRequests(userRecallRequest.getParamQueryFilter(), userRecallRequest.getPageSize(), userRecallRequest.getFirstProductSkns());
List<RecallRequest> commonRequests = commonRequestBuilder.buildCommonRecallRequests(userRecallRequest, userRecallRequest.getPageSize(), userRecallRequest.getFirstProductSkns());
List<RecallRequestResponse> commonRequestResponses = batchRecallCacheBean.batchRecallAndCache(commonRequests);
RECALL_NEW_LOGGER.info("UserRecallCacheBean[2.1]-doRecallCommon,requestCount is [{}], cost is [{}]", commonRequests.size(), System.currentTimeMillis() - begin);
return commonRequestResponses;
... ...
package com.yoho.search.recall.scene.beans.helper;
import com.yoho.search.recall.scene.beans.strategy.StrategyEnum;
public class StrategyHelper {
public static boolean isCommonStrategy(StrategyEnum strategy) {
return strategy.equals(StrategyEnum.COMMON_CTR_VALUE) || strategy.equals(StrategyEnum.COMMON_HEAT_VALUE);
}
}
... ...
... ... @@ -29,9 +29,11 @@ public enum StrategyEnum {
ADD_FLOW(12),//流量补偿
NEW_SHOP(11),//新开店铺
COMMON_RECALL_VALUE(1),//页面兜底召回-包含个性化【随机200取40】
COMMON(0),//兜底,其他策略数量足够时召回来的商品会丢弃
DEFAULT(-1);//其他,无视即可
COMMON_CTR_VALUE(2),//页面兜底召回-包含个性化【随机200取40】
COMMON_HEAT_VALUE(1),//页面兜底召回-包含个性化【随机200取40】
DEFAULT_HEAT_VALUE(-1),//第四部分做A/B测试
DEFAULT_CTR_VALUE(-2);//第四部分做A/B测试
private Integer priority;
... ...
package com.yoho.search.recall.scene.beans.strategy.impls;
import com.yoho.search.recall.scene.beans.helper.ExtendFilterHelper;
import com.yoho.search.recall.scene.beans.helper.SortBuilderHelper;
import com.yoho.search.recall.scene.beans.strategy.IStrategy;
import com.yoho.search.recall.scene.beans.strategy.StrategyEnum;
... ... @@ -14,27 +13,27 @@ import org.elasticsearch.search.sort.SortBuilder;
* @author gufei.hu
*
*/
public class CommonRecallValueStrategy implements IStrategy {
public class CommonCtrValueStrategy implements IStrategy {
private int size;
public CommonRecallValueStrategy(int size) {
public CommonCtrValueStrategy(int size) {
this.size = size;
}
@Override
public StrategyEnum strategtEnum() {
return StrategyEnum.COMMON_RECALL_VALUE;
return StrategyEnum.COMMON_CTR_VALUE;
}
@Override
public QueryBuilder extendFilter() {
return ExtendFilterHelper.commonRecallValueFilter();
return null;
}
@Override
public SortBuilder<?> sortBuilder() {
return SortBuilderHelper.getRandomSort();
return SortBuilderHelper.getCtrValueDescSort();
}
@Override
... ...
package com.yoho.search.recall.scene.beans.strategy.impls;
import com.yoho.search.recall.scene.beans.helper.ExtendFilterHelper;
import com.yoho.search.recall.scene.beans.helper.SortBuilderHelper;
import com.yoho.search.recall.scene.beans.strategy.IStrategy;
import com.yoho.search.recall.scene.beans.strategy.StrategyEnum;
... ... @@ -9,27 +8,27 @@ import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.search.sort.SortBuilder;
/**
* 真正兜底的召回
* 按人气兜底的召回
*
* @author gufei.hu
*
*/
public class CommonStrategy implements IStrategy {
public class CommonHeatValueStrategy implements IStrategy {
private int size;
public CommonStrategy(int size) {
public CommonHeatValueStrategy(int size) {
this.size = size;
}
@Override
public StrategyEnum strategtEnum() {
return StrategyEnum.COMMON;
return StrategyEnum.COMMON_HEAT_VALUE;
}
@Override
public QueryBuilder extendFilter() {
return ExtendFilterHelper.commonFilter();
return null;
}
@Override
... ...
... ... @@ -64,7 +64,7 @@ public class SortBrandVectorCacheBean {
RECALL_NEW_LOGGER.info("loadBrandSortVector from [{}] begin........", indexName);
long begin = System.currentTimeMillis();
SearchParam searchParam = new SearchParam();
searchParam.setSize(10000);
searchParam.setSize(15000);
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
Map<String, List<Double>> result = this.buildSortBrandVectors(searchResult, isForRnn);
if (!result.isEmpty()) {
... ...
package com.yoho.search.restapi.others;
import com.yoho.search.common.cache.aop.SearchCacheAble;
import com.yoho.search.common.utils.HttpServletRequestUtils;
import com.yoho.search.models.SearchApiResult;
import com.yoho.search.service.service.IImageRepertoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
/**
* @Author: wangnan
* @Date: Created in 2018/4/16
*/
@Controller
public class ImageRepertoryController {
@Autowired
private IImageRepertoryService imageRepertoryService;
/**
* 搜索图库列表
*/
@SearchCacheAble(cacheInMinute = 1, cacheName = "IMAGEREPERTORY")
@RequestMapping(method = RequestMethod.GET, value = "/imageRepertory")
@ResponseBody
public SearchApiResult searchImageRepertory(HttpServletRequest request) {
Map<String, String> paramMap = HttpServletRequestUtils.transParamType(request);
return imageRepertoryService.searchImageRepertoryList(paramMap);
}
}
... ...
... ... @@ -3,6 +3,7 @@ package com.yoho.search.restapi.scene;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.yoho.search.common.downgrade.persional.PersionalRateLimit;
import com.yoho.search.common.utils.HttpServletRequestUtils;
import com.yoho.search.models.PromotionConditions;
import com.yoho.search.models.SearchApiResult;
import com.yoho.search.service.scene.promotion.PromotionAggregationsService;
... ... @@ -16,6 +17,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
... ... @@ -177,4 +179,11 @@ public class PromotionSceneController {
return map;
}
@RequestMapping(method = RequestMethod.GET, value = "/promotion/aggPromotions")
@ResponseBody
public SearchApiResult aggPromotions(HttpServletRequest request){
Map<String, String> paramMap = HttpServletRequestUtils.transParamType(request);
return promotionAggregationsService.aggPromotions(paramMap);
}
}
... ...
... ... @@ -105,6 +105,10 @@ public class AggregationFactoryService {
return new RecommendPromotionAggregation(promotionIndexBaseService, promotionCount);
}
public IAggregation getPromotionAggregation(int promotionCount) {
return new PromotionAggregation(promotionCount);
}
public IAggregation getRecentShelveDayAggregation() {
return new RecentShelveDayAggregation();
}
... ...
package com.yoho.search.service.aggregations.impls;
import com.yoho.search.base.utils.DateUtil;
import com.yoho.search.base.utils.ProductIndexEsField;
import com.yoho.search.core.es.agg.AbstractAggregation;
import com.yoho.search.models.RecommendPromotionAggVO;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.filter.InternalFilter;
import org.elasticsearch.search.aggregations.bucket.nested.InternalNested;
import org.elasticsearch.search.aggregations.bucket.nested.NestedAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.terms.LongTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import java.util.*;
import java.util.stream.Collectors;
public class PromotionAggregation extends AbstractAggregation {
private static final String TERM_AGGREGATION_NAME = "promotionIdAgg";
private int promotionCount;
public PromotionAggregation(int promotionCount) {
this.promotionCount = promotionCount;
}
public int getPromotionCount() {
return promotionCount;
}
public void setPromotionCount(int promotionCount) {
this.promotionCount = promotionCount;
}
@Override
public String aggName() {
return "promotionAgg";
}
@Override
public String filterName() {
return "cxfilter";
}
@Override
public AbstractAggregationBuilder<?> getBuilder() {
BoolQueryBuilder boolFilter = QueryBuilders.boolQuery();
Date now = new Date();
boolFilter.must(QueryBuilders.rangeQuery(ProductIndexEsField.matchedPromotionsEndTime).gt(DateUtil.setHourSeonds(now, 1, 0, 0)));
boolFilter.must(QueryBuilders.rangeQuery(ProductIndexEsField.matchedPromotionsStartTime).lt(DateUtil.setHourSeonds(now, 0, 0, 0)));
boolFilter.mustNot(QueryBuilders.termsQuery(ProductIndexEsField.matchedPromotionsType, Arrays.asList("Needpaygift")));
AbstractAggregationBuilder<NestedAggregationBuilder> nestedAggregationBuilder =
AggregationBuilders.nested(aggName(), ProductIndexEsField.matchedPromotions)
.subAggregation(AggregationBuilders.filter(filterName(), boolFilter)
.subAggregation(AggregationBuilders.terms(TERM_AGGREGATION_NAME).field(ProductIndexEsField.matchedPromotionsId).size(getPromotionCount()).order(Terms.Order.aggregation("priority", false))
.subAggregation(AggregationBuilders.max("priority").field("matchedPromotions.priority"))));
return nestedAggregationBuilder;
}
@Override
public Object getAggregationResponseMap(Map<String, Aggregation> aggMaps) {
InternalNested aggregation = (InternalNested) aggMaps.get(aggName());
if(aggregation.getAggregations().asList().isEmpty()){
return new ArrayList<RecommendPromotionAggVO>();
}
InternalFilter filter = (InternalFilter)aggregation.getAggregations().asList().get(0);
List<LongTerms.Bucket> longTerms = ((LongTerms)filter.getAggregations().asList().get(0)).getBucketsInternal();
List<Integer> ids = longTerms.stream().map(e -> e.getKeyAsNumber().intValue()).collect(Collectors.toList());
if(ids==null || ids.isEmpty()){
return null;
}
return ids;
}
}
... ...
... ... @@ -76,9 +76,9 @@ public class RecommendPromotionAggregation extends AbstractAggregation {
List<LongTerms.Bucket> longTerms = ((LongTerms)filter.getAggregations().asList().get(0)).getBucketsInternal();
List<Integer> ids = longTerms.stream().map(e -> e.getKeyAsNumber().intValue()).collect(Collectors.toList());
if(ids==null || ids.isEmpty()){
return new ArrayList<RecommendPromotionAggVO>();
return null;
}
return promotionIndexBaseService.getPromotionInfoByIds(ISearchConstants.INDEX_NAME_PROMOTIONINDEX, ids);
return ids;
}
}
... ...
... ... @@ -120,6 +120,18 @@ public class SearchRequestParams {
public static final String SHOPS_PARAM_SHOPSTYPE = "shopsType";
public static final String SHOPS_PARAM_STATUS = "status";
//ImageRepertory index param
public static final String IMAGEREPERTORY_PARAM_ID = "id";
public static final String IMAGEREPERTORY_PARAM_ITEMID = "itemId";
public static final String IMAGEREPERTORY_PARAM_CHANNEL = "channel";
public static final String IMAGEREPERTORY_PARAM_SEASON = "season";
public static final String IMAGEREPERTORY_PARAM_IMAGESIZE = "imageSize";
public static final String IMAGEREPERTORY_PARAM_IMAGENAME = "imageName";
public static final String IMAGEREPERTORY_PARAM_IMAGETYPE = "imageType";
public static final String IMAGEREPERTORY_PARAM_ITEMTYPE = "itemType";
public static final String IMAGEREPERTORY_PARAM_PORT = "port";
public static final String SHOPS_PARAM_CUSTOMIZE_TAG = "customize_tag";
//Promotion index field
... ...
... ... @@ -44,14 +44,15 @@ public class PromotionIndexBaseService {
@Autowired
private PromotionTagHelper promotionTagHelper;
public List<RecommendPromotionAggVO> getPromotionInfoByIds(String indexName, List<Integer> ids) {
public List<RecommendPromotionAggVO> getPromotionInfoByIds(String indexName, List<Integer> ids, boolean needBanner) {
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, ""));
if (needBanner) {
boolQueryBuilder.mustNot(QueryBuilders.termQuery(SearchRequestParams.PROMOTIONINDEX_COMMONBANNER, ""));
}
searchParam.setFiter(boolQueryBuilder);
searchParam.setSize(ids.size());
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
... ...
... ... @@ -6,6 +6,7 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import com.yoho.search.common.utils.SearchKeyWordUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.common.lucene.search.function.CombineFunction;
... ... @@ -132,7 +133,7 @@ public class FunctionScoreSearchHelper {
// 模糊搜索页的打分器
private List<IScorer> getFuzzyPageScorers(BoolQueryBuilder persionalFilter, Map<String, String> paramMap) {
List<IScorer> scorers = new ArrayList<IScorer>();
List<IScorer> scorers = new ArrayList<>();
// 1、不是默认搜索类页,返回空列表
if (!searchCommonHelper.isFuzzySearchPageDefault(paramMap)) {
return scorers;
... ... @@ -145,6 +146,11 @@ public class FunctionScoreSearchHelper {
scorers.add(searchScorerFactory.getChannelSearchScorer(paramMap));
// 5、添加线下可售商品打分器
scorers.add(searchScorerFactory.getOfflineSaleOnlyScorer());
// 6、添加关键词完全匹配的打分器
String query = MapUtils.getString(paramMap, SearchRequestParams.PARAM_SEARCH_QUERY);
if(StringUtils.isNotBlank(query)){
scorers.add(searchScorerFactory.getCsBrandKeyWordScorer(query));
}
return scorers;
}
... ...
package com.yoho.search.service.list;
import com.yoho.search.models.SearchApiResult;
import com.yoho.search.recall.common.ABUserPartitionUtils;
import com.yoho.search.recall.scene.SceneRecallProductListService;
import com.yoho.search.service.base.SearchDynamicConfigService;
import com.yoho.search.service.helper.SearchCommonHelper;
... ... @@ -28,11 +29,6 @@ public class ProductListSwitchService {
@Autowired
private FuzzySceneProductListService fuzzySceneProductListService;
private boolean isAUser(int uid) {
int tail = uid % 1024;
return tail < 512 ? true : false;
}
/**
* 普通商品列表入口
*
... ... @@ -67,12 +63,12 @@ public class ProductListSwitchService {
}
// 5个性化版本A/B 测试
int uid = searchCommonHelper.getUid(paramMap);
if(uid>0 && isAUser(uid)){
return defaultProductListService.productListForDefaultPersional(paramMap);
}
// int uid = searchCommonHelper.getUid(paramMap);
// if(ABUserPartitionUtils.isAUser(uid)){
// return defaultProductListService.productListForDefaultPersional(paramMap);
// }
// 6、是否使用新的召回策略
// 6、使用召回策略
boolean searchPersionalNewStrategyOpen = searchDynamicConfigService.searchPersionalNewStrategyOpen();
if (searchPersionalNewStrategyOpen) {
return sceneRecallProductListService.recallProductList(paramMap);
... ...
... ... @@ -199,7 +199,7 @@ public class NewGoodProductSceneService extends AbstractCacheAbleService {
*/
private String getRandomSeed(Map<String, String> paramMap) {
int uid = MapUtils.getIntValue(paramMap, "uid", 0);
RedisKeyBuilder redisKeyBuilder = RedisKeyBuilder.newInstance().appendFixed("YOHOSEARCH:UserGPRandomSeed:").appendVar("uid");
RedisKeyBuilder redisKeyBuilder = RedisKeyBuilder.newInstance().appendFixed("YOHOSEARCH:UserGPRandomSeed:").appendVar(uid);
JSONObject jsonObject = searchCacheService.getJSONObjectFromCache(this.searchCache, redisKeyBuilder);
if (jsonObject != null) {
return jsonObject.getString("UserGoodProductRandomSeed");
... ...
package com.yoho.search.service.scene.aggregations;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
import org.elasticsearch.search.aggregations.Aggregation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yoho.search.base.utils.CollectionUtils;
... ... @@ -21,12 +8,21 @@ import com.yoho.search.common.cache.aop.SearchCacheAble;
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.RecommendPromotionAggVO;
import com.yoho.search.models.SearchApiResult;
import com.yoho.search.service.aggregations.impls.AggregationFactoryService;
import com.yoho.search.service.base.SearchCommonService;
import com.yoho.search.service.base.index.promotion.PromotionIndexBaseService;
import com.yoho.search.service.helper.SearchParamHelper;
import com.yoho.search.service.scene.common.SceneSelectionsService;
import com.yoho.search.service.service.IAggRecommendService;
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
import org.elasticsearch.search.aggregations.Aggregation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.*;
@Component
public class SceneAggregationsHelper {
... ... @@ -42,7 +38,7 @@ public class SceneAggregationsHelper {
@Autowired
private SceneSelectionsService sceneSelectionsService;
@Autowired
private IAggRecommendService aggRecommendService;
private PromotionIndexBaseService promotionIndexBaseService;
private Object getAggregationResponse(IAggregation aggregation, Map<String, String> paramMap) throws Exception {
// 1、构造SearchParam
... ... @@ -103,8 +99,13 @@ public class SceneAggregationsHelper {
try {
// 1、获取aggregation
IAggregation aggregation = aggregationFactoryService.getRecommendPromotionAggregation(50);
Object respone = this.getAggregationResponse(aggregation, paramMap);
return new SearchApiResult().setData(respone);
Object ids = this.getAggregationResponse(aggregation, paramMap);
List<RecommendPromotionAggVO> result = new ArrayList<>();
if(ids == null){
return new SearchApiResult().setData(result);
}
result = promotionIndexBaseService.getPromotionInfoByIds(ISearchConstants.INDEX_NAME_PROMOTIONINDEX, (List<Integer>) ids, true);
return new SearchApiResult().setData(result);
} catch (Exception e) {
logger.error(e.getMessage(), e);
return new SearchApiResult().setCode(500).setMessage("secneAggrecommendPromotion Exception");
... ... @@ -112,6 +113,27 @@ public class SceneAggregationsHelper {
}
/**
* 聚合促销专题-非个性化
*
* @param paramMap
* @return
*/
@SearchCacheAble(cacheName = "AGG_PROMOTION", cacheInMinute = 15, excludeParams = { "uid", "udid", "order", "page", "viewNum", "yh_channel"})
public List<RecommendPromotionAggVO> aggPromotion(Map<String, String> paramMap) {
try {
IAggregation aggregation = aggregationFactoryService.getPromotionAggregation(50);
Object ids = this.getAggregationResponse(aggregation, paramMap);
if(ids == null){
return Collections.emptyList();
}
return promotionIndexBaseService.getPromotionInfoByIds(ISearchConstants.INDEX_NAME_PROMOTIONINDEX, (List<Integer>) ids, false);
} catch (Exception e) {
logger.error(e.getMessage(), e);
return Collections.emptyList();
}
}
/**
* 从缓存中获取数据后按分页参数截取
*
* @param recommendPromotions
... ... @@ -125,7 +147,9 @@ public class SceneAggregationsHelper {
return new ArrayList<Object>();
}
List<?> recommendPromotionList = (List<?>) recommendPromotions;
if (recommendPromotionList.isEmpty()) {
return recommendPromotionList;
}
int totalCount = recommendPromotionList.size();
int start = (page - 1) * count;
int end = start + count;
... ...
... ... @@ -4,6 +4,10 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.yoho.search.base.utils.CollectionUtils;
import com.yoho.search.models.RecommendPromotionAggVO;
import com.yoho.search.service.helper.SearchCommonHelper;
import com.yoho.search.service.scene.aggregations.SceneAggregationsHelper;
import com.yoho.search.service.scene.common.SceneRecommendBrandsService;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
... ... @@ -64,6 +68,10 @@ public class PromotionAggregationsService extends AbstractCacheAbleService {
private PromotionSceneHelper promotionSceneHelper;
@Autowired
private SceneRecommendBrandsService sceneRecommendBrandsService;
@Autowired
private SceneAggregationsHelper sceneAggregationsHelper;
@Autowired
private SearchCommonHelper searchCommonHelper;
@Override
public SearchCache getSearchCache() {
... ... @@ -199,4 +207,17 @@ public class PromotionAggregationsService extends AbstractCacheAbleService {
}
}
public SearchApiResult aggPromotions(Map<String, String> paramMap){
int size = 10;
JSONObject jsonObject = new JSONObject();
List<RecommendPromotionAggVO> recommendPromotionAggVOS = sceneAggregationsHelper.aggPromotion(paramMap);
if (recommendPromotionAggVOS.size() > size) {
jsonObject.put("promotionList", CollectionUtils.safeSubList(recommendPromotionAggVOS, 0, size));
} else {
jsonObject.put("promotionList", recommendPromotionAggVOS);
}
return new SearchApiResult().setData(jsonObject);
}
}
... ...
... ... @@ -109,4 +109,9 @@ public class SearchScorerFactory {
public IScorer getOfflineSaleOnlyScorer() {
return new OfflineSaleOnlyScorer();
}
// 获取CsBrandKeyWord的打分器
public IScorer getCsBrandKeyWordScorer(String query) {
return new CsBrandKeyWordScorer(query);
}
}
... ...
package com.yoho.search.service.scorer.impl;
import com.yoho.search.base.utils.ProductIndexEsField;
import com.yoho.search.models.YohoFilterFunctionBuilders;
import com.yoho.search.service.scorer.IScorer;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
public class CsBrandKeyWordScorer implements IScorer {
private static final float NEW_PRODUCT_WEIGHT = 10;
private String keyword;
public CsBrandKeyWordScorer(String keyword){
this.keyword = keyword;
}
@Override
public void addScorer(YohoFilterFunctionBuilders yohoFilterFunctionBuilders) {
yohoFilterFunctionBuilders.add(QueryBuilders.termQuery(ProductIndexEsField.csBrandKeyword,keyword), ScoreFunctionBuilders.weightFactorFunction(NEW_PRODUCT_WEIGHT));
}
}
... ...
... ... @@ -18,7 +18,7 @@ import com.yoho.search.service.scorer.IScorer;
public class FeatureFactorScorer implements IScorer {
private static final Double BASE_CONSTANT = 1.0D;
private static final Double FACTOR_CONSTANT = 0.8D;
private static final Double FACTOR_CONSTANT = 0.4D;
private QueryBuilder scoreFilter;
private String featureFactors;
... ...
... ... @@ -10,9 +10,6 @@ import java.util.Map;
public interface IHelperService {
/**
* 搜索帮助列表
*
* @param paramMap
* @return
*/
SearchApiResult helper(Map<String, String> paramMap);
}
... ...
package com.yoho.search.service.service;
import com.yoho.search.models.SearchApiResult;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* 图库服务
* @Author: wangnan
* @Date: Created in 2018/4/16
*/
@Service
public interface IImageRepertoryService {
/**
* 搜索图库列表
*/
SearchApiResult searchImageRepertoryList(Map<String, String> paramMap);
}
... ...
package com.yoho.search.service.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.yoho.error.event.SearchEvent;
import com.yoho.search.base.utils.EventReportEnum;
import com.yoho.search.base.utils.ISearchConstants;
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.core.es.utils.IgnoreSomeException;
import com.yoho.search.models.SearchApiResult;
import com.yoho.search.service.base.SearchCommonService;
import com.yoho.search.service.base.SearchRequestParams;
import com.yoho.search.service.service.IImageRepertoryService;
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.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* 图库服务
* @Author: wangnan
* @Date: Created in 2018/4/16
*/
@Service
public class ImageRepertoryServiceImpl extends BaseService implements IImageRepertoryService, ApplicationEventPublisherAware {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private ApplicationEventPublisher publisher;
@Autowired
private SearchCommonService searchCommonService;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
@Override
public SearchApiResult searchImageRepertoryList(Map<String, String> paramMap) {
try {
logger.info("[class=ImageRepertoryServiceImpl][func=searchImageRepertoryList][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
// 1.构造查询参数
SearchParam searchParam = new SearchParam();
int pageSize = StringUtils.isBlank(paramMap.get("viewNum")) ? 10 : Integer.parseInt(paramMap.get("viewNum"));
int page = StringUtils.isBlank(paramMap.get("page")) ? 1 : Integer.parseInt(paramMap.get("page"));
if (page < 1 || pageSize < 0) {
return new SearchApiResult().setCode(400).setMessage("分页参数错误");
}
if (pageSize > 100) {
pageSize = 100;
}
searchParam.setOffset((page - 1) * pageSize);
searchParam.setSize(pageSize);
//2.配置Filter
BoolQueryBuilder boolFilter = constructHelperFilterBuilder(paramMap);
searchParam.setFiter(boolFilter);
final String indexName = ISearchConstants.INDEX_NAME_IMAGE_REPERTORY;
//3.查询ES
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
SearchApiResult searchApiResult = new SearchApiResult();
if (searchResult == null) {
return searchApiResult.setCode(500);
}
// 8.构造返回结果并加入缓存
JSONObject dataMap = new JSONObject();
dataMap.put("total", searchResult.getTotal());
dataMap.put("page", searchResult.getPage());
dataMap.put("page_size", searchParam.getSize());
dataMap.put("page_total", searchResult.getTotalPage());
dataMap.put("imageRepertory_list", getImageRepertoryMap(searchResult.getResultList()));
return new SearchApiResult().setData(dataMap);
} catch (Exception e) {
publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_IMAGEREPERTORY.getEventName(), EventReportEnum.SEARCHCONTROLLER_IMAGEREPERTORY.getFunctionName(),
EventReportEnum.SEARCHCONTROLLER_IMAGEREPERTORY.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
return SearchApiResultUtils.errorSearchApiResult("imageRepertory", paramMap, e);
}
}
private BoolQueryBuilder constructHelperFilterBuilder(Map<String, String> paramMap) throws Exception {
BoolQueryBuilder boolFilter = QueryBuilders.boolQuery();
boolFilter = boolQueryTermQuery(paramMap, boolFilter, SearchRequestParams.IMAGEREPERTORY_PARAM_ID);
boolFilter = boolQueryTermsQuery(paramMap, boolFilter, SearchRequestParams.IMAGEREPERTORY_PARAM_ITEMID);
boolFilter = boolQueryTermQuery(paramMap, boolFilter, SearchRequestParams.IMAGEREPERTORY_PARAM_CHANNEL);
boolFilter = boolQueryTermQuery(paramMap, boolFilter, SearchRequestParams.IMAGEREPERTORY_PARAM_SEASON);
boolFilter = boolQueryTermQuery(paramMap, boolFilter, SearchRequestParams.IMAGEREPERTORY_PARAM_IMAGESIZE);
boolFilter = boolQueryTermQuery(paramMap, boolFilter, SearchRequestParams.IMAGEREPERTORY_PARAM_IMAGENAME);
boolFilter = boolQueryTermQuery(paramMap, boolFilter, SearchRequestParams.IMAGEREPERTORY_PARAM_IMAGETYPE);
boolFilter = boolQueryTermQuery(paramMap, boolFilter, SearchRequestParams.IMAGEREPERTORY_PARAM_ITEMTYPE);
boolFilter = boolQueryTermQuery(paramMap, boolFilter, SearchRequestParams.IMAGEREPERTORY_PARAM_PORT);
boolFilter = generalHandler(paramMap, boolFilter);
return boolFilter;
}
private List<Map<String, Object>> getImageRepertoryMap(List<Map<String, Object>> resultList) {
List<Map<String, Object>> returnList = new ArrayList<Map<String, Object>>();
for (Map<String, Object> map : resultList) {
Map<String, Object> productMap = getImageRepertoryMap(map);
returnList.add(productMap);
}
return returnList;
}
private Map<String, Object> getImageRepertoryMap(Map<String, Object> map) {
Map<String, Object> productMap = new LinkedHashMap<>();
productMap.put("id", map.get("id") == null ? "" : map.get("id"));
productMap.put("itemId", map.get("itemId") == null ? "" : map.get("itemId"));
productMap.put("channel", map.get("channel") == null ? "" : map.get("channel"));
productMap.put("season", map.get("season") == null ? "" : map.get("season"));
productMap.put("imageUrl", map.get("imageUrl") == null ? "" : map.get("imageUrl"));
productMap.put("imageSize", map.get("imageSize") == null ? "" : map.get("imageSize"));
productMap.put("imageName", map.get("imageName") == null ? "" : map.get("imageName"));
productMap.put("imageType", map.get("imageType") == null ? "" : map.get("imageType"));
productMap.put("itemType", map.get("itemType") == null ? "" : map.get("itemType"));
productMap.put("remarks", map.get("remarks") == null ? "" : map.get("remarks"));
productMap.put("port", map.get("port") == null ? "" : map.get("port"));
productMap.put("menu", map.get("menu") == null ? "" : map.get("menu"));
productMap.put("menuName", map.get("menuName") == null ? "" : map.get("menuName"));
return productMap;
}
}
... ...
... ... @@ -19,6 +19,7 @@ import com.yoho.search.service.helper.AggCommonHelper;
import com.yoho.search.service.helper.SearchCommonHelper;
import com.yoho.search.service.service.IShopListService;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.common.lucene.search.function.CombineFunction;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.index.query.Operator;
... ... @@ -75,9 +76,11 @@ public class ShopListServiceImpl implements IShopListService {
}
queryBuilder.minimumShouldMatch("100%");
// 2.1 全球购得分减半
FilterFunctionBuilder[] filterFunctionBuilders = new FilterFunctionBuilder[1];
filterFunctionBuilders[0] = new FilterFunctionBuilder(QueryBuilders.termQuery("isGlobal", "Y"), ScoreFunctionBuilders.weightFactorFunction(0.5f));
FilterFunctionBuilder[] filterFunctionBuilders = new FilterFunctionBuilder[2];
filterFunctionBuilders[0] = new FilterFunctionBuilder(QueryBuilders.termQuery(ProductIndexEsField.isGlobal, "Y"), ScoreFunctionBuilders.weightFactorFunction(0.5f));
filterFunctionBuilders[1] = new FilterFunctionBuilder(QueryBuilders.termQuery(ProductIndexEsField.csBrandKeyword, keyword), ScoreFunctionBuilders.weightFactorFunction(10f));
FunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(queryBuilder, filterFunctionBuilders);
functionScoreQueryBuilder.boostMode(CombineFunction.MULTIPLY);
searchParam.setQuery(functionScoreQueryBuilder);
// 3、构建filter
... ...
... ... @@ -8,18 +8,14 @@ pool:
redis:
yohoSearchRedis:
cluster: true
cluster: false
sync: false
auth:
timeout: 1000
servers:
- 192.168.103.35:6379
- 192.168.103.78:6379
- 192.168.103.76:6379
- 192.168.102.216:6379
readOnly:
- 192.168.103.35:6379
- 192.168.103.78:6379
- 192.168.103.76:6379
- 192.168.102.216:6379
primary: no
yohoSearchBigDataRedis:
... ...
... ... @@ -8,18 +8,14 @@ pool:
redis:
yohoSearchRedis:
cluster: true
cluster: ${search.redis.iscluster}
sync: false
auth:
auth: ${search.redis.auth}
timeout: 1000
servers:
- ${redis.search.cluster.address0}
- ${redis.search.cluster.address1}
- ${redis.search.cluster.address2}
- ${search.redis.address}:${search.redis.port}
readOnly:
- ${redis.search.cluster.address0}
- ${redis.search.cluster.address1}
- ${redis.search.cluster.address2}
- ${search.redis.address}:${search.redis.port}
primary: no
yohoSearchBigDataRedis:
... ...