...
|
...
|
@@ -2,7 +2,6 @@ package com.yoho.search.service.scene; |
|
|
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.Arrays;
|
|
|
import java.util.Date;
|
|
|
import java.util.HashMap;
|
|
|
import java.util.Iterator;
|
|
|
import java.util.LinkedHashMap;
|
...
|
...
|
@@ -20,17 +19,18 @@ import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders; |
|
|
import org.elasticsearch.search.sort.SortBuilder;
|
|
|
import org.elasticsearch.search.sort.SortBuilders;
|
|
|
import org.elasticsearch.search.sort.SortOrder;
|
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
import com.yoho.search.base.utils.DateUtil;
|
|
|
import com.yoho.search.base.utils.ISearchConstants;
|
|
|
import com.yoho.search.base.utils.ProductIndexEsField;
|
|
|
import com.yoho.search.common.cache.aop.SearchCacheAble;
|
|
|
import com.yoho.search.common.cache.model.SearchCache;
|
|
|
import com.yoho.search.core.es.model.SearchParam;
|
|
|
import com.yoho.search.core.es.model.SearchResult;
|
|
|
import com.yoho.search.core.personalized.PersonalizedSearch;
|
|
|
import com.yoho.search.models.SearchApiResult;
|
|
|
import com.yoho.search.models.YohoFilterFunctionBuilders;
|
|
|
import com.yoho.search.service.base.ProductListSortService;
|
...
|
...
|
@@ -48,7 +48,9 @@ import com.yoho.search.service.scorer.personal.PersonalVectorFeatureSearch; |
|
|
|
|
|
@Service
|
|
|
public class NewGoodProductSceneService extends AbstractCacheAbleService {
|
|
|
|
|
|
|
|
|
private static final Logger logger = LoggerFactory.getLogger(NewGoodProductSceneService.class);
|
|
|
|
|
|
@Autowired
|
|
|
private SearchCommonService searchCommonService;
|
|
|
@Autowired
|
...
|
...
|
@@ -84,54 +86,60 @@ public class NewGoodProductSceneService extends AbstractCacheAbleService { |
|
|
* @return
|
|
|
* @throws Exception
|
|
|
*/
|
|
|
@SearchCacheAble(cacheInMinute =10,cacheName="GOOD_PRODUCT_BY_SKN",excludeParams={"uid"})
|
|
|
public SearchApiResult goodProductListBySkn(Map<String, String> paramMap) throws Exception {
|
|
|
// 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 = searchServiceHelper.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>> results = searchResult.getResultList();
|
|
|
|
|
|
// 5、排序【recProductSkns插到1、5、8的位置】以及条数截取
|
|
|
results = this.sortEsProductList(results, productSkns, recProductSkns);
|
|
|
int pageSize = StringUtils.isBlank(paramMap.get("viewNum")) ? 10 : Integer.parseInt(paramMap.get("viewNum"));
|
|
|
results = results.size() > pageSize ? results.subList(0, pageSize) : results;
|
|
|
|
|
|
// 6、构造返回结果
|
|
|
JSONObject dataMap = new JSONObject();
|
|
|
dataMap.put("total", results.size());
|
|
|
dataMap.put("page", 1);
|
|
|
dataMap.put("page_size", searchParam.getSize());
|
|
|
dataMap.put("page_total", 1);
|
|
|
dataMap.put("product_list", productIndexBaseService.getProductListWithPricePlan(results));
|
|
|
return new SearchApiResult().setData(dataMap);
|
|
|
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 = searchServiceHelper.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>> results = searchResult.getResultList();
|
|
|
|
|
|
// 5、排序【recProductSkns插到1、5、8的位置】以及条数截取
|
|
|
results = this.sortEsProductList(results, productSkns, recProductSkns);
|
|
|
int pageSize = StringUtils.isBlank(paramMap.get("viewNum")) ? 10 : Integer.parseInt(paramMap.get("viewNum"));
|
|
|
results = results.size() > pageSize ? results.subList(0, pageSize) : results;
|
|
|
|
|
|
// 6、构造返回结果
|
|
|
JSONObject dataMap = new JSONObject();
|
|
|
dataMap.put("total", results.size());
|
|
|
dataMap.put("page", 1);
|
|
|
dataMap.put("page_size", searchParam.getSize());
|
|
|
dataMap.put("page_total", 1);
|
|
|
dataMap.put("product_list", productIndexBaseService.getProductListWithPricePlan(results));
|
|
|
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、检测分页参数
|
...
|
...
|
@@ -227,12 +235,12 @@ public class NewGoodProductSceneService extends AbstractCacheAbleService { |
|
|
BoolQueryBuilder randomScorerFilter = QueryBuilders.boolQuery().mustNot(QueryBuilders.termsQuery(ProductIndexEsField.productSkn, firstProductSkns));
|
|
|
scorers.add(new RandomScorer(this.getRandomSeed(paramMap), randomScorerFilter));
|
|
|
|
|
|
// 3、添加特征向量[只计算三个月以内上新的,为了性能]
|
|
|
BoolQueryBuilder persionalFilter = QueryBuilders.boolQuery();
|
|
|
long todayLastTimeSecond = DateUtil.getLastTimeSecond(new Date());
|
|
|
long oneMonthInSecond = 30 * 24 * 60 * 60;
|
|
|
persionalFilter.must(QueryBuilders.rangeQuery("firstShelveTime").from(todayLastTimeSecond - 3 * oneMonthInSecond));
|
|
|
scorers.add(this.getPersonalVectorFeatureScorer(persionalFilter, paramMap));
|
|
|
// // 3、添加特征向量[只计算三个月以内上新的,为了性能]
|
|
|
// BoolQueryBuilder persionalFilter = QueryBuilders.boolQuery();
|
|
|
// long todayLastTimeSecond = DateUtil.getLastTimeSecond(new Date());
|
|
|
// long oneMonthInSecond = 30 * 24 * 60 * 60;
|
|
|
// persionalFilter.must(QueryBuilders.rangeQuery("firstShelveTime").from(todayLastTimeSecond - 3 * oneMonthInSecond));
|
|
|
// scorers.add(this.getPersonalVectorFeatureScorer(persionalFilter, paramMap));
|
|
|
|
|
|
// 4、构建
|
|
|
YohoFilterFunctionBuilders yohoFilterFunctionBuilders = new YohoFilterFunctionBuilders();
|
...
|
...
|
@@ -250,26 +258,31 @@ public class NewGoodProductSceneService extends AbstractCacheAbleService { |
|
|
return functionScoreQueryBuilder;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 个性化的打分器
|
|
|
*
|
|
|
* @param persionalFilter
|
|
|
* @param paramMap
|
|
|
* @return
|
|
|
*/
|
|
|
private IScorer getPersonalVectorFeatureScorer(BoolQueryBuilder persionalFilter, Map<String, String> paramMap) {
|
|
|
// 1、获取PersonalizedSearch
|
|
|
PersonalizedSearch personalizedSearch = personalVectorFeatureSearch.getPersonalizedSearch(paramMap);
|
|
|
if (personalizedSearch == null) {
|
|
|
return null;
|
|
|
}
|
|
|
// 2、为个性化打分添加filter条件
|
|
|
BoolQueryBuilder scoreFilter = QueryBuilders.boolQuery();
|
|
|
long todayLastTimeSecond = DateUtil.getLastTimeSecond(new Date());
|
|
|
long oneMonthInSecond = 30 * 24 * 60 * 60;
|
|
|
scoreFilter.must(QueryBuilders.rangeQuery("firstShelveTime").from(todayLastTimeSecond - 3 * oneMonthInSecond));
|
|
|
return searchScorerFactory.getFeatureFactorScorer(scoreFilter, personalizedSearch.getUserVectorFeature(), personalizedSearch.getVectorFeatureVersion());
|
|
|
}
|
|
|
// /**
|
|
|
// * 个性化的打分器
|
|
|
// *
|
|
|
// * @param persionalFilter
|
|
|
// * @param paramMap
|
|
|
// * @return
|
|
|
// */
|
|
|
// private IScorer getPersonalVectorFeatureScorer(BoolQueryBuilder
|
|
|
// persionalFilter, Map<String, String> paramMap) {
|
|
|
// // 1、获取PersonalizedSearch
|
|
|
// PersonalizedSearch personalizedSearch =
|
|
|
// personalVectorFeatureSearch.getPersonalizedSearch(paramMap);
|
|
|
// if (personalizedSearch == null) {
|
|
|
// return null;
|
|
|
// }
|
|
|
// // 2、为个性化打分添加filter条件
|
|
|
// BoolQueryBuilder scoreFilter = QueryBuilders.boolQuery();
|
|
|
// long todayLastTimeSecond = DateUtil.getLastTimeSecond(new Date());
|
|
|
// long oneMonthInSecond = 30 * 24 * 60 * 60;
|
|
|
// scoreFilter.must(QueryBuilders.rangeQuery("firstShelveTime").from(todayLastTimeSecond
|
|
|
// - 3 * oneMonthInSecond));
|
|
|
// return searchScorerFactory.getFeatureFactorScorer(scoreFilter,
|
|
|
// personalizedSearch.getUserVectorFeature(),
|
|
|
// personalizedSearch.getVectorFeatureVersion());
|
|
|
// }
|
|
|
|
|
|
/**
|
|
|
* 有好货默认的过滤规则
|
...
|
...
|
|