Authored by Gino Zhang

Merge branch '1228' of git.yoho.cn:yoho-search/yoho-search-service into 1228

package com.yoho.search.service.restapi;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.yoho.search.service.downgrade.aop.DownGradeAble;
import com.yoho.search.service.servicenew.IBreakSizeService;
import com.yoho.search.service.utils.HttpServletRequestUtils;
import com.yoho.search.service.vo.SearchApiResult;
import com.yoho.search.service.vo.SizeSortReqBO;
@Controller
public class BreakSizeController {
@Autowired
private IBreakSizeService breakSizeService;
/**
* 【断码区】获取分类,以及分类下的型号列表(with storage_sku)
*
* @return
*/
@DownGradeAble(key = "sort_sizes")
@RequestMapping(method = RequestMethod.GET, value = "/sort_sizes")
@ResponseBody
public SearchApiResult sort_sizes(@ModelAttribute SizeSortReqBO sizeSortReqBO) {
return breakSizeService.sortSizes(sizeSortReqBO);
}
/**
* 【断码区】按分类和型号获取商品(with storage_sku)
*
* @param request
* @return
*/
@DownGradeAble(key = "sort_size_products")
@RequestMapping(method = RequestMethod.GET, value = "/sort_size_products")
@ResponseBody
public SearchApiResult sort_size_products(HttpServletRequest request) {
Map<String, String> paramMap = HttpServletRequestUtils.transParamType(request);
return breakSizeService.sort_size_products(paramMap);
}
}
... ...
package com.yoho.search.service.restapi;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.yoho.search.service.servicenew.IProductListService;
import com.yoho.search.service.utils.HttpServletRequestUtils;
import com.yoho.search.service.vo.SearchApiResult;
@Controller
public class ProductListController {
@Autowired
private IProductListService productListService;
/**
* 获取商品列表
*
* @return
*/
@RequestMapping(method = RequestMethod.GET, value = "/productindex/productList")
@ResponseBody
public SearchApiResult productList(HttpServletRequest request) {
Map<String, String> paramMap = HttpServletRequestUtils.transParamType(request);
return productListService.productList(paramMap);
}
/**
* 打印获取商品列表的ES的dsl的工具接口
*
* @return
*/
@RequestMapping(method = RequestMethod.GET, value = "/dsl/productList")
@ResponseBody
public SearchApiResult getESDsl(HttpServletRequest request) {
Map<String, String> paramMap = HttpServletRequestUtils.transParamType(request);
return productListService.getESDsl(paramMap);
}
}
... ...
package com.yoho.search.service.restapi;
import com.yoho.search.service.downgrade.aop.DownGradeAble;
import com.yoho.search.service.service.SearchSortSizeService;
import com.yoho.search.service.servicenew.*;
import com.yoho.search.service.servicenew.impl.SearchSortGroupService;
import com.yoho.search.service.utils.HttpServletRequestUtils;
import com.yoho.search.service.vo.SearchApiResult;
import com.yoho.search.service.vo.SizeSortReqBO;
import com.yoho.search.service.vo.SuggestApiResult;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
import com.yoho.search.service.downgrade.aop.DownGradeAble;
import com.yoho.search.service.service.SearchSortSizeService;
import com.yoho.search.service.servicenew.IProductIndexService;
import com.yoho.search.service.servicenew.ISearchWithCacheService;
import com.yoho.search.service.servicenew.ISearchWithLocalCacheService;
import com.yoho.search.service.servicenew.ISelectionsWithAdvanceService;
import com.yoho.search.service.servicenew.ISelectionsWithOutAdvanceService;
import com.yoho.search.service.servicenew.impl.SearchSortGroupService;
import com.yoho.search.service.utils.HttpServletRequestUtils;
import com.yoho.search.service.vo.SearchApiResult;
import com.yoho.search.service.vo.SuggestApiResult;
@Controller
public class SearchNewController {
... ... @@ -107,20 +111,6 @@ public class SearchNewController {
}
/**
* 按分类和型号获取商品(with storage_sku)
*
* @param request
* @return
*/
@DownGradeAble(key = "sort_size_products")
@RequestMapping(method = RequestMethod.GET, value = "/sort_size_products")
@ResponseBody
public SearchApiResult sort_size_products(HttpServletRequest request) {
Map<String, String> paramMap = HttpServletRequestUtils.transParamType(request);
return searchWithLocalCacheService.sort_size_products(paramMap);
}
/**
* 批量获取brandIds对应的商品数量和商品列表[我收藏的品牌]
*
* @param request
... ... @@ -227,18 +217,6 @@ public class SearchNewController {
}
/**
* 获取分类,以及分类下的型号列表(with storage_sku)
*
* @return
*/
@DownGradeAble(key = "sort_sizes")
@RequestMapping(method = RequestMethod.GET, value = "/sort_sizes")
@ResponseBody
public SearchApiResult sort_sizes(@ModelAttribute SizeSortReqBO sizeSortReqBO) {
return searchWithCacheService.sortSizes(sizeSortReqBO);
}
/**
* 按品牌前缀名获取品牌列表
*
* @param request
... ... @@ -267,33 +245,6 @@ public class SearchNewController {
}
/**
* 获取商品列表
*
* @return
*/
//@DownGradeAble(key = "productList")
@RequestMapping(method = RequestMethod.GET, value = "/productindex/productList")
@ResponseBody
public SearchApiResult productList(HttpServletRequest request) {
Map<String, String> paramMap = HttpServletRequestUtils.transParamType(request);
return searchWithLocalCacheService.productList(paramMap);
}
/**
* 打印获取商品列表的ES的dsl的工具接口
*
* @return
*/
@RequestMapping(method = RequestMethod.GET, value = "/dsl/productList")
@ResponseBody
public SearchApiResult getESDsl(HttpServletRequest request) {
Map<String, String> paramMap = HttpServletRequestUtils.transParamType(request);
return searchWithLocalCacheService.getESDsl(paramMap);
}
/**
* 聚合品牌
*
... ...
... ... @@ -60,7 +60,8 @@ public class SearchCommonService implements ApplicationEventPublisherAware {
*/
public SearchResult doSearch(final String indexName, final SearchParam searchParam) {
// TODO: need be tested
// SearchResult searchResult = yohoIndexService.search(indexName, searchParam);
// SearchResult searchResult = yohoIndexService.search(indexName,
// searchParam);
IElasticsearchClient client = esClientMgr.getClient(indexName);
SearchResult searchResult = client.search(indexName, indexName, searchParam);
this.publishSearchResultEvent(indexName, searchParam, searchResult);
... ... @@ -68,6 +69,19 @@ public class SearchCommonService implements ApplicationEventPublisherAware {
}
/**
* 根据多个索引查询
* @param indexNames
* @param searchParam
* @return
*/
public SearchResult doSearch(final List<String> indexNames, final SearchParam searchParam) {
IElasticsearchClient client = esClientMgr.getClient(indexNames.get(0));
SearchResult searchResult = client.search(indexNames, indexNames, searchParam);
this.publishSearchResultEvent(indexNames.toString(), searchParam, searchResult);
return searchResult;
}
/**
* 通用的查询接口
*
* @param indexName
... ... @@ -80,7 +94,8 @@ public class SearchCommonService implements ApplicationEventPublisherAware {
}
// TODO: need be tested
// List<SearchResult> results = yohoIndexService.multiSearch(indexName, searchParams);
// List<SearchResult> results = yohoIndexService.multiSearch(indexName,
// searchParams);
IElasticsearchClient client = esClientMgr.getClient(indexName);
List<SearchResult> results = client.multiSearch(indexName, indexName, searchParams);
for (int i = 0; i < searchParams.size(); i++) {
... ... @@ -172,7 +187,8 @@ public class SearchCommonService implements ApplicationEventPublisherAware {
}
// TODO: need be tested
// MultiGetResponse response = yohoIndexService.multiGet(indexName, idSet, fields);
// MultiGetResponse response = yohoIndexService.multiGet(indexName,
// idSet, fields);
IElasticsearchClient client = esClientMgr.getClient(indexName);
String realIndexName = yohoIndexHelper.getRealIndexName(indexName, client);
if (StringUtils.isBlank(realIndexName)) {
... ...
... ... @@ -12,6 +12,7 @@ import java.util.Map;
import javax.annotation.PostConstruct;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
... ... @@ -38,20 +39,6 @@ import com.yoho.search.service.personalized.PersonalizedSearch;
import com.yoho.search.service.personalized.model.SearchFeature;
import com.yoho.search.service.utils.HttpServletRequestUtils;
import com.yoho.search.service.utils.SearchRequestParams;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.sort.FieldSortBuilder;
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 javax.annotation.PostConstruct;
import java.util.*;
@Service
public class SearchServiceHelper {
... ...
package com.yoho.search.service.servicenew;
import java.util.Map;
import com.yoho.search.service.vo.SearchApiResult;
import com.yoho.search.service.vo.SizeSortReqBO;
public interface IBreakSizeService {
/**
* 获取断码区的品类和尺码信息
*
* @param sizeSortReqBO
* @return
*/
public SearchApiResult sortSizes(SizeSortReqBO sizeSortReqBO);
/**
* 获取断码区的商品列表【支持聚合】[使用本地缓存]
*
* @param paramMap
* @return
*/
public SearchApiResult sort_size_products(Map<String, String> paramMap);
}
... ...
package com.yoho.search.service.servicenew;
import java.util.Map;
import com.yoho.search.service.vo.SearchApiResult;
public interface IProductListService {
/**
* 获取商品列表[使用本地缓存]
* @param paramMap
* @return
*/
public SearchApiResult productList(Map<String, String> paramMap);
/**
* 打印获取商品列表的ES语句
* @param paramMap
* @return
*/
public SearchApiResult getESDsl(Map<String, String> paramMap);
}
... ...
package com.yoho.search.service.servicenew;
import java.util.Map;
import com.yoho.search.service.vo.SearchApiResult;
import com.yoho.search.service.vo.SizeSortReqBO;
import com.yoho.search.service.vo.SuggestApiResult;
import java.util.Map;
public interface ISearchWithCacheService {
/**
... ... @@ -41,15 +40,6 @@ public interface ISearchWithCacheService {
public SearchApiResult aggProductsByBrandIdInParam(Map<String, String> paramMap);
/**
* 获取断码区的品类和尺码信息
*
* @param sizeSortReqBO
* @return
*/
public SearchApiResult sortSizes(SizeSortReqBO sizeSortReqBO);
/**
* 获取某个品牌下面的商品【我收藏的品牌】
*
* @param paramMap
... ...
package com.yoho.search.service.servicenew;
import com.yoho.search.service.vo.SearchApiResult;
import java.util.Map;
import com.yoho.search.service.vo.SearchApiResult;
/**
* 使用本地缓存的接口,因为数据量比较大
*
* @author hugufei
*
*/
public interface ISearchWithLocalCacheService {
/**
* 获取商品列表[使用本地缓存]
* @param paramMap
* @return
*/
public SearchApiResult productList(Map<String, String> paramMap);
/**
* 打印获取商品列表的ES语句
* @param paramMap
* @return
*/
public SearchApiResult getESDsl(Map<String, String> paramMap);
/**
* 获取品牌的聚合结果[使用本地缓存]
*
* @param paramMap
* @return
*/
... ... @@ -34,6 +22,7 @@ public interface ISearchWithLocalCacheService {
/**
* 按品牌前缀名获取品牌列表[使用本地缓存]
*
* @param paramMap
* @return
*/
... ... @@ -41,26 +30,18 @@ public interface ISearchWithLocalCacheService {
/**
* 获取商品列表[直接从brand索引里取全部]
*
* @param paramMap
* @return
*/
public SearchApiResult brandList(Map<String, String> paramMap);
/**
* 获取断码区的商品列表【支持聚合】[使用本地缓存]
* @param paramMap
* @return
*/
public SearchApiResult sort_size_products(Map<String, String> paramMap);
/**
* 获取商品池列表
*
* @param paramMap
* @return
*/
public SearchApiResult productPool(Map<String, String> paramMap);
}
... ...
package com.yoho.search.service.servicenew.impl;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yoho.search.service.service.SearchSortSizeService;
import com.yoho.search.service.servicenew.IBreakSizeService;
import com.yoho.search.service.servicenew.IProductIndexService;
import com.yoho.search.service.servicenew.IProductListService;
import com.yoho.search.service.servicenew.ISelectionsWithAdvanceService;
import com.yoho.search.service.utils.SearchApiResultUtils;
import com.yoho.search.service.utils.SearchRequestParams;
import com.yoho.search.service.utils.StringSplitUtils;
import com.yoho.search.service.vo.SearchApiResult;
import com.yoho.search.service.vo.SizeSortReqBO;
@Service
public class BreakSizeServiceImpl implements IBreakSizeService {
private static final Logger logger = LoggerFactory.getLogger(SearchWithLocalCacheServiceImpl.class);
@Autowired
private SearchSortSizeService searchSortSizeService;
@Autowired
private IProductListService productListService;
@Autowired
private IProductIndexService productIndexService;
@Autowired
private ISelectionsWithAdvanceService selectionsWithAdvanceService;
@Override
public SearchApiResult sortSizes(SizeSortReqBO sizeSortReqBO) {
return searchSortSizeService.sortSizes(sizeSortReqBO);
}
@Override
public SearchApiResult sort_size_products(Map<String, String> paramMap) {
try {
logger.info("[func=sort_size_products][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
// 1、先判断参数是否需要聚合【聚合不走storageSku索引】
JSONObject filter = new JSONObject();
if (paramMap.containsKey("needFilter") && "1".equals(paramMap.get("needFilter"))) {
// 1)获取不带全部品牌的聚合结果
paramMap.put("aggStorageSku", "aggStorageSku");
SearchApiResult filterResult = selectionsWithAdvanceService.getSelectionsWithAdvance(paramMap);
JSONObject filterJSONObject = this.getFilterResultFromJSONObject(filterResult);
if (filterJSONObject != null) {
filter = filterJSONObject;
}
// 2)获取品牌的聚合结果
SearchApiResult aggBrandResult = productIndexService.aggBrand(paramMap);
JSONArray aggBrand = this.getAggBrandResultFromJSONObject(aggBrandResult);
if (aggBrand != null && !aggBrand.isEmpty()) {
filter.put("brand", aggBrand);
}
}
// 2、从storageSku索引里根据参数获取skn[已使用本地缓存]
JSONObject productData = new JSONObject();
String[] productSkns = searchSortSizeService.getProductSknFromStorageSkuIndex(paramMap, 200);
if (productSkns == null || productSkns.length == 0) {
productData.put("total", 0);
productData.put("page_total", 0);
productData.put("page", 1);
productData.put("product_list", new JSONArray());
} else {
// 根据skn和其他参数查询结果[已使用本地缓存]
String productSknStr = StringSplitUtils.collectionToString(productSkns, ",");
paramMap.put(SearchRequestParams.PARAM_SYNC_SKN, productSknStr);
SearchApiResult searchApiResult = productListService.productList(paramMap);
productData = getProductResultFromJSONObject(searchApiResult);
}
// 3、拼装真正的结果
JSONObject realData = new JSONObject();
if (filter != null && !filter.isEmpty()) {
realData.put("filter", filter);
}
if (productData != null) {
realData.putAll(productData);
}
return new SearchApiResult().setData(realData);
} catch (Exception e) {
return SearchApiResultUtils.errorSearchApiResult("sort_size_products", paramMap, e);
}
}
private JSONObject getFilterResultFromJSONObject(SearchApiResult aggResult) {
try {
if (aggResult == null) {
return null;
}
JSONObject data = (JSONObject) aggResult.getData();
return data.getJSONObject("filter");
} catch (Exception e) {
logger.error(e.getMessage(), e);
return null;
}
}
private JSONArray getAggBrandResultFromJSONObject(SearchApiResult aggBrandResult) {
try {
if (aggBrandResult == null) {
return null;
}
return (JSONArray) aggBrandResult.getData();
} catch (Exception e) {
logger.error(e.getMessage(), e);
return null;
}
}
private JSONObject getProductResultFromJSONObject(SearchApiResult aggResult) {
try {
if (aggResult == null) {
return null;
}
return (JSONObject) aggResult.getData();
} catch (Exception e) {
logger.error(e.getMessage(), e);
return null;
}
}
}
... ...
package com.yoho.search.service.servicenew.impl;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.search.builder.SearchSourceBuilder;
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.ISearchConstants;
import com.yoho.search.core.es.model.SearchParam;
import com.yoho.search.core.es.model.SearchResult;
import com.yoho.search.core.es.utils.SearchParamUtils;
import com.yoho.search.service.aggregations.impls.AggregationFactoryService;
import com.yoho.search.service.cache.CacheEnum;
import com.yoho.search.service.cache.LocalCacheService;
import com.yoho.search.service.service.AggregationService;
import com.yoho.search.service.service.SearchCacheService;
import com.yoho.search.service.service.SearchCommonService;
import com.yoho.search.service.service.SearchKeyWordService;
import com.yoho.search.service.service.SearchServiceHelper;
import com.yoho.search.service.service.SearchSortSizeService;
import com.yoho.search.service.servicenew.IProductIndexService;
import com.yoho.search.service.servicenew.IProductListService;
import com.yoho.search.service.servicenew.ISelectionsWithAdvanceService;
import com.yoho.search.service.utils.HttpServletRequestUtils;
import com.yoho.search.service.utils.SearchApiResultUtils;
import com.yoho.search.service.vo.SearchApiResult;
@Service
public class ProductListServiceImpl implements IProductListService {
private static final Logger logger = LoggerFactory.getLogger(ProductListServiceImpl.class);
private static Logger CACHE_MATCH_REQUEST = LoggerFactory.getLogger("CACHE_MATCH_REQUEST");
@Autowired
private SearchServiceHelper searchServiceHelper;
@Autowired
private AggregationFactoryService aggregationFactoryService;
@Autowired
private AggregationService aggregationService;
@Autowired
private SearchCommonService searchCommonService;
@Autowired
private SearchAfterCacheService searchAfterCacheService;
@Autowired
private SearchSortSizeService searchSortSizeService;
@Autowired
private IProductIndexService productIndexService;
@Autowired
private LocalCacheService localCacheService;
@Autowired
private ISelectionsWithAdvanceService selectionsWithAdvanceService;
@Autowired
private SearchKeyWordService searchKeyWordService;
@Autowired
private SearchCacheService searchCacheService;
@Override
public SearchApiResult productList(Map<String, String> paramMap) {
try {
logger.info("[func=productList][param={}][begin={}]", paramMap, System.currentTimeMillis());
// 1)构造搜索参数
SearchParam searchParam = buildProductListSearchParam(paramMap);
// 5)从缓存中获取数据
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
CacheEnum cacheEnum = CacheEnum.EHCACHE;
JSONObject cacheObject = searchCacheService.getJSONObjectFromCache(cacheEnum, indexName, searchParam);
if (cacheObject != null) {
CACHE_MATCH_REQUEST.info("match cache , url is :/productindex/productList.json?" + HttpServletRequestUtils.genParamString(paramMap));
return new SearchApiResult().setData(cacheObject);
}
// 6)查询ES
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
if (searchResult == null) {
return new SearchApiResult().setCode(500).setMessage("execption");
}
// 7)记录关键字对应的查询结果
String queryWord = paramMap.get("query");
if (!StringUtils.isBlank(queryWord) && !searchServiceHelper.isQuerySkn(queryWord)) {
searchKeyWordService.recordKeyWordByResultCount(queryWord, searchResult.getTotal());
}
// 8)当返回结果为空时,先记录请求参数,然后修改operator为or并重新搜索,minimum修改为50%
if (StringUtils.isNotBlank(queryWord) && 0 == searchResult.getTotal()) {
searchKeyWordService.handleEmptyRecords(paramMap);
logger.info("search result is empty by operator of AND, will use operator of OR to reenforce search result");
searchParam.setQuery(searchServiceHelper.constructOrQueryBuilder(paramMap));
searchResult = searchCommonService.doSearch(indexName, searchParam);
}
// 9)构造返回结果
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", searchServiceHelper.getProductMapList(searchResult.getResultList()));
// 10)将结果存进缓存
searchCacheService.addJSONObjectToCache(cacheEnum, indexName, searchParam, dataMap);
return new SearchApiResult().setData(dataMap);
} catch (Exception e) {
return SearchApiResultUtils.errorSearchApiResult("productList", paramMap, e);
}
}
@Override
public SearchApiResult getESDsl(Map<String, String> paramMap) {
logger.info("[func=getESDsl][param={}]", paramMap);
try {
SearchParam searchParam = buildProductListSearchParam(paramMap);
SearchSourceBuilder searchSourceBuilder = SearchParamUtils.genSearchSourceBuilderFromSearchParam(searchParam);
SearchApiResult searchApiResult = new SearchApiResult();
searchApiResult.setData(searchSourceBuilder.toString());
logger.info("[func=getESDsl][dsl=\n{}]", searchApiResult.getData());
return searchApiResult;
} catch (Exception e) {
return SearchApiResultUtils.errorSearchApiResult("getESDsl", paramMap, e);
}
}
private void setHighlight(final Map<String, String> paramMap, SearchParam searchParam) {
if (StringUtils.isNotBlank(paramMap.get("highlight")) && "1".equals(paramMap.get("highlight")) && StringUtils.isNotBlank(paramMap.get("query"))) {
searchParam.setHighlight(true);
List<String> highlightFields = new ArrayList<String>();
highlightFields.add("productName.productName_ansj");
searchParam.setHighlightFields(highlightFields);
}
}
private SearchParam buildProductListSearchParam(Map<String, String> paramMap) throws Exception {
// 1)验证查询条数
int pageSize = StringUtils.isBlank(paramMap.get("viewNum")) ? 10 : Integer.parseInt(paramMap.get("viewNum"));
int page = StringUtils.isBlank(paramMap.get("page")) ? 1 : Integer.parseInt(paramMap.get("page"));
if (page < 1 || pageSize < 0) {
throw new IllegalArgumentException("分页参数不合法");
}
if (pageSize > 500) {
pageSize = 500;
}
// 2)构建基本查询参数
paramMap.put("isProductList", "Y");// 加个参数,表明是商品列表
SearchParam searchParam = new SearchParam();
searchParam.setQuery(searchServiceHelper.constructQueryBuilderForProductList(paramMap));
searchParam.setFiter(searchServiceHelper.constructFilterBuilder(paramMap, null));
setHighlight(paramMap, searchParam);
searchParam.setAggregationBuilders(null);
searchParam.setPage(page);
searchParam.setOffset((page - 1) * pageSize);
searchParam.setSize(pageSize);
// 3)设置排序字段
searchParam.setSortBuilders(searchServiceHelper.buildSortList(paramMap));
// 4)设置查询结果返回字段
if (StringUtils.isNotBlank(paramMap.get("resultFields"))) {
String resultFields = paramMap.get("resultFields");
searchParam.setResultFields(Arrays.asList(resultFields.split(",")));
}
return searchParam;
}
}
... ...
package com.yoho.search.service.servicenew.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yoho.error.event.SearchEvent;
import com.yoho.search.base.utils.EventReportEnum;
import com.yoho.search.base.utils.ISearchConstants;
import com.yoho.search.core.es.agg.IAggregation;
import com.yoho.search.core.es.model.SearchParam;
import com.yoho.search.core.es.model.SearchResult;
import com.yoho.search.core.es.utils.IgnoreSomeException;
import com.yoho.search.service.aggregations.AggInterface;
import com.yoho.search.service.aggregations.impls.AggregationFactoryService;
import com.yoho.search.service.service.SearchCacheService;
import com.yoho.search.service.service.SearchCommonService;
import com.yoho.search.service.service.SearchServiceHelper;
import com.yoho.search.service.service.SearchSortSizeService;
import com.yoho.search.service.servicenew.IProductIndexService;
import com.yoho.search.service.servicenew.ISearchWithCacheService;
import com.yoho.search.service.servicenew.ISelectionsWithAdvanceService;
import com.yoho.search.service.servicenew.IShopsService;
import com.yoho.search.service.utils.HttpServletRequestUtils;
import com.yoho.search.service.utils.SearchApiResultUtils;
import com.yoho.search.service.utils.SearchRequestParams;
import com.yoho.search.service.vo.SearchApiResult;
import com.yoho.search.service.vo.SizeSortReqBO;
import com.yoho.search.service.vo.SuggestApiResult;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.*;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
... ... @@ -52,10 +44,30 @@ import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.*;
import java.util.Map.Entry;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yoho.error.event.SearchEvent;
import com.yoho.search.base.utils.EventReportEnum;
import com.yoho.search.base.utils.ISearchConstants;
import com.yoho.search.core.es.agg.IAggregation;
import com.yoho.search.core.es.model.SearchParam;
import com.yoho.search.core.es.model.SearchResult;
import com.yoho.search.core.es.utils.IgnoreSomeException;
import com.yoho.search.service.aggregations.AggInterface;
import com.yoho.search.service.aggregations.impls.AggregationFactoryService;
import com.yoho.search.service.service.SearchCacheService;
import com.yoho.search.service.service.SearchCommonService;
import com.yoho.search.service.service.SearchServiceHelper;
import com.yoho.search.service.service.SearchSortSizeService;
import com.yoho.search.service.servicenew.IProductIndexService;
import com.yoho.search.service.servicenew.ISearchWithCacheService;
import com.yoho.search.service.servicenew.ISelectionsWithAdvanceService;
import com.yoho.search.service.servicenew.IShopsService;
import com.yoho.search.service.utils.HttpServletRequestUtils;
import com.yoho.search.service.utils.SearchApiResultUtils;
import com.yoho.search.service.utils.SearchRequestParams;
import com.yoho.search.service.vo.SearchApiResult;
import com.yoho.search.service.vo.SuggestApiResult;
@Service
public class SearchWithCacheServiceImpl implements ISearchWithCacheService, ApplicationEventPublisherAware {
... ... @@ -447,11 +459,6 @@ public class SearchWithCacheServiceImpl implements ISearchWithCacheService, Appl
}
@Override
public SearchApiResult sortSizes(SizeSortReqBO sizeSortReqBO) {
return searchSortSizeService.sortSizes(sizeSortReqBO);
}
@Override
public SearchApiResult groupBrands(Map<String, String> paramMap) {
try {
logger.info("[func=groupBrands][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
... ...
package com.yoho.search.service.servicenew.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yoho.error.event.SearchEvent;
import com.yoho.search.base.utils.EventReportEnum;
import com.yoho.search.base.utils.ISearchConstants;
import com.yoho.search.core.es.model.SearchParam;
import com.yoho.search.core.es.model.SearchResult;
import com.yoho.search.core.es.utils.IgnoreSomeException;
import com.yoho.search.core.es.utils.SearchParamUtils;
import com.yoho.search.service.aggregations.impls.AggregationFactoryService;
import com.yoho.search.service.cache.CacheEnum;
import com.yoho.search.service.cache.LocalCacheService;
import com.yoho.search.service.service.*;
import com.yoho.search.service.servicenew.IProductIndexService;
import com.yoho.search.service.servicenew.ISearchWithLocalCacheService;
import com.yoho.search.service.servicenew.ISelectionsWithAdvanceService;
import com.yoho.search.service.utils.*;
import com.yoho.search.service.vo.SearchApiResult;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
... ... @@ -26,7 +18,6 @@ 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.Terms;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
... ... @@ -37,10 +28,31 @@ import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.*;
import java.util.concurrent.Callable;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yoho.error.event.SearchEvent;
import com.yoho.search.base.utils.EventReportEnum;
import com.yoho.search.base.utils.ISearchConstants;
import com.yoho.search.core.es.model.SearchParam;
import com.yoho.search.core.es.model.SearchResult;
import com.yoho.search.core.es.utils.IgnoreSomeException;
import com.yoho.search.service.aggregations.impls.AggregationFactoryService;
import com.yoho.search.service.cache.CacheEnum;
import com.yoho.search.service.cache.LocalCacheService;
import com.yoho.search.service.service.AggregationService;
import com.yoho.search.service.service.SearchCacheService;
import com.yoho.search.service.service.SearchCommonService;
import com.yoho.search.service.service.SearchKeyWordService;
import com.yoho.search.service.service.SearchServiceHelper;
import com.yoho.search.service.service.SearchSortSizeService;
import com.yoho.search.service.servicenew.IProductIndexService;
import com.yoho.search.service.servicenew.IProductListService;
import com.yoho.search.service.servicenew.ISearchWithLocalCacheService;
import com.yoho.search.service.servicenew.ISelectionsWithAdvanceService;
import com.yoho.search.service.utils.HttpServletRequestUtils;
import com.yoho.search.service.utils.LocalCacheKeyUtils;
import com.yoho.search.service.utils.SearchApiResultUtils;
import com.yoho.search.service.vo.SearchApiResult;
@Service
public class SearchWithLocalCacheServiceImpl implements ISearchWithLocalCacheService, ApplicationEventPublisherAware {
... ... @@ -71,6 +83,8 @@ public class SearchWithLocalCacheServiceImpl implements ISearchWithLocalCacheSer
private SearchKeyWordService searchKeyWordService;
@Autowired
private SearchCacheService searchCacheService;
@Autowired
private IProductListService productListService;
private ApplicationEventPublisher publisher;
... ... @@ -79,122 +93,6 @@ public class SearchWithLocalCacheServiceImpl implements ISearchWithLocalCacheSer
this.publisher = applicationEventPublisher;
}
private void setHighlight(final Map<String, String> paramMap, SearchParam searchParam) {
if (StringUtils.isNotBlank(paramMap.get("highlight")) && "1".equals(paramMap.get("highlight")) && StringUtils.isNotBlank(paramMap.get("query"))) {
searchParam.setHighlight(true);
List<String> highlightFields = new ArrayList<String>();
highlightFields.add("productName.productName_ansj");
searchParam.setHighlightFields(highlightFields);
}
}
/**
* 打印获取商品列表的ES语句
*
* @param paramMap
* @return
*/
@Override
public SearchApiResult getESDsl(Map<String, String> paramMap) {
logger.info("[func=getESDsl][param={}]", paramMap);
try {
SearchParam searchParam = buildProductListSearchParam(paramMap);
SearchSourceBuilder searchSourceBuilder = SearchParamUtils.genSearchSourceBuilderFromSearchParam(searchParam);
SearchApiResult searchApiResult = new SearchApiResult();
searchApiResult.setData(searchSourceBuilder.toString());
logger.info("[func=getESDsl][dsl=\n{}]", searchApiResult.getData());
return searchApiResult;
} catch (Exception e) {
return SearchApiResultUtils.errorSearchApiResult("getESDsl", paramMap, e);
}
}
private SearchParam buildProductListSearchParam(Map<String, String> paramMap) throws Exception {
// 1)验证查询条数
int pageSize = StringUtils.isBlank(paramMap.get("viewNum")) ? 10 : Integer.parseInt(paramMap.get("viewNum"));
int page = StringUtils.isBlank(paramMap.get("page")) ? 1 : Integer.parseInt(paramMap.get("page"));
if (page < 1 || pageSize < 0) {
throw new IllegalArgumentException("分页参数不合法");
}
if (pageSize > 500) {
pageSize = 500;
}
// 2)构建基本查询参数
paramMap.put("isProductList", "Y");//加个参数,表明是商品列表
SearchParam searchParam = new SearchParam();
searchParam.setQuery(searchServiceHelper.constructQueryBuilderForProductList(paramMap));
searchParam.setFiter(searchServiceHelper.constructFilterBuilder(paramMap, null));
setHighlight(paramMap, searchParam);
searchParam.setAggregationBuilders(null);
searchParam.setPage(page);
searchParam.setOffset((page - 1) * pageSize);
searchParam.setSize(pageSize);
// 3)设置排序字段
// searchParam.setSortFields(searchServiceHelper.buildSort(paramMap));
searchParam.setSortBuilders(searchServiceHelper.buildSortList(paramMap));
// 4)设置查询结果返回字段
if (StringUtils.isNotBlank(paramMap.get("resultFields"))) {
String resultFields = paramMap.get("resultFields");
searchParam.setResultFields(Arrays.asList(resultFields.split(",")));
}
return searchParam;
}
@Override
public SearchApiResult productList(Map<String, String> paramMap) {
try {
logger.info("[func=productList][param={}][begin={}]", paramMap, System.currentTimeMillis());
//1)构造搜索参数
SearchParam searchParam = buildProductListSearchParam(paramMap);
// 5)从缓存中获取数据
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
CacheEnum cacheEnum = CacheEnum.EHCACHE;
JSONObject cacheObject = searchCacheService.getJSONObjectFromCache(cacheEnum, indexName, searchParam);
if (cacheObject != null) {
CACHE_MATCH_REQUEST.info("match cache , url is :/productindex/productList.json?" + HttpServletRequestUtils.genParamString(paramMap));
return new SearchApiResult().setData(cacheObject);
}
// 6)查询ES
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
if (searchResult == null) {
return new SearchApiResult().setCode(500).setMessage("execption");
}
// 7)记录关键字对应的查询结果
String queryWord = paramMap.get("query");
if (!StringUtils.isBlank(queryWord) && !searchServiceHelper.isQuerySkn(queryWord)) {
searchKeyWordService.recordKeyWordByResultCount(queryWord, searchResult.getTotal());
}
// 8)当返回结果为空时,先记录请求参数,然后修改operator为or并重新搜索,minimum修改为50%
if (StringUtils.isNotBlank(queryWord) && 0 == searchResult.getTotal()) {
searchKeyWordService.handleEmptyRecords(paramMap);
logger.info("search result is empty by operator of AND, will use operator of OR to reenforce search result");
searchParam.setQuery(searchServiceHelper.constructOrQueryBuilder(paramMap));
searchResult = searchCommonService.doSearch(indexName, searchParam);
}
// 9)构造返回结果
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", searchServiceHelper.getProductMapList(searchResult.getResultList()));
// 10)将结果存进缓存
searchCacheService.addJSONObjectToCache(cacheEnum, indexName, searchParam, dataMap);
return new SearchApiResult().setData(dataMap);
} catch (Exception e) {
return SearchApiResultUtils.errorSearchApiResult("productList", paramMap, e);
}
}
@Override
public SearchApiResult aggBrand(Map<String, String> paramMap) {
try {
... ... @@ -366,94 +264,6 @@ public class SearchWithLocalCacheServiceImpl implements ISearchWithLocalCacheSer
}
@Override
public SearchApiResult sort_size_products(Map<String, String> paramMap) {
try {
logger.info("[func=sort_size_products][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
// 1、先判断参数是否需要聚合【聚合不走storageSku索引】
JSONObject filter = new JSONObject();
if (paramMap.containsKey("needFilter") && "1".equals(paramMap.get("needFilter"))) {
// 1)获取不带全部品牌的聚合结果
paramMap.put("aggStorageSku", "aggStorageSku");
SearchApiResult filterResult = selectionsWithAdvanceService.getSelectionsWithAdvance(paramMap);
JSONObject filterJSONObject = this.getFilterResultFromJSONObject(filterResult);
if (filterJSONObject != null) {
filter = filterJSONObject;
}
// 2)获取品牌的聚合结果
SearchApiResult aggBrandResult = productIndexService.aggBrand(paramMap);
JSONArray aggBrand = this.getAggBrandResultFromJSONObject(aggBrandResult);
if (aggBrand != null && !aggBrand.isEmpty()) {
filter.put("brand", aggBrand);
}
}
// 2、从storageSku索引里根据参数获取skn[已使用本地缓存]
JSONObject productData = new JSONObject();
String[] productSkns = searchSortSizeService.getProductSknFromStorageSkuIndex(paramMap, 200);
if (productSkns == null || productSkns.length == 0) {
productData.put("total", 0);
productData.put("page_total", 0);
productData.put("page", 1);
productData.put("product_list", new JSONArray());
} else {
// 根据skn和其他参数查询结果[已使用本地缓存]
String productSknStr = StringSplitUtils.collectionToString(productSkns, ",");
paramMap.put(SearchRequestParams.PARAM_SYNC_SKN, productSknStr);
SearchApiResult searchApiResult = this.productList(paramMap);
productData = getProductResultFromJSONObject(searchApiResult);
}
// 3、拼装真正的结果
JSONObject realData = new JSONObject();
if (filter != null && !filter.isEmpty()) {
realData.put("filter", filter);
}
if (productData != null) {
realData.putAll(productData);
}
return new SearchApiResult().setData(realData);
} catch (Exception e) {
return SearchApiResultUtils.errorSearchApiResult("sort_size_products", paramMap, e);
}
}
private JSONObject getFilterResultFromJSONObject(SearchApiResult aggResult) {
try {
if (aggResult == null) {
return null;
}
JSONObject data = (JSONObject) aggResult.getData();
return data.getJSONObject("filter");
} catch (Exception e) {
logger.error(e.getMessage(), e);
return null;
}
}
private JSONArray getAggBrandResultFromJSONObject(SearchApiResult aggBrandResult) {
try {
if (aggBrandResult == null) {
return null;
}
return (JSONArray) aggBrandResult.getData();
} catch (Exception e) {
logger.error(e.getMessage(), e);
return null;
}
}
private JSONObject getProductResultFromJSONObject(SearchApiResult aggResult) {
try {
if (aggResult == null) {
return null;
}
return (JSONObject) aggResult.getData();
} catch (Exception e) {
logger.error(e.getMessage(), e);
return null;
}
}
@Override
public SearchApiResult productPool(Map<String, String> paramMap) {
try {
long begin = System.currentTimeMillis();
... ... @@ -464,7 +274,7 @@ public class SearchWithLocalCacheServiceImpl implements ISearchWithLocalCacheSer
}
// 2)如果有order参数就走老逻辑
if (StringUtils.isNotBlank(paramMap.get("order"))) {
return this.productList(paramMap);
return productListService.productList(paramMap);
}
// 3)检测分页参数
int pageSize = StringUtils.isBlank(paramMap.get("viewNum")) ? 10 : Integer.parseInt(paramMap.get("viewNum"));
... ... @@ -521,7 +331,6 @@ public class SearchWithLocalCacheServiceImpl implements ISearchWithLocalCacheSer
}
}
/**
* 搜索商品池
*
... ... @@ -583,6 +392,4 @@ public class SearchWithLocalCacheServiceImpl implements ISearchWithLocalCacheSer
}
}
}
... ...