|
|
package com.yoho.search.service.scene;
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.Collections;
|
|
|
import java.util.HashMap;
|
|
|
import java.util.Iterator;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
import java.util.Random;
|
|
|
|
|
|
import javax.annotation.PostConstruct;
|
|
|
|
|
|
import org.apache.commons.lang.StringUtils;
|
|
|
import org.elasticsearch.index.query.BoolQueryBuilder;
|
|
|
import org.elasticsearch.index.query.QueryBuilder;
|
|
|
import org.elasticsearch.index.query.QueryBuilders;
|
|
|
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
|
|
|
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
|
|
|
import org.elasticsearch.search.SearchHit;
|
|
|
import org.elasticsearch.search.SearchHits;
|
|
|
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
|
|
|
import org.elasticsearch.search.aggregations.Aggregation;
|
|
|
import org.elasticsearch.search.aggregations.AggregationBuilders;
|
|
|
import org.elasticsearch.search.aggregations.bucket.MultiBucketsAggregation;
|
|
|
import org.elasticsearch.search.aggregations.bucket.MultiBucketsAggregation.Bucket;
|
|
|
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
|
|
|
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.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
import com.alibaba.fastjson.JSON;
|
|
|
import com.alibaba.fastjson.JSONArray;
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
import com.yoho.search.base.utils.ISearchConstants;
|
|
|
import com.yoho.search.base.utils.ProductIndexEsField;
|
|
|
import com.yoho.search.common.cache.SearchCacheFactory;
|
|
|
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.models.GoodProductBO;
|
|
|
import com.yoho.search.models.SearchApiResult;
|
|
|
import com.yoho.search.models.YohoFilterFunctionBuilders;
|
|
|
import com.yoho.search.service.base.SearchCacheService;
|
|
|
import com.yoho.search.service.base.SearchCommonService;
|
|
|
import com.yoho.search.service.base.index.ProductIndexBaseService;
|
|
|
import com.yoho.search.service.helper.FunctionScoreSearchHelper;
|
|
|
import com.yoho.search.service.helper.SearchCommonHelper;
|
|
|
import com.yoho.search.service.helper.SearchServiceHelper;
|
|
|
|
|
|
@Service
|
|
|
public class GoodProductSceneService {
|
|
|
|
|
|
// private static final Logger logger =
|
|
|
// LoggerFactory.getLogger(GoodProductSceneService.class);
|
|
|
|
|
|
@Autowired
|
|
|
private SearchCommonService searchCommonService;
|
|
|
@Autowired
|
|
|
private SearchServiceHelper searchServiceHelper;
|
|
|
@Autowired
|
|
|
private SearchCommonHelper searchCommonHelper;
|
|
|
@Autowired
|
|
|
private FunctionScoreSearchHelper functionScoreSearchHelper;
|
|
|
@Autowired
|
|
|
private ProductIndexBaseService productIndexBaseService;
|
|
|
@Autowired
|
|
|
private SearchCacheService searchCacheService;
|
|
|
@Autowired
|
|
|
private SearchCacheFactory searchCacheFactory;
|
|
|
|
|
|
private SearchCache productListSearchCache;
|
|
|
|
|
|
@PostConstruct
|
|
|
void init() {
|
|
|
productListSearchCache = searchCacheFactory.getProductListSearchCache();
|
|
|
}
|
|
|
|
|
|
private static final String view_product_skn = "view_product_skn";
|
|
|
private static final String cart_product_skn = "cart_product_skn";
|
|
|
private static final String collect_product_skn = "collect_product_skn";
|
|
|
|
|
|
public SearchApiResult goodProductList(Map<String, String> paramMap) throws Exception {
|
|
|
// 1、检测分页参数
|
|
|
int pageSize = StringUtils.isBlank(paramMap.get("viewNum")) ? 30 : Integer.parseInt(paramMap.get("viewNum"));
|
|
|
int page = StringUtils.isBlank(paramMap.get("page")) ? 1 : Integer.parseInt(paramMap.get("page"));
|
|
|
if (page < 1 || pageSize < 0) {
|
|
|
return new SearchApiResult().setCode(400).setMessage("分页参数不合法");
|
|
|
}
|
|
|
|
|
|
// 1.1 SKN参数获取
|
|
|
List<String> view_product_skns = stringToList(paramMap.getOrDefault(view_product_skn, ""), ",");
|
|
|
List<String> cart_productskns = stringToList(paramMap.getOrDefault(cart_product_skn, ""), ",");
|
|
|
List<String> collect_product_skns = stringToList(paramMap.getOrDefault(collect_product_skn, ""), ",");
|
|
|
|
|
|
// 2、先获取用户浏览的SKN对应的品类列表
|
|
|
List<String> allProductSkn = new ArrayList<String>();
|
|
|
allProductSkn.addAll(view_product_skns);
|
|
|
allProductSkn.addAll(cart_productskns);
|
|
|
allProductSkn.addAll(collect_product_skns);
|
|
|
|
|
|
JSONObject sortAndBrandInfo = this.querySknSortAndBrand(allProductSkn);
|
|
|
|
|
|
// 3、再根据品类和品牌推荐出SKN
|
|
|
List<String> recommondSkns = this.recommondSknsBySortAndBrandInfo(sortAndBrandInfo, paramMap, view_product_skns, cart_productskns, collect_product_skns);
|
|
|
|
|
|
// 4、构造搜索参数
|
|
|
SearchParam searchParam = new SearchParam();
|
|
|
BoolQueryBuilder boolFilter = searchServiceHelper.constructFilterBuilder(paramMap, null);
|
|
|
searchParam.setFiter(this.getDefaultBoolQueryBuilder(boolFilter));
|
|
|
searchParam.setQuery(this.builderGoodProductQueryBuilder(paramMap, boolFilter, recommondSkns));
|
|
|
searchParam.setOffset((page - 1) * pageSize);
|
|
|
searchParam.setSize(pageSize);
|
|
|
// 5、设置返回字段【节省带宽】
|
|
|
List<String> includeFields = productIndexBaseService.getProductIndexIncludeFields();
|
|
|
includeFields.add(ProductIndexEsField.phrase);
|
|
|
searchParam.setIncludeFields(includeFields);
|
|
|
|
|
|
List<SortBuilder<?>> sortBuilders = new ArrayList<SortBuilder<?>>();
|
|
|
sortBuilders.add(SortBuilders.scoreSort().order(SortOrder.DESC));
|
|
|
sortBuilders.add(SortBuilders.fieldSort(ProductIndexEsField.heatValue).order(SortOrder.DESC));
|
|
|
sortBuilders.add(SortBuilders.fieldSort(ProductIndexEsField.id).order(SortOrder.DESC));
|
|
|
searchParam.setSortBuilders(sortBuilders);
|
|
|
|
|
|
// 5)从缓存中获取数据
|
|
|
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
|
|
|
JSONObject cacheObject = searchCacheService.getJSONObjectFromCache(productListSearchCache, indexName, searchParam);
|
|
|
if (cacheObject != null) {
|
|
|
return new SearchApiResult().setData(cacheObject);
|
|
|
}
|
|
|
// 6)查询ES
|
|
|
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
|
|
|
if (searchResult == null) {
|
|
|
return new SearchApiResult().setCode(500).setMessage("execption");
|
|
|
}
|
|
|
// 7)构造返回结果
|
|
|
JSONObject dataMap = new JSONObject();
|
|
|
dataMap.put("total", searchResult.getTotal());
|
|
|
dataMap.put("page", searchResult.getPage());
|
|
|
dataMap.put("page_size", searchParam.getSize());
|
|
|
dataMap.put("page_total", searchResult.getTotalPage());
|
|
|
dataMap.put("product_list", productIndexBaseService.getProductListWithPricePlan(searchResult.getResultList()));
|
|
|
|
|
|
// 8)将结果存进缓存
|
|
|
searchCacheService.addJSONObjectToCache(productListSearchCache, indexName, searchParam, dataMap);
|
|
|
return new SearchApiResult().setData(dataMap);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 获取skn的品类列表和品牌列表
|
|
|
*
|
|
|
* @param productSkns
|
|
|
* @return
|
|
|
*/
|
|
|
private JSONObject querySknSortAndBrand(List<String> productSkns) {
|
|
|
SearchParam searchParam = new SearchParam();
|
|
|
// 1、设置过滤条件
|
|
|
BoolQueryBuilder boolFilter = QueryBuilders.boolQuery();
|
|
|
boolFilter.must(QueryBuilders.termsQuery("productSkn", productSkns));
|
|
|
searchParam.setFiter(boolFilter);
|
|
|
// 2、设置聚合条件,获取所有的品类和品牌
|
|
|
TermsAggregationBuilder smallSortIdAgg = AggregationBuilders.terms("smallSortAgg").field("smallSortId").size(100);
|
|
|
TermsAggregationBuilder 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.setSize(0);
|
|
|
searchParam.setOffset(0);
|
|
|
|
|
|
// 4、先从缓存中获取,如果能取到,则直接返回
|
|
|
JSONObject sortAndBrandJSONObject = searchCacheService.getJSONObjectFromCache(productListSearchCache, 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) {
|
|
|
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(productListSearchCache, 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>();
|
|
|
}
|
|
|
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()));
|
|
|
}
|
|
|
}
|
|
|
return results;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 根据skn参数获取推荐出来的skn列表
|
|
|
*
|
|
|
* @return
|
|
|
*/
|
|
|
private List<String> recommondSknsBySortAndBrandInfo(JSONObject sortAndBrandInfo, Map<String, String> paramMap, List<String> view_product_skns, List<String> cart_productskns,
|
|
|
List<String> collect_product_skns) throws Exception {
|
|
|
// 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>();
|
|
|
}
|
|
|
// 2、构造filter
|
|
|
SearchParam searchParam = new SearchParam();
|
|
|
BoolQueryBuilder boolFilter = searchServiceHelper.constructFilterBuilder(paramMap, null);
|
|
|
boolFilter = this.getDefaultBoolQueryBuilder(boolFilter);
|
|
|
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());
|
|
|
// 强制加上个性化打分
|
|
|
functionScoreSearchHelper.buildFunctionScoreQueryBuild(functionScoreQueryBuilder, boolFilter, paramMap);
|
|
|
searchParam.setQuery(functionScoreQueryBuilder);
|
|
|
|
|
|
// 4、设置聚合条件
|
|
|
String sortField = "_score";
|
|
|
SortOrder sortOrder = SortOrder.DESC;
|
|
|
List<AbstractAggregationBuilder<?>> list = new ArrayList<AbstractAggregationBuilder<?>>();
|
|
|
// 4.1)构造父聚合:品类聚合【同时按子聚合的sort字段排序】
|
|
|
TermsAggregationBuilder parentAggregationBuilder = AggregationBuilders.terms("smallSortAgg").field("smallSortId").size(smallSortIds.size());
|
|
|
// 4.2)构造子聚合:品牌或聚合【同时按子聚合的sort字段排序】
|
|
|
TermsAggregationBuilder 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").sort(SortBuilders.scoreSort().order(sortOrder)).size(1));
|
|
|
list.add(parentAggregationBuilder.subAggregation(sonAggregationBuilder));
|
|
|
searchParam.setAggregationBuilders(list);
|
|
|
|
|
|
// 5、设置分页
|
|
|
searchParam.setSize(0);
|
|
|
searchParam.setOffset(0);
|
|
|
|
|
|
// 6、先从缓存中获取,如果能取到,则直接返回
|
|
|
JSONArray recommendedSknJSONArray = searchCacheService.getJSONArrayFromCache(productListSearchCache, ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
|
|
|
if (recommendedSknJSONArray != null) {
|
|
|
return this.jsonArrayToList(recommendedSknJSONArray, String.class);
|
|
|
}
|
|
|
// 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("smallSortAgg")) {
|
|
|
return new ArrayList<String>();
|
|
|
}
|
|
|
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();
|
|
|
// 9.1、获取推荐出来的商品
|
|
|
recommendedSknJSONArray.addAll(this.getProductSkns(goodProductLists));
|
|
|
// 9.2、再加入用户购物车和收藏夹中的商品
|
|
|
this.addListToJsonArray(recommendedSknJSONArray, cart_productskns);
|
|
|
this.addListToJsonArray(recommendedSknJSONArray, collect_product_skns);
|
|
|
if (cart_productskns.isEmpty() && collect_product_skns.isEmpty()) {
|
|
|
this.addListToJsonArray(recommendedSknJSONArray, view_product_skns);
|
|
|
}
|
|
|
searchCacheService.addJSONArrayToCache(productListSearchCache, indexName, searchParam, recommendedSknJSONArray);
|
|
|
return this.jsonArrayToList(recommendedSknJSONArray, String.class);
|
|
|
}
|
|
|
|
|
|
private void addListToJsonArray(JSONArray recommendedSknJSONArray, List<String> list) {
|
|
|
for (String skn : list) {
|
|
|
if (!recommendedSknJSONArray.contains(skn)) {
|
|
|
recommendedSknJSONArray.add(skn);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
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>();
|
|
|
Random random = new Random();
|
|
|
for (int i = 0; i < maxSknCount; i++) {
|
|
|
for (GoodProductBO goodProductBO : goodProductLists) {
|
|
|
int randomCount = 1 + random.nextInt(2);
|
|
|
results.addAll(goodProductBO.randomGetProductSkn(randomCount));
|
|
|
}
|
|
|
}
|
|
|
return results;
|
|
|
}
|
|
|
|
|
|
private QueryBuilder builderGoodProductQueryBuilder(Map<String, String> paramMap, BoolQueryBuilder boolFilter, List<String> recommendedSknList) {
|
|
|
QueryBuilder queryBuilder = QueryBuilders.matchAllQuery();
|
|
|
// 未推荐出商品则直接走个性化
|
|
|
if (recommendedSknList == null || recommendedSknList.isEmpty()) {
|
|
|
return functionScoreSearchHelper.buildFunctionScoreQueryBuild(queryBuilder, boolFilter, paramMap);
|
|
|
} else {
|
|
|
YohoFilterFunctionBuilders yohoFilterFunctionBuilders = new YohoFilterFunctionBuilders();
|
|
|
Map<Integer, List<String>> recommondSknMap = this.splitProductSkns(recommendedSknList, 2);
|
|
|
float currentGroupScore = 1000;
|
|
|
for (Map.Entry<Integer, List<String>> entry : recommondSknMap.entrySet()) {
|
|
|
yohoFilterFunctionBuilders.add(QueryBuilders.termsQuery("productSkn", entry.getValue()), ScoreFunctionBuilders.weightFactorFunction(currentGroupScore));
|
|
|
currentGroupScore = currentGroupScore - 10;
|
|
|
}
|
|
|
FunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(queryBuilder, yohoFilterFunctionBuilders.getFilterFunctionBuilders());
|
|
|
return functionScoreQueryBuilder;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 有好货默认的过滤规则
|
|
|
*
|
|
|
* @return
|
|
|
*/
|
|
|
private BoolQueryBuilder getDefaultBoolQueryBuilder(BoolQueryBuilder boolFilter) {
|
|
|
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(ProductIndexEsField.breakSizePercent).lt(50));
|
|
|
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 JSON.parseArray(jsonArray.toJSONString(), clazz);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 分组
|
|
|
*
|
|
|
* @param recommendedSknList
|
|
|
* @return
|
|
|
*/
|
|
|
private Map<Integer, List<String>> splitProductSkns(List<String> recommendedSknList, int maxCountPerGroup) {
|
|
|
int maxSize = recommendedSknList.size();
|
|
|
int groupSize = maxSize / maxCountPerGroup;
|
|
|
if (maxSize % maxCountPerGroup > 0) {
|
|
|
groupSize = groupSize + 1;
|
|
|
}
|
|
|
Map<Integer, List<String>> result = new HashMap<Integer, List<String>>();
|
|
|
for (int i = 0; i < groupSize; i++) {
|
|
|
int fromIndex = i * maxCountPerGroup;
|
|
|
int toIndex = (i + 1) * maxCountPerGroup;
|
|
|
result.put(i, recommendedSknList.subList(fromIndex, toIndex > maxSize ? maxSize : toIndex));
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
private List<String> stringToList(String source, String split) {
|
|
|
if (StringUtils.isBlank(source)) {
|
|
|
return new ArrayList<String>();
|
|
|
}
|
|
|
List<String> result = new ArrayList<String>();
|
|
|
for (String part : source.split(split)) {
|
|
|
result.add(part);
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
} |