Authored by 胡古飞

Merge branch 'master' into 5.6-global

# Conflicts:
#	service/src/main/java/com/yoho/search/service/servicenew/impl/GoodProductListService.java
... ... @@ -43,9 +43,9 @@ public class FunctionScoreSearchHelper {
// 普通个性化的时间维度
private final int oneDaySecondCount = 24 * 60 * 60;
private FirstShelveTimeScore commonFirstShelveTimeScore = new FirstShelveTimeScore(90, 30, 60);
private FirstShelveTimeScore commonFirstShelveTimeScore = new FirstShelveTimeScore(60, 30, 30);
// 新品到着的个性化时间维度
private FirstShelveTimeScore newRecShelveTimeScore = new FirstShelveTimeScore(30, 10, 20);
private FirstShelveTimeScore newRecShelveTimeScore = new FirstShelveTimeScore(14, 7, 7);
private final float globalWeight = 0.50f;
private WeightBuilder genWeightFactorBuilder(float factor) {
... ...
... ... @@ -26,6 +26,8 @@ import org.elasticsearch.search.aggregations.metrics.tophits.TopHits;
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;
... ... @@ -37,19 +39,20 @@ import com.yoho.search.core.es.model.SearchResult;
import com.yoho.search.service.cache.CacheEnum;
import com.yoho.search.service.service.SearchCacheService;
import com.yoho.search.service.service.SearchCommonService;
import com.yoho.search.service.service.base.ProductIndexBaseService;
import com.yoho.search.service.service.helper.AggProductListHelper;
import com.yoho.search.service.service.helper.FunctionScoreSearchHelper;
import com.yoho.search.service.service.helper.SearchCommonHelper;
import com.yoho.search.service.service.helper.SearchServiceHelper;
import com.yoho.search.service.service.helper.SearchSortHelper;
import com.yoho.search.service.servicenew.IGoodProductsService;
import com.yoho.search.service.utils.SearchRequestParams;
import com.yoho.search.service.vo.GoodProductBO;
import com.yoho.search.service.vo.SearchApiResult;
@Service
public class GoodProductListService implements IGoodProductsService {
private static final Logger logger = LoggerFactory.getLogger(GoodProductListService.class);
@Autowired
private SearchCommonService searchCommonService;
@Autowired
... ... @@ -64,17 +67,13 @@ public class GoodProductListService implements IGoodProductsService {
private SearchCommonHelper searchCommonHelper;
@Autowired
private FunctionScoreSearchHelper functionScoreSearchHelper;
@Autowired
private ProductIndexBaseService productIndexBaseService;
private final int maxSmallSortCount = 20;
private final int maxProductSknCountPerSort = 5;
private final int maxCountPerGroup = 3;
// private final float firstSknScore = 300;
private final float recommendedSknMaxScore = 200;
@Override
public SearchApiResult goodProductList(Map<String, String> paramMap) {
boolean openLog = "13420925".equals(paramMap.getOrDefault("uid", "0"));
if (openLog) {
logger.warn("goodProductList param is : [{}]", paramMap.toString());
}
// 1、检测分页参数
int pageSize = StringUtils.isBlank(paramMap.get("viewNum")) ? 30 : Integer.parseInt(paramMap.get("viewNum"));
int page = StringUtils.isBlank(paramMap.get("page")) ? 1 : Integer.parseInt(paramMap.get("page"));
... ... @@ -82,9 +81,14 @@ public class GoodProductListService implements IGoodProductsService {
return new SearchApiResult().setCode(400).setMessage("分页参数不合法");
}
// 2、先获取用户浏览的SKN对应的品类列表
List<Integer> smallSortIds = this.getProductSknSmallSortIds(paramMap, maxSmallSortCount);
// 3、再每个品类下获取5个SKN[每次随机打乱]
List<String> recommondSkns = this.getRecommondedSkns(smallSortIds, maxProductSknCountPerSort, paramMap);
JSONObject sortAndBrandInfo = this.querySknSortAndBrand(paramMap.getOrDefault("product_skn", ""));
// 3、再根据品类和品牌推荐SKN
List<String> recommondSkns = this.recommondSknsBySortAndBrandInfo(sortAndBrandInfo, paramMap);
if (paramMap.getOrDefault("uid", "0").equals("13420925")) {
logger.warn("goodProductList recommondSkns is : [{}]", recommondSkns);
}
// 4、构造搜索参数
SearchParam searchParam = new SearchParam();
... ... @@ -106,6 +110,11 @@ public class GoodProductListService implements IGoodProductsService {
CacheEnum cacheEnum = CacheEnum.EHCACHE;
JSONObject cacheObject = searchCacheService.getJSONObjectFromCache(cacheEnum, indexName, searchParam);
if (cacheObject != null) {
JSONArray product_list = cacheObject.getJSONArray("product_list");
if(product_list!=null){
// Collections.shuffle(product_list);
// cacheObject.put("product_list", product_list);
}
return new SearchApiResult().setData(cacheObject);
}
// 6)查询ES
... ... @@ -119,42 +128,22 @@ public class GoodProductListService implements IGoodProductsService {
dataMap.put("page", searchResult.getPage());
dataMap.put("page_size", searchParam.getSize());
dataMap.put("page_total", searchResult.getTotalPage());
dataMap.put("product_list", productIndexBaseService.getProductListWithPricePlan(searchResult.getResultList(), Arrays.asList("phrase")));
dataMap.put("product_list", searchServiceHelper.getProductMapList(searchResult.getResultList(), Arrays.asList("phrase")));
// 8)将结果存进缓存
searchCacheService.addJSONObjectToCache(cacheEnum, indexName, searchParam, dataMap);
return new SearchApiResult().setData(dataMap);
}
private QueryBuilder builderGoodProductQueryBuilder(Map<String, String> paramMap, List<String> recommendedSknList) {
QueryBuilder queryBuilder = QueryBuilders.matchAllQuery();
FunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(queryBuilder);
// 针对推荐出来的SKN做加分
if (recommendedSknList != null && !recommendedSknList.isEmpty()) {
Map<Integer, List<String>> recommondSknMap = this.splitProductSkns(recommendedSknList, maxCountPerGroup);
float currentGroupScore = recommendedSknMaxScore;
for (Map.Entry<Integer, List<String>> entry : recommondSknMap.entrySet()) {
functionScoreQueryBuilder.add(QueryBuilders.termsQuery("productSkn", entry.getValue()), ScoreFunctionBuilders.weightFactorFunction(currentGroupScore));
currentGroupScore = currentGroupScore - 10;
}
}
// 加上个性化打分
if (searchCommonHelper.isNeedPersonalSearch(paramMap)) {
functionScoreSearchHelper.addCommonPersonalizedScriptScore(functionScoreQueryBuilder, paramMap);
}
return functionScoreQueryBuilder;
}
/**
* 获取SKN相关的小分类
* 获取skn的品类列表和品牌列表
*
* @param productSkns
* @return
*/
private List<Integer> getProductSknSmallSortIds(Map<String, String> paramMap, int maxCount) {
String productSkns = paramMap.get(SearchRequestParams.PARAM_SEARCH_PRODUCT_SKN);
private JSONObject querySknSortAndBrand(String productSkns) {
if (StringUtils.isBlank(productSkns)) {
return new ArrayList<Integer>();
return new JSONObject();
}
String[] productSknArray = productSkns.split(",");
SearchParam searchParam = new SearchParam();
... ... @@ -162,102 +151,108 @@ public class GoodProductListService implements IGoodProductsService {
BoolQueryBuilder boolFilter = QueryBuilders.boolQuery();
boolFilter.must(QueryBuilders.termsQuery("productSkn", productSknArray));
searchParam.setFiter(boolFilter);
// 2、设置聚合条件
final String aggName = "smallSortAgg";
TermsBuilder smallSortIdAgg = AggregationBuilders.terms(aggName).field("smallSortId").size(maxCount);
searchParam.setAggregationBuilders(Arrays.asList(smallSortIdAgg));
// 2、设置聚合条件,获取所有的品类和品牌
TermsBuilder smallSortIdAgg = AggregationBuilders.terms("smallSortAgg").field("smallSortId").size(100);
TermsBuilder brandIdAgg = AggregationBuilders.terms("brandAgg").field("brandId").size(100);
List<AbstractAggregationBuilder> aggregationBuilders = new ArrayList<AbstractAggregationBuilder>();
aggregationBuilders.add(smallSortIdAgg);
aggregationBuilders.add(brandIdAgg);
searchParam.setAggregationBuilders(aggregationBuilders);
// 3、设置分页
searchParam.setPage(0);
searchParam.setSize(0);
searchParam.setOffset(0);
// 4、先从缓存中获取,如果能取到,则直接返回
JSONArray sknSmallSortIdJSONArray = searchCacheService.getJSONArrayFromCache(ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
if (sknSmallSortIdJSONArray != null) {
return this.jsonArrayToList(sknSmallSortIdJSONArray, Integer.class);
JSONObject sortAndBrandJSONObject = searchCacheService.getJSONObjectFromCache(ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
if (sortAndBrandJSONObject != null) {
return sortAndBrandJSONObject;
}
// 5、执行搜索
SearchResult searchResult = searchCommonService.doSearch(ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
if (searchResult == null || searchResult.getAggMaps() == null || searchResult.getAggMaps().get("smallSortAgg") == null) {
if (searchResult == null || searchResult.getAggMaps() == null) {
return new JSONObject();
}
Map<String, Aggregation> aggMaps = searchResult.getAggMaps();
// 6、从聚合结果中获取品牌和品类id
List<Integer> smallSortIds = this.getIdsFromAggMaps(aggMaps, "smallSortAgg");
List<Integer> brandIds = this.getIdsFromAggMaps(aggMaps, "brandAgg");
// 7、构造返回结果并加入缓存
sortAndBrandJSONObject = new JSONObject();
sortAndBrandJSONObject.put("brandIds", brandIds);
sortAndBrandJSONObject.put("smallSortIds", smallSortIds);
searchCacheService.addJSONObjectToCache(ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam, sortAndBrandJSONObject);
return sortAndBrandJSONObject;
}
private List<Integer> getIdsFromAggMaps(Map<String, Aggregation> aggMaps, String aggName) {
if (!aggMaps.containsKey(aggName)) {
return new ArrayList<Integer>();
}
sknSmallSortIdJSONArray = new JSONArray();
MultiBucketsAggregation aggregation = (MultiBucketsAggregation) searchResult.getAggMaps().get(aggName);
Iterator<? extends Bucket> smallSortIdIterator = aggregation.getBuckets().iterator();
while (smallSortIdIterator.hasNext()) {
Bucket smallSortIdBucket = smallSortIdIterator.next();
if (StringUtils.isNumeric(smallSortIdBucket.getKeyAsString())) {
sknSmallSortIdJSONArray.add(Integer.valueOf(smallSortIdBucket.getKeyAsString()));
MultiBucketsAggregation aggregation = (MultiBucketsAggregation) aggMaps.get(aggName);
List<Integer> results = new ArrayList<Integer>();
Iterator<? extends Bucket> iterator = aggregation.getBuckets().iterator();
while (iterator.hasNext()) {
Bucket bucket = iterator.next();
if (StringUtils.isNumeric(bucket.getKeyAsString())) {
results.add(Integer.valueOf(bucket.getKeyAsString()));
}
}
searchCacheService.addJSONArrayToCache(ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam, sknSmallSortIdJSONArray);
return this.jsonArrayToList(sknSmallSortIdJSONArray, Integer.class);
}
/**
* 有好货默认的过滤规则
*
* @return
*/
private BoolQueryBuilder getDefaultBoolQueryBuilder() {
BoolQueryBuilder boolFilter = QueryBuilders.boolQuery();
boolFilter.mustNot(QueryBuilders.termsQuery("isSeckill", "Y"));
boolFilter.mustNot(QueryBuilders.termsQuery("isGlobal", "Y"));
boolFilter.must(QueryBuilders.termQuery("status", 1));
boolFilter.must(QueryBuilders.termQuery("isOutlets", 2));
boolFilter.must(QueryBuilders.termQuery("attribute", 1));
// 默认推库存>2,非断码,并且短评存在的数据
boolFilter.must(QueryBuilders.rangeQuery("storageNum").gte(2));
boolFilter.must(QueryBuilders.rangeQuery("breakingRate").lt(50));
boolFilter.must(QueryBuilders.rangeQuery("basePinRatio").lt(3.5));
boolFilter.must(QueryBuilders.termQuery("isPhraseExist", "Y"));
return boolFilter;
return results;
}
/**
* 每个品类为用户推荐maxSize个SKN
* 根据skn参数获取推荐出来的skn列表
*
* @param smallSortIds
* @param maxSize
* @param paramMap
* @return
*/
private List<String> getRecommondedSkns(List<Integer> smallSortIds, int maxSizePerSort, Map<String, String> paramMap) {
// 1、如果品类为空,则直接返回
if (smallSortIds == null || smallSortIds.isEmpty()) {
private List<String> recommondSknsBySortAndBrandInfo(JSONObject sortAndBrandInfo, Map<String, String> paramMap) {
// 1、获取品牌id和品类id
if (sortAndBrandInfo == null || sortAndBrandInfo.isEmpty()) {
return new ArrayList<String>();
}
JSONArray brandIdJSONArray = sortAndBrandInfo.getJSONArray("brandIds");
JSONArray smallSortIdJSONArray = sortAndBrandInfo.getJSONArray("smallSortIds");
List<Integer> brandIds = this.jsonArrayToList(brandIdJSONArray, Integer.class);
List<Integer> smallSortIds = this.jsonArrayToList(smallSortIdJSONArray, Integer.class);
if (brandIds.isEmpty() && smallSortIds.isEmpty()) {
return new ArrayList<String>();
}
SearchParam searchParam = new SearchParam();
// 2、构造filter
SearchParam searchParam = new SearchParam();
BoolQueryBuilder boolFilter = this.getDefaultBoolQueryBuilder();
boolFilter.must(QueryBuilders.termsQuery("smallSortId", smallSortIds));
BoolQueryBuilder brandAndSortFilter = new BoolQueryBuilder();
if (!brandIds.isEmpty()) {
brandAndSortFilter.should(QueryBuilders.termsQuery("brandId", brandIds));
}
if (!smallSortIds.isEmpty()) {
brandAndSortFilter.should(QueryBuilders.termsQuery("smallSortId", smallSortIds));
}
boolFilter.must(brandAndSortFilter);
searchParam.setFiter(boolFilter);
// 3、构造query
FunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(QueryBuilders.matchAllQuery());
// 针对看过的SKN做加分
String productSkns = paramMap.get(SearchRequestParams.PARAM_SEARCH_PRODUCT_SKN);
if (!StringUtils.isBlank(productSkns)) {
functionScoreQueryBuilder.add(QueryBuilders.termsQuery("productSkn", productSkns.split(",")), ScoreFunctionBuilders.weightFactorFunction(100));
}
// 强制加上个性化打分
functionScoreSearchHelper.addCommonPersonalizedScriptScore(functionScoreQueryBuilder, paramMap);
searchParam.setQuery(functionScoreQueryBuilder);
// 4、设置聚合条件
final String firstAggName = "firstAgg";
String order = "_score:desc";
String sortField = order.split(":")[0];
SortOrder sortOrder = order.split(":")[1].equals("desc") ? SortOrder.DESC : SortOrder.ASC;
String sortField = "_score";
SortOrder sortOrder = SortOrder.DESC;
List<AbstractAggregationBuilder> list = new ArrayList<AbstractAggregationBuilder>();
// 4.1)构造父聚合:品牌或品类聚合【同时按子聚合的sort字段排序】
TermsBuilder parentAggregationBuilder = AggregationBuilders.terms(firstAggName).field("smallSortId").size(smallSortIds.size());
// 4.2)添加子聚合:取得分最大的值
parentAggregationBuilder.subAggregation(AggregationBuilders.max("sort").field(sortField));
// 4.3)添加孙聚合:取打分最高的一个product
parentAggregationBuilder.subAggregation(AggregationBuilders.topHits("product").addSort(SortBuilders.fieldSort(sortField).order(sortOrder)).setSize(maxSizePerSort));
list.add(parentAggregationBuilder);
// 4.1)构造父聚合:品类聚合【同时按子聚合的sort字段排序】
TermsBuilder parentAggregationBuilder = AggregationBuilders.terms("smallSortAgg").field("smallSortId").size(smallSortIds.size());
// 4.2)构造子聚合:品牌或聚合【同时按子聚合的sort字段排序】
TermsBuilder sonAggregationBuilder = AggregationBuilders.terms("brandAgg").field("brandId").size(brandIds.size());
// 4.3)为子聚合添加孙聚合:取得分最大的值
sonAggregationBuilder.subAggregation(AggregationBuilders.max("sort").field(sortField));
// 4.4)为子聚合孙聚合:取打分最高的一个product
sonAggregationBuilder.subAggregation(AggregationBuilders.topHits("product").addSort(SortBuilders.fieldSort(sortField).order(sortOrder)).setSize(1));
list.add(parentAggregationBuilder.subAggregation(sonAggregationBuilder));
searchParam.setAggregationBuilders(list);
// 5、设置分页
... ... @@ -270,26 +265,123 @@ public class GoodProductListService implements IGoodProductsService {
if (recommendedSknJSONArray != null) {
return this.jsonArrayToList(recommendedSknJSONArray, String.class);
}
// 7、执行搜索,并构造返回结果
// 7、执行搜索
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
if (searchResult == null || searchResult.getAggMaps() == null) {
return new ArrayList<String>();
}
// 8、获取搜索结果
Map<String, Aggregation> aggMaps = searchResult.getAggMaps();
if (!aggMaps.containsKey(firstAggName)) {
if (!aggMaps.containsKey("smallSortAgg")) {
return new ArrayList<String>();
}
List<String> recommendedSknList = this.getRecommendedSknList((MultiBucketsAggregation) aggMaps.get(firstAggName));
List<GoodProductBO> goodProductLists = new ArrayList<GoodProductBO>();
Iterator<? extends Bucket> smallSortIterator = ((MultiBucketsAggregation) aggMaps.get("smallSortAgg")).getBuckets().iterator();
while (smallSortIterator.hasNext()) {
Bucket smallSortBucket = smallSortIterator.next();
Map<String, Aggregation> smallSortAggMap = smallSortBucket.getAggregations().getAsMap();
if (!smallSortAggMap.containsKey("brandAgg")) {
continue;
}
Iterator<? extends Bucket> brandIdIterator = ((MultiBucketsAggregation) smallSortAggMap.get("brandAgg")).getBuckets().iterator();
List<String> productSkns = new ArrayList<String>();
while (brandIdIterator.hasNext()) {
Bucket brandIdBucket = brandIdIterator.next();
if (brandIdBucket.getAggregations().getAsMap().containsKey("product")) {
TopHits topHits = brandIdBucket.getAggregations().get("product");
if (topHits != null) {
SearchHits hits = topHits.getHits();
for (SearchHit hit : hits.getHits()) {
productSkns.add("" + hit.getSource().get("productSkn"));
}
}
}
}
if (!productSkns.isEmpty()) {
Collections.shuffle(productSkns);
goodProductLists.add(new GoodProductBO(smallSortBucket.getKeyAsString(), productSkns));
}
}
Collections.shuffle(goodProductLists);
// 9、构造返回结果
recommendedSknJSONArray = new JSONArray();
for (String recommendedSkn : recommendedSknList) {
recommendedSknJSONArray.add(recommendedSkn);
// 9.1、获取推荐出来的商品
recommendedSknJSONArray.addAll(this.getProductSkns(goodProductLists));
// 9.2、再加入用户看过的商品前面
for (String skn : paramMap.getOrDefault("product_skn", "").split(",")) {
if (!recommendedSknJSONArray.contains(skn)) {
recommendedSknJSONArray.add(skn);
}
}
searchCacheService.addJSONArrayToCache(indexName, searchParam, recommendedSknJSONArray);
return this.jsonArrayToList(recommendedSknJSONArray, String.class);
}
private List<String> getProductSkns(List<GoodProductBO> goodProductLists) {
if (goodProductLists == null || goodProductLists.isEmpty()) {
return new ArrayList<String>();
}
int maxSknCount = 0;
for (GoodProductBO goodProductBO : goodProductLists) {
int productSknSize = goodProductBO.getProductSkn().size();
if (maxSknCount < productSknSize) {
maxSknCount = productSknSize;
}
}
List<String> results = new ArrayList<String>();
for (int i = 0; i < maxSknCount; i++) {
for (GoodProductBO goodProductBO : goodProductLists) {
int randomCount = 1 + (int) (Math.random() * 2);
results.addAll(goodProductBO.randomGetProductSkn(randomCount));
}
}
return results;
}
private QueryBuilder builderGoodProductQueryBuilder(Map<String, String> paramMap, List<String> recommendedSknList) {
QueryBuilder queryBuilder = QueryBuilders.matchAllQuery();
FunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(queryBuilder);
// 针对推荐出来的SKN做加分
if (recommendedSknList != null && !recommendedSknList.isEmpty()) {
Map<Integer, List<String>> recommondSknMap = this.splitProductSkns(recommendedSknList, 2);
float currentGroupScore = 1000;
for (Map.Entry<Integer, List<String>> entry : recommondSknMap.entrySet()) {
functionScoreQueryBuilder.add(QueryBuilders.termsQuery("productSkn", entry.getValue()), ScoreFunctionBuilders.weightFactorFunction(currentGroupScore));
currentGroupScore = currentGroupScore - 10;
}
}
// 加上个性化打分
if (searchCommonHelper.isNeedPersonalSearch(paramMap)) {
functionScoreSearchHelper.addCommonPersonalizedScriptScore(functionScoreQueryBuilder, paramMap);
}
return functionScoreQueryBuilder;
}
/**
* 有好货默认的过滤规则
*
* @return
*/
private BoolQueryBuilder getDefaultBoolQueryBuilder() {
BoolQueryBuilder boolFilter = QueryBuilders.boolQuery();
boolFilter.mustNot(QueryBuilders.termsQuery("isSeckill", "Y"));
boolFilter.mustNot(QueryBuilders.termsQuery("isGlobal", "Y"));
boolFilter.must(QueryBuilders.termQuery("status", 1));
boolFilter.must(QueryBuilders.termQuery("isOutlets", 2));
boolFilter.must(QueryBuilders.termQuery("attribute", 1));
// 默认推库存>2,非断码,并且短评存在的数据
boolFilter.must(QueryBuilders.rangeQuery("storageNum").gte(2));
boolFilter.must(QueryBuilders.rangeQuery("breakingRate").lt(50));
boolFilter.must(QueryBuilders.rangeQuery("basePinRatio").lt(3.5));
boolFilter.must(QueryBuilders.termQuery("isPhraseExist", "Y"));
return boolFilter;
}
private <T> List<T> jsonArrayToList(JSONArray jsonArray, Class<T> clazz) {
if (jsonArray == null) {
return new ArrayList<T>();
}
return JSONObject.parseArray(jsonArray.toJSONString(), clazz);
}
... ... @@ -315,40 +407,11 @@ public class GoodProductListService implements IGoodProductsService {
return result;
}
/**
* 获取聚合出来的商品
*
* @param aggregation
* @return
*/
private List<String> getRecommendedSknList(MultiBucketsAggregation aggregation) {
Iterator<? extends Bucket> itAgg = aggregation.getBuckets().iterator();
List<String> recommendedSknList = new ArrayList<String>();
while (itAgg.hasNext()) {
Bucket lt = itAgg.next();
if (lt.getAggregations().getAsMap().containsKey("product")) {
TopHits topHits = lt.getAggregations().get("product");
if (topHits != null) {
SearchHits hits = topHits.getHits();
for (SearchHit hit : hits.getHits()) {
recommendedSknList.add("" + hit.getSource().get("productSkn"));
}
}
}
public static List<String> getNewList(List<String> oldList) {
List<String> newList = new ArrayList<String>();
for (String element : oldList) {
newList.add(element);
}
Collections.shuffle(recommendedSknList);
return recommendedSknList;
return newList;
}
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
for (int i = 1; i <= 99; i++) {
list.add(i + "");
}
Map<Integer, List<String>> results = new GoodProductListService().splitProductSkns(list, 20);
for (Map.Entry<Integer, List<String>> entry : results.entrySet()) {
System.out.println(entry.getKey() + "_" + entry.getValue());
}
}
}
... ...
... ... @@ -88,7 +88,7 @@ public class SearchSortGroupService implements ISearchSortGroupService, Applicat
// 性别
if (paramMap.containsKey(SearchRequestParams.PARAM_SEARCH_GENDER)) {
String[] genders = paramMap.get(SearchRequestParams.PARAM_SEARCH_GENDER).split(",");
boolFilter.must(QueryBuilders.termQuery("gender", genders));
boolFilter.must(QueryBuilders.termsQuery("gender", genders));
}
// 如果contain_global!=Y,则过滤掉全球购的商品[全球购商品融合需求]
if (!searchCommonHelper.containGlobal(paramMap)) {
... ...
package com.yoho.search.service.vo;
import java.util.ArrayList;
import java.util.List;
public class GoodProductBO {
private String smallSortId;
private List<String> productSkn;
public GoodProductBO(String smallSortId, List<String> productSkn) {
super();
this.smallSortId = smallSortId;
this.productSkn = productSkn;
}
public String getSmallSortId() {
return smallSortId;
}
public List<String> getProductSkn() {
return productSkn;
}
public List<String> randomGetProductSkn(int count) {
List<String> results = new ArrayList<String>();
if (productSkn == null || productSkn.isEmpty()) {
return results;
}
for (int i = 0; i < count; i++) {
if (!productSkn.isEmpty()) {
results.add(productSkn.remove(0));
}
}
return results;
}
}
... ...