Authored by 胡古飞

找相似支持传shopId

... ... @@ -27,6 +27,7 @@ import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yoho.search.base.utils.ConvertUtils;
import com.yoho.search.base.utils.ISearchConstants;
import com.yoho.search.core.es.model.SearchParam;
import com.yoho.search.core.es.model.SearchResult;
... ... @@ -108,23 +109,23 @@ public class SearchLikeServiceImpl implements ISearchLikeService {
return new SearchApiResult().setCode(400).setMessage("请输入SKN");
}
// 2、获取当前查询的SKN的基本信息
Map<String, Object> productInfo = this.getProductSknInfo(productSkn);
if (productInfo == null) {
JSONObject productInfoInEs = this.getProductInfoInEs(productSkn);
if (productInfoInEs == null) {
return new SearchApiResult().setCode(400).setMessage("SKN不存在");
}
// 3、检测分页参数
int pageSize = StringUtils.isBlank(paramMap.get("viewNum")) ? 30 : Integer.parseInt(paramMap.get("viewNum"));
int pageSize = StringUtils.isBlank(paramMap.get("viewNum")) ? 60 : 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 > 30 || pageSize < 10) {
pageSize = 30;
if (pageSize > 60 || pageSize < 10) {
pageSize = 60;
}
// 4、获取同一个品牌下的最多20个商品
JSONArray inBrandProductList = this.getProductListInBrand(productInfo, paramMap, 20);
// 4、获取同一个品牌下的最多20个商品
JSONArray inBrandProductList = this.getProductListInBrand(productInfoInEs, paramMap, 20);
// 5、获取不同品牌下的余下数量的商品[通过聚合的方式来查找]
List<String> notInProductSkns = new ArrayList<String>();
for (int i = 0; i < inBrandProductList.size(); i++) {
... ... @@ -132,7 +133,7 @@ public class SearchLikeServiceImpl implements ISearchLikeService {
notInProductSkns.add(product.getString("product_skn"));
}
notInProductSkns.add(productSkn);
JSONArray notInBrandProductList = this.getProductListNotInBrand(productInfo, paramMap, notInProductSkns, pageSize - inBrandProductList.size());
JSONArray notInBrandProductList = this.getProductListNotInBrand(productInfoInEs, paramMap, notInProductSkns, pageSize - inBrandProductList.size());
// 6、构造返回结果
Map<String, Object> dataMap = new HashMap<String, Object>();
... ... @@ -144,12 +145,28 @@ public class SearchLikeServiceImpl implements ISearchLikeService {
dataMap.put("page_total", 1);
dataMap.put("page_size", pageSize);
dataMap.put("total", productList.size());
dataMap.put("product_info", productInfo);
dataMap.put("product_info", this.genProductInfoResult(productInfoInEs));
dataMap.put("product_list", productList);
return new SearchApiResult().setData(dataMap);
}
private JSONObject getProductSknInfo(String productSkn) {
private Map<String, Object> genProductInfoResult(JSONObject productInfoInEs) {
List<Map<String, Object>> resultList = new ArrayList<Map<String, Object>>();
resultList.add(productInfoInEs);
List<Map<String, Object>> results = searchServiceHelper.getProductMapList(resultList);
if (results == null || results.isEmpty()) {
return null;
}
return results.get(0);
}
/**
* 获取SKN在ES中的原生信息
*
* @param productSkn
* @return
*/
private JSONObject getProductInfoInEs(String productSkn) {
SearchParam searchParam = new SearchParam();
searchParam.setQuery(QueryBuilders.matchAllQuery());
BoolQueryBuilder boolFilter = QueryBuilders.boolQuery();
... ... @@ -174,12 +191,8 @@ public class SearchLikeServiceImpl implements ISearchLikeService {
if (productLists == null || productLists.isEmpty()) {
return null;
}
Map<String, Object> productInfoMap = searchServiceHelper.getProductMap(productLists.get(0));
if (productInfoMap == null) {
return null;
}
jsonObject = new JSONObject();
jsonObject.putAll(productInfoMap);
jsonObject.putAll(productLists.get(0));
searchCacheService.addJSONObjectToCache(productIndexName, searchParam, jsonObject);
return jsonObject;
}
... ... @@ -192,14 +205,14 @@ public class SearchLikeServiceImpl implements ISearchLikeService {
* @param limit
* @return
*/
private JSONArray getProductListInBrand(Map<String, Object> productInfo, Map<String, String> paramMap, int limit) {
private JSONArray getProductListInBrand(JSONObject productInfoInEs, Map<String, String> paramMap, int limit) {
SearchParam searchParam = new SearchParam();
// 1、构建Query
QueryBuilder queryBuilder = this.genQueryBuilder(productInfo, paramMap, true);
QueryBuilder queryBuilder = this.genQueryBuilder(productInfoInEs, paramMap, true);
searchParam.setQuery(queryBuilder);
// 2、设置过滤条件
BoolQueryBuilder booleanQueryBuilder = this.genBoolQueryBuilder(productInfo, Arrays.asList(paramMap.get(SearchRequestParams.PARAM_SYNC_SKN)), true);
BoolQueryBuilder booleanQueryBuilder = this.genBoolQueryBuilder(productInfoInEs, paramMap, Arrays.asList(paramMap.get(SearchRequestParams.PARAM_SYNC_SKN)), true);
searchParam.setFiter(booleanQueryBuilder);
// 3、设置排序规则[按打分排序]
... ... @@ -238,14 +251,14 @@ public class SearchLikeServiceImpl implements ISearchLikeService {
* @param limit
* @return
*/
private JSONArray getProductListNotInBrand(Map<String, Object> productInfo, Map<String, String> paramMap, List<String> notInProductSkns, int limit) {
private JSONArray getProductListNotInBrand(JSONObject productInfoInEs, Map<String, String> paramMap, List<String> notInProductSkns, int limit) {
SearchParam searchParam = new SearchParam();
// 1、构建Query
QueryBuilder queryBuilder = this.genQueryBuilder(productInfo, paramMap, false);
QueryBuilder queryBuilder = this.genQueryBuilder(productInfoInEs, paramMap, false);
searchParam.setQuery(queryBuilder);
// 2、设置过滤条件
BoolQueryBuilder booleanQueryBuilder = this.genBoolQueryBuilder(productInfo, notInProductSkns, false);
BoolQueryBuilder booleanQueryBuilder = this.genBoolQueryBuilder(productInfoInEs, paramMap, notInProductSkns, false);
searchParam.setFiter(booleanQueryBuilder);
// 3、设置聚合条件
... ... @@ -255,7 +268,8 @@ public class SearchLikeServiceImpl implements ISearchLikeService {
SortOrder sortOrder = order.split(":")[1].equals("desc") ? SortOrder.DESC : SortOrder.ASC;
List<AbstractAggregationBuilder> list = new ArrayList<AbstractAggregationBuilder>();
// 3.1)构造父聚合:品牌或品类聚合【同时按子聚合的sort字段排序】
TermsBuilder brandAggregationBuilder = AggregationBuilders.terms(firstAggName).field("brandId").order(Terms.Order.aggregation("sort", sortOrder.equals(SortOrder.ASC))).size(200 + limit);
TermsBuilder brandAggregationBuilder = AggregationBuilders.terms(firstAggName).field("brandId").order(Terms.Order.aggregation("sort", sortOrder.equals(SortOrder.ASC)))
.size(200 + limit);
// 3.2)添加子聚合:取得分最大的值
brandAggregationBuilder.subAggregation(AggregationBuilders.max("sort").field(sortField));
// 3.3)添加孙聚合:取打分最高的一个product
... ... @@ -283,21 +297,24 @@ public class SearchLikeServiceImpl implements ISearchLikeService {
if (!aggMaps.containsKey(firstAggName)) {
return new JSONArray();
}
List<Map<String, Object>> productList = aggProductListHelper.getProductListFromAggregation(((MultiBucketsAggregation) aggMaps.get(firstAggName)), limit, sortField,sortOrder);
List<Map<String, Object>> productList = aggProductListHelper.getProductListFromAggregation(((MultiBucketsAggregation) aggMaps.get(firstAggName)), limit, sortField,
sortOrder);
productJSONArray = this.listToJsonArray(productList);
searchCacheService.addJSONArrayToCache(indexName, searchParam, productJSONArray);
return productJSONArray;
}
private QueryBuilder genQueryBuilder(Map<String, Object> productInfo, Map<String, String> paramMap, boolean isInBrand) {
private QueryBuilder genQueryBuilder(JSONObject productInfoInEs, Map<String, String> paramMap, boolean isInBrand) {
// 1、设置查询的值
String product_name = (String) productInfo.get("product_name");
String brand_name = (String) productInfo.get("brand_name");
String query = product_name;
String productName = productInfoInEs.getString("productName");
String standardOnlyNames = productInfoInEs.getString("standardOnlyNames");
String brandName = productInfoInEs.getString("brandName");
String query = productName + "," + standardOnlyNames;
if (isInBrand) {
query = query + "," + brand_name;
query = query + "," + brandName;
} else {
query = query.replaceAll(brand_name, "");
query = query.replaceAll(brandName, "");
}
// 2、设置字段权重
MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(query);
... ... @@ -306,23 +323,27 @@ public class SearchLikeServiceImpl implements ISearchLikeService {
multiMatchQueryBuilder.field(searchFieldBoost.getFieldName(), searchFieldBoost.getBoost());
}
// 3、设置匹配度
multiMatchQueryBuilder.minimumShouldMatch("50%");
if (isInBrand) {
multiMatchQueryBuilder.minimumShouldMatch("50%");
} else {
multiMatchQueryBuilder.minimumShouldMatch("66%");
}
// 4、添加个性化打分
QueryBuilder queryBuilder = functionScoreSearchHelper.buildFunctionScoreQueryBuild(multiMatchQueryBuilder, paramMap);
return queryBuilder;
}
private BoolQueryBuilder genBoolQueryBuilder(Map<String, Object> productInfo, List<String> notProductSkns, boolean isInBrand) {
private BoolQueryBuilder genBoolQueryBuilder(JSONObject productInfoInEs, Map<String, String> paramMap, List<String> notProductSkns, boolean isInBrand) {
BoolQueryBuilder boolFilter = QueryBuilders.boolQuery();
// 1)设置此SKN相关的过滤条件
String gender = (String) productInfo.get("gender");
String gender = productInfoInEs.getString("gender");
if (!StringUtils.isBlank(gender)) {
boolFilter.must(QueryBuilders.termQuery("gender", gender));
}
// 2)找相似要具体到到中分类或小分类,大分类范围太广
BoolQueryBuilder sortFilter = QueryBuilders.boolQuery();
Integer middle_sort_id = (Integer) productInfo.get("middle_sort_id");
Integer small_sort_id = (Integer) productInfo.get("small_sort_id");
Integer middle_sort_id = productInfoInEs.getInteger("middleSortId");
Integer small_sort_id = productInfoInEs.getInteger("smallSortId");
sortFilter.should(QueryBuilders.termQuery("middleSortId", middle_sort_id));
sortFilter.should(QueryBuilders.termQuery("smallSortId", small_sort_id));
boolFilter.must(sortFilter);
... ... @@ -338,12 +359,17 @@ public class SearchLikeServiceImpl implements ISearchLikeService {
boolFilter.mustNot(QueryBuilders.termsQuery("productSkn", notProductSkns.toArray(new String[notProductSkns.size()])));
}
// 4)设置品牌
Integer brandId = (Integer) productInfo.get("brand_id");
Integer brandId = productInfoInEs.getInteger("brandId");
if (isInBrand) {
boolFilter.must(QueryBuilders.termQuery("brandId", brandId));
} else {
boolFilter.mustNot(QueryBuilders.termQuery("brandId", brandId));
}
// 5)设置店铺
if (!isInBrand && paramMap.containsKey(SearchRequestParams.PARAM_SEARCH_SHOP) && StringUtils.isNotBlank(paramMap.get(SearchRequestParams.PARAM_SEARCH_SHOP))) {
int[] shopids = ConvertUtils.stringToIntArray(paramMap.get(SearchRequestParams.PARAM_SEARCH_SHOP), ",");
boolFilter.must(QueryBuilders.termsQuery("shopId", shopids));
}
return boolFilter;
}
... ...