|
|
package com.yoho.search.service.service.impl;
|
|
|
|
|
|
import static java.util.stream.Collectors.joining;
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.HashSet;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
import java.util.Set;
|
|
|
|
|
|
import org.apache.commons.collections.CollectionUtils;
|
|
|
import org.apache.commons.lang.StringUtils;
|
|
|
import org.elasticsearch.index.query.BoolQueryBuilder;
|
|
|
import org.elasticsearch.index.query.QueryBuilders;
|
|
|
import org.slf4j.Logger;
|
...
|
...
|
@@ -19,7 +17,6 @@ import org.springframework.stereotype.Service; |
|
|
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.aop.SearchCacheAble;
|
|
|
import com.yoho.search.common.utils.SearchApiResultUtils;
|
|
|
import com.yoho.search.core.es.model.SearchParam;
|
|
|
import com.yoho.search.core.es.model.SearchResult;
|
...
|
...
|
@@ -58,26 +55,46 @@ public class ProductListWithSupplyServiceImpl implements IProductListWithSupplyS |
|
|
* 不支持分页,最多返回100个
|
|
|
*/
|
|
|
@Override
|
|
|
@SearchCacheAble(cacheInMinute = 30, cacheName = "PRODUCT_LIST_WITH_SUPPLY")
|
|
|
//@SearchCacheAble(cacheInMinute = 30, cacheName = "PRODUCT_LIST_WITH_SUPPLY", includeParams = { "product_skn" })
|
|
|
public SearchApiResult productListWithSupply(Map<String, String> paramMap) {
|
|
|
try {
|
|
|
// 1)构建基本查询参数
|
|
|
SearchParam searchParam = searchParamHelper.buildDefault(paramMap);
|
|
|
// 1)参数校验
|
|
|
String inputSknListString = paramMap.getOrDefault(SearchRequestParams.PARAM_SEARCH_PRODUCT_SKN, "");
|
|
|
if (inputSknListString == null || inputSknListString.isEmpty()) {
|
|
|
return new SearchApiResult().setCode(400).setMessage("请传SKN参数");
|
|
|
}
|
|
|
// 2)构建searchParam
|
|
|
SearchParam searchParam = new SearchParam();
|
|
|
String[] productSkns = inputSknListString.split(",");
|
|
|
BoolQueryBuilder filter = new BoolQueryBuilder();
|
|
|
// 2.1)查询这些skn
|
|
|
filter.must(QueryBuilders.termsQuery(ProductIndexEsField.productSkn, productSkns));
|
|
|
// 2.2)保留【上架有库存】或【限购】
|
|
|
BoolQueryBuilder shouldFilter = new BoolQueryBuilder();
|
|
|
shouldFilter.should(QueryBuilders.termQuery(ProductIndexEsField.isLimitbuy, "Y"));
|
|
|
shouldFilter.should(QueryBuilders.boolQuery().must(QueryBuilders.termQuery(ProductIndexEsField.status, 1))
|
|
|
.must(QueryBuilders.rangeQuery(ProductIndexEsField.storageNum).gte(1)));
|
|
|
filter.must(shouldFilter);
|
|
|
|
|
|
// 3)设置其他参数
|
|
|
searchParam.setAggregationBuilders(null);
|
|
|
searchParam.setOffset(0);
|
|
|
searchParam.setSize(100);
|
|
|
// 2)查询ES
|
|
|
searchParam.setSize(productSkns.length);
|
|
|
searchParam.setIncludeFields(productIndexBaseService.getProductIndexIncludeFields());
|
|
|
|
|
|
// 4)查询ES
|
|
|
SearchResult searchResult = searchCommonService.doSearch(ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
|
|
|
if (searchResult == null) {
|
|
|
return new SearchApiResult().setCode(500).setMessage("execption");
|
|
|
}
|
|
|
// 3)补充SKN逻辑:记录传入的skn列表,调用搜索,把返回的product列表中的skn记录到一个列表,找出无效的skn,用这些skn查找相似的,加入到之前的返回列表中返回
|
|
|
List<Map<String, Object>> productList = supplySkn(paramMap, searchResult, searchParam);
|
|
|
// 4)构造返回结果
|
|
|
// 5)补充SKN逻辑:记录传入的skn列表,调用搜索,把返回的product列表中的skn记录到一个列表,找出无效的skn,用这些skn查找相似的,加入到之前的返回列表中返回
|
|
|
List<Map<String, Object>> productList = supplySkn(searchResult, productSkns);
|
|
|
|
|
|
// 6)构造返回结果
|
|
|
JSONObject dataMap = new JSONObject();
|
|
|
dataMap.put("total", productList.size());
|
|
|
dataMap.put("page", 1);
|
|
|
dataMap.put("page_size", searchParam.getSize());
|
|
|
dataMap.put("page_size", productSkns.length);
|
|
|
dataMap.put("page_total", 1);
|
|
|
dataMap.put("product_list", productList);
|
|
|
return new SearchApiResult().setData(dataMap);
|
...
|
...
|
@@ -90,85 +107,34 @@ public class ProductListWithSupplyServiceImpl implements IProductListWithSupplyS |
|
|
/**
|
|
|
* 补充相似的skn
|
|
|
*/
|
|
|
private List<Map<String, Object>> supplySkn(Map<String, String> paramMap, SearchResult searchResult, SearchParam searchParam) {
|
|
|
String inputSknListString = paramMap.getOrDefault(SearchRequestParams.PARAM_SEARCH_PRODUCT_SKN, "");
|
|
|
// 输入skn参数列表
|
|
|
String[] inputSknList = inputSknListString.split(",");
|
|
|
@SuppressWarnings("unchecked")
|
|
|
private List<Map<String, Object>> supplySkn(SearchResult searchResult, String[] productSkns) {
|
|
|
// 1、先获取有效skn的变价计划
|
|
|
List<Map<String, Object>> productList = productIndexBaseService.getProductListWithPricePlan(searchResult.getResultList());
|
|
|
// 搜索结果skn列表
|
|
|
// 2、数量一致,不需要补充
|
|
|
if (productList.size() == productSkns.length) {
|
|
|
return productList;
|
|
|
}
|
|
|
// 3、获取已经存在的skn
|
|
|
Set<String> outputSknSet = new HashSet<>();
|
|
|
for (Map<String, Object> product : productList) {
|
|
|
String skn = product.get("product_skn").toString();
|
|
|
outputSknSet.add(skn);
|
|
|
}
|
|
|
// 无效的skn列表(比如不满足库存和状态等)
|
|
|
// 3、获取无效的skn列表
|
|
|
List<String> invalidSknList = new ArrayList<>();
|
|
|
for (int i = 0; i < inputSknList.length; i++) {
|
|
|
if (!outputSknSet.contains(inputSknList[i])) {
|
|
|
invalidSknList.add(inputSknList[i]);
|
|
|
}
|
|
|
}
|
|
|
// 如果无效的skn满足isLimitbuy则保留
|
|
|
invalidSknList = validateSkn(invalidSknList, productList);
|
|
|
String sknString = invalidSknList.stream().collect(joining(","));
|
|
|
int pageSize = searchParam.getSize();
|
|
|
// 需要补充的skn个数
|
|
|
int supplySknNum = 0;
|
|
|
// 如果pageSize等于搜索返回的skn个数,不需要补充
|
|
|
int validSknCount = inputSknList.length - invalidSknList.size();
|
|
|
if (validSknCount < pageSize) {
|
|
|
// 补充的skn数要根据pageSize的大小来确定
|
|
|
// 如果pageSize大于等于输入skn数,补充skn数等于输入skn数减去有效skn数
|
|
|
// 如果pageSize小于输入skn数,补充数等于pageSize减去返回数
|
|
|
if (pageSize >= inputSknList.length) {
|
|
|
supplySknNum = inputSknList.length - validSknCount;
|
|
|
} else {
|
|
|
supplySknNum = pageSize - validSknCount;
|
|
|
for (int i = 0; i < productSkns.length; i++) {
|
|
|
if (!outputSknSet.contains(productSkns[i])) {
|
|
|
invalidSknList.add(productSkns[i]);
|
|
|
}
|
|
|
}
|
|
|
// 如果需要补充数大于0,去调用找相似服务,获取补充数个结果
|
|
|
if (supplySknNum > 0) {
|
|
|
paramMap.put("viewNum", supplySknNum + "");
|
|
|
paramMap.put("product_skn", sknString);
|
|
|
SearchApiResult searchApiResult = similarProductService.similarProductList(paramMap);
|
|
|
JSONObject supplyDataMap = (JSONObject) searchApiResult.getData();
|
|
|
@SuppressWarnings("unchecked")
|
|
|
List<Map<String, Object>> supplyProductList = (List<Map<String, Object>>) supplyDataMap.get("product_list");
|
|
|
productList.addAll(supplyProductList);
|
|
|
}
|
|
|
// 4、执行找相似进行补充
|
|
|
int viewNum = productSkns.length - productList.size();
|
|
|
String productSkn = StringUtils.join(invalidSknList, ",");
|
|
|
SearchApiResult searchApiResult = similarProductService.similarProductList(productSkn,viewNum);
|
|
|
Map<String,Object> dataMap = (Map<String,Object> )searchApiResult.getData();
|
|
|
List<Map<String, Object>> supplyProductList = (List<Map<String, Object>>) dataMap.get("product_list");
|
|
|
productList.addAll(supplyProductList);
|
|
|
return productList;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 如果无效的skn列表中有isLimitbuy的skn,则保留
|
|
|
*/
|
|
|
private List<String> validateSkn(List<String> invalidSknList, List<Map<String, Object>> productList) {
|
|
|
String sknString = invalidSknList.stream().collect(joining(","));
|
|
|
SearchParam searchParam = new SearchParam();
|
|
|
BoolQueryBuilder boolFilter = QueryBuilders.boolQuery();
|
|
|
boolFilter.must(QueryBuilders.termsQuery(ProductIndexEsField.productSkn, sknString.split(",")));
|
|
|
boolFilter.must(QueryBuilders.termQuery(ProductIndexEsField.isLimitbuy, "Y"));
|
|
|
searchParam.setFiter(boolFilter);
|
|
|
searchParam.setQuery(QueryBuilders.matchAllQuery());
|
|
|
searchParam.setSize(invalidSknList.size());
|
|
|
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
|
|
|
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
|
|
|
List<Map<String, Object>> productListValidate = productIndexBaseService.getProductListWithPricePlan(searchResult.getResultList());
|
|
|
// 无效的skn列表(比如不满足库存和状态等)
|
|
|
List<String> trueInvalidSknList = new ArrayList<>();
|
|
|
Set<String> outputSknSet = new HashSet<>();
|
|
|
if (CollectionUtils.isNotEmpty(productListValidate)) {
|
|
|
productList.addAll(productListValidate);
|
|
|
for (Map<String, Object> product : productListValidate) {
|
|
|
String skn = product.get("product_skn").toString();
|
|
|
outputSknSet.add(skn);
|
|
|
}
|
|
|
}
|
|
|
for (int i = 0; i < invalidSknList.size(); i++) {
|
|
|
if (!outputSknSet.contains(invalidSknList.get(i))) {
|
|
|
trueInvalidSknList.add(invalidSknList.get(i));
|
|
|
}
|
|
|
}
|
|
|
return trueInvalidSknList;
|
|
|
}
|
|
|
} |
...
|
...
|
|