Authored by wangnan

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

Showing 24 changed files with 950 additions and 82 deletions
package com.yoho.search.recall.scene.beans.cache;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.yoho.search.base.utils.ISearchConstants;
import com.yoho.search.base.utils.ProductIndexEsField;
import com.yoho.search.core.es.model.SearchParam;
import com.yoho.search.core.es.model.SearchResult;
import com.yoho.search.recall.scene.beans.helper.SknImgHelper;
import com.yoho.search.recall.scene.models.req.*;
import com.yoho.search.service.base.SearchCommonService;
import com.yoho.search.service.base.index.BrandIndexBaseService;
import com.yoho.search.service.base.index.ProductIndexBaseService;
import org.apache.commons.collections.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.*;
import java.util.stream.Collectors;
@Component
public class ShopProductCacheBean extends AbstractCacheBean<ShopProductRequest, ShopProductResponse, ShopProductRequestResponse> {
@Autowired
private SearchCommonService searchCommonService;
@Autowired
private SknImgHelper sknImgHelper;
@Autowired
private ProductIndexBaseService productIndexBaseService;
@Autowired
private BrandIndexBaseService brandIndexBaseService;
public List<ShopProductResponse> getShopSknByShopId(List<ShopProductRequest> shopSknRequests, String hrShopIds) {
List<ShopProductRequestResponse> shopSknRequestResponses = new ArrayList<>();
for (ShopProductRequest request : shopSknRequests) {
shopSknRequestResponses.add(new ShopProductRequestResponse(request));
}
//2、执行父类方法
this.bacthFillResponseWithCache(shopSknRequestResponses, shopSknRequestResponses.size());
List<ShopProductResponse> shopProductResponses = shopSknRequestResponses.stream().map(ShopProductRequestResponse::getResponse).filter(Objects::nonNull).collect(Collectors.toList());
for (ShopProductResponse response : shopProductResponses) {
response.setHr_shop_id(hrShopIds);
}
//3、返回结果
return shopProductResponses;
}
@Override
protected boolean useEhCache() {
return false;
}
@Override
protected Map<ShopProductRequest, ShopProductResponse> queryMissCacheRequestResults(List<ShopProductRequestResponse> missCacheRequests) {
Map<ShopProductRequest, ShopProductResponse> results = new HashMap<>();
if (missCacheRequests == null || missCacheRequests.isEmpty()) {
return results;
}
List<SearchParam> searchParams = new ArrayList<>();
for (ShopProductRequestResponse requestResponse : missCacheRequests) {
searchParams.add(requestResponse.getRequest().searchParam());
}
//2、执行搜索
List<SearchResult> searchResults = searchCommonService.doMutiSearch(ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParams);
Set<Integer> brandIds = new HashSet<>();
for (SearchResult searchResult : searchResults) {
List<Map<String, Object>> resultList = searchResult.getResultList();
brandIds.addAll(resultList.stream().map(result -> MapUtils.getInteger(result, ProductIndexEsField.brandId, 0)).collect(Collectors.toSet()));
}
Map<String, Map<String, Object>> brandMap = new HashMap<>();
if (!CollectionUtils.isEmpty(brandIds)) {
brandMap = brandIndexBaseService.getBrandMapByIds(brandIds);
}
//获得变价计划
Map<String, List<Map<String, Object>>> shopProductListMap = new HashMap<>();
for (int i = 0; i < missCacheRequests.size(); i++) {
ShopProductRequest request = missCacheRequests.get(i).getRequest();
SearchResult searchResult = searchResults.get(i);
if (request != null && searchResult != null) {
shopProductListMap.put(request.getShopId().toString(), searchResult.getResultList());
}
}
shopProductListMap = productIndexBaseService.getProductListWithPricePlan(shopProductListMap);
for (int i = 0; i < missCacheRequests.size(); i++) {
ShopProductRequest request = missCacheRequests.get(i).getRequest();
List<Map<String, Object>> productList = shopProductListMap.get(request.getShopId().toString());
ShopProductResponse response = buildResponse(productList, brandMap, request);
results.put(request, response);
}
return results;
}
private ShopProductResponse buildResponse(List<Map<String, Object>> productList, Map<String, Map<String, Object>> brandMap, ShopProductRequest request) {
ShopProductResponse response = new ShopProductResponse();
List<ShopProductResponse.ShopProduct> shopProductList = new ArrayList<>();
response.setShop_id(request.getShopId());
response.setShop_product_list(shopProductList);
if (!CollectionUtils.isEmpty(productList)) {
Map<String, Object> product = productList.get(0);
response.setShop_name(MapUtils.getString(product, "shop_name", ""));
//1、构建结果
for (Map<String, Object> productInfo : productList) {
ShopProductResponse.ShopProduct shopProduct = new ShopProductResponse.ShopProduct();
shopProduct.setProduct_skn(MapUtils.getInteger(productInfo, "product_skn", 0));
shopProduct.setProduct_name(MapUtils.getString(productInfo, "product_name", ""));
shopProduct.setGender(MapUtils.getString(productInfo, "gender", "1,3"));
shopProduct.setSales_price(MapUtils.getDouble(productInfo, "sales_price", 0.0));
shopProduct.setDefault_images(MapUtils.getString(productInfo, "default_images", ""));
String brandId = MapUtils.getString(productInfo, "brand_id", "");
Map<String, Object> brand = brandMap.get(brandId);
if (brand != null) {
shopProduct.setBrand_name(MapUtils.getString(brand, "brand_name", ""));
shopProduct.setBrand_ico(MapUtils.getString(brand, "brand_ico", ""));
}
shopProduct.setProduct_price_plan_list(MapUtils.getObject(productInfo, "product_price_plan_list", Collections.emptyList()));
List<JSONObject> goodsList = JSON.parseObject(JSON.toJSONString(productInfo.get("goods_list")), new TypeReference<List<JSONObject>>() {});
sknImgHelper.genImage(goodsList, shopProduct);
shopProductList.add(shopProduct);
}
}
return response;
}
}
... ...
package com.yoho.search.recall.scene.beans.cache;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.yoho.search.base.utils.ISearchConstants;
import com.yoho.search.base.utils.ProductIndexEsField;
import com.yoho.search.core.es.model.SearchParam;
import com.yoho.search.core.es.model.SearchResult;
import com.yoho.search.recall.scene.beans.helper.SknImgHelper;
import com.yoho.search.recall.scene.models.req.SknImgsRequestResponse;
import com.yoho.search.recall.scene.models.req.SknImgsResponse;
import com.yoho.search.recall.scene.models.req.SknImgsResquest;
import com.yoho.search.service.base.SearchCommonService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.*;
@Component
public class SknImgsCacheBean extends AbstractCacheBean<SknImgsResquest, SknImgsResponse, SknImgsRequestResponse> {
@Autowired
private SearchCommonService searchCommonService;
@Autowired
private SknImgHelper sknImgHelper;
@Override
protected boolean useEhCache() {
return false;
}
public Map<String, SknImgsResponse> querySknImgs(List<String> productSkns) {
//1、构建请求与返回结果
final List<SknImgsRequestResponse> requestResponses = new ArrayList<>();
for (String productSkn : productSkns) {
requestResponses.add(new SknImgsRequestResponse(new SknImgsResquest(Integer.valueOf(productSkn))));
}
//2、调父类方法
this.bacthFillResponseWithCache(requestResponses, productSkns.size());
//2、构造返回结果
Map<String, SknImgsResponse> finalResults = new HashMap<>();
for (SknImgsRequestResponse sknImgsRequestResponse : requestResponses) {
if (sknImgsRequestResponse != null && sknImgsRequestResponse.getResponse() != null) {
finalResults.put(sknImgsRequestResponse.getRequest().getProductSkn().toString(), sknImgsRequestResponse.getResponse());
}
}
return finalResults;
}
@Override
protected Map<SknImgsResquest, SknImgsResponse> queryMissCacheRequestResults(List<SknImgsRequestResponse> missCacheRequests) {
//1、合法性判断
Map<SknImgsResquest, SknImgsResponse> results = new HashMap<>();
if (missCacheRequests == null || missCacheRequests.isEmpty()) {
return results;
}
//2、获取skn
List<Integer> productSkns = new ArrayList<>();
for (SknImgsRequestResponse sknDefaultImgRequestResponse : missCacheRequests) {
productSkns.add(sknDefaultImgRequestResponse.getRequest().getProductSkn());
}
//3、构建SearchParam
SearchParam searchParam = new SearchParam();
searchParam.setSize(productSkns.size());
searchParam.setFiter(QueryBuilders.termsQuery(ProductIndexEsField.productSkn, productSkns));
searchParam.setIncludeFields(missCacheRequests.get(0).getRequest().includeFields());
SearchResult searchResult = searchCommonService.doSearch(ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
if (searchResult != null && CollectionUtils.isNotEmpty(searchResult.getResultList())) {
Map<String, SknImgsResponse> defaultImgTempMap = new HashMap<>();
for (Map<String, Object> product : searchResult.getResultList()) {
SknImgsResponse response = new SknImgsResponse();
response.setDefault_images(MapUtils.getString(product, ProductIndexEsField.defaultImages, ""));
response.setSkn_default_img(MapUtils.getString(product, ProductIndexEsField.sknDefaultImg, ""));
response.setGender(MapUtils.getString(product, ProductIndexEsField.gender, ""));
List<JSONObject> goodsList = JSON.parseObject(JSON.toJSONString(product.get(ProductIndexEsField.goodsList)), new TypeReference<List<JSONObject>>() {});
sknImgHelper.genImage(goodsList, response);
defaultImgTempMap.put(MapUtils.getString(product,ProductIndexEsField.productSkn,""), response);
}
for (SknImgsRequestResponse requestResponse : missCacheRequests) {
results.put(requestResponse.getRequest(), defaultImgTempMap.get(requestResponse.getRequest().getProductSkn().toString()));
}
}
return results;
}
}
... ...
package com.yoho.search.recall.scene.beans.helper;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.lang.reflect.Method;
import java.util.List;
@Component
public class SknImgHelper<Response> {
public void genImage(List<JSONObject> goodsList, Response response) {
if(CollectionUtils.isEmpty(goodsList)){
return;
}
JSONObject firstGood = null;
for (JSONObject good : goodsList) {
if ("Y".equals(good.getString("is_default")) && StringUtils.isNotEmpty(good.getString("images_url"))) {
genImage(good, response);
return;
}
// 有可能,goodlist中的所有good都没有cover1或者cover2,最终就采用第一个good
if(null == firstGood && StringUtils.isNotEmpty(good.getString("images_url"))){
firstGood = good;
}
}
if (firstGood != null) {
genImage(firstGood, response);
}
}
private void genImage(JSONObject good, Response response) {
String images_url = good.getString("images_url");
String conver_1 = good.getString("cover_1");
String conver_2 = good.getString("cover_2");
try {
Method[] methods = response.getClass().getDeclaredMethods();
// 循环查找想要的方法
for(Method method : methods) {
if("setCover_1".equals(method.getName())) {
method.invoke(response, (StringUtils.isEmpty(conver_1) ? images_url : conver_1));
}
if("setCover_2".equals(method.getName())) {
method.invoke(response, (StringUtils.isEmpty(conver_2) ? images_url : conver_2));
}
}
} catch (Exception e) {
}
}
}
... ...
... ... @@ -30,4 +30,8 @@ public class CacheTimeConstants {
//页面个性化因子的缓存
public static final int PAGE_PERSIONAL_FACTOR = 60 ;
public static final int CACHE_60_MINUTE = 60 ;
public static final int CACHE_10_MINUTE = 10 ;
}
... ...
package com.yoho.search.recall.scene.models.req;
import com.yoho.core.redis.cluster.operations.serializer.RedisKeyBuilder;
import com.yoho.search.base.utils.MD5Util;
import com.yoho.search.base.utils.ProductIndexEsField;
import com.yoho.search.core.es.model.SearchParam;
import com.yoho.search.recall.scene.constants.CacheTimeConstants;
import com.yoho.search.recall.scene.models.common.ICacheRequest;
import com.yoho.search.recall.scene.models.common.ParamQueryFilter;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import java.util.Arrays;
import java.util.List;
public class ShopProductRequest implements ICacheRequest {
private static final List<String> includeFields = Arrays.asList(ProductIndexEsField.productSkn, ProductIndexEsField.productName, ProductIndexEsField.shopId, ProductIndexEsField.shopName, ProductIndexEsField.defaultImages, ProductIndexEsField.goodsList, ProductIndexEsField.salesPrice,ProductIndexEsField.gender, ProductIndexEsField.brandId);
private ParamQueryFilter paramQueryFilter;
private Integer shopId;
private RedisKeyBuilder redisKeyBuilder;
public ShopProductRequest(ParamQueryFilter paramQueryFilter, Integer shopId) {
this.paramQueryFilter = paramQueryFilter;
this.shopId = shopId;
this.redisKeyBuilder = genRedisKeyBuilder();
}
public RedisKeyBuilder genRedisKeyBuilder() {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(paramQueryFilter == null ? "" : paramQueryFilter.getParamMd5Key());
stringBuilder.append(shopId);
String value = MD5Util.string2MD5(stringBuilder.toString());
return RedisKeyBuilder.newInstance().appendFixed("YOHOSEARCH:").appendFixed("SHOP_SKN:").appendVar(cacheTimeInMinute()).appendFixed(":").appendVar(value);
}
@Override
public RedisKeyBuilder redisKeyBuilder() {
return redisKeyBuilder;
}
@Override
public int cacheTimeInMinute() {
return CacheTimeConstants.CACHE_10_MINUTE;
}
public ParamQueryFilter getParamQueryFilter() {
return paramQueryFilter;
}
public Integer getShopId() {
return shopId;
}
public void setShopId(Integer shopId) {
this.shopId = shopId;
}
public SearchParam searchParam() {
SearchParam searchParam = new SearchParam();
if (paramQueryFilter != null && paramQueryFilter.getParamQuery() != null) {
searchParam.setQuery(paramQueryFilter.getParamQuery());
}
BoolQueryBuilder realFilter = QueryBuilders.boolQuery();
realFilter.must(QueryBuilders.termQuery(ProductIndexEsField.shopId, shopId));
if (paramQueryFilter != null && paramQueryFilter.getParamFilter() != null) {
realFilter.must(paramQueryFilter.getParamFilter());
}
searchParam.setFiter(realFilter);
searchParam.setIncludeFields(includeFields);
searchParam.setSortBuilders(Arrays.asList(SortBuilders.fieldSort(ProductIndexEsField.heatValue).order(SortOrder.DESC), SortBuilders.fieldSort(ProductIndexEsField.shelveTime).order(SortOrder.DESC)));
searchParam.setOffset(0);
searchParam.setSize(10);
return searchParam;
}
}
... ...
package com.yoho.search.recall.scene.models.req;
import com.alibaba.fastjson.JSON;
import com.yoho.search.base.utils.Transfer;
import com.yoho.search.recall.scene.models.common.AbstractCacheRequestResponse;
public class ShopProductRequestResponse extends AbstractCacheRequestResponse<ShopProductRequest, ShopProductResponse> {
public ShopProductRequestResponse(ShopProductRequest request) {
super(request);
}
@Override
public Transfer<String, ShopProductResponse> getToResponseTransfer() {
return (v) -> JSON.parseObject(v, ShopProductResponse.class);
}
@Override
public Transfer<ShopProductResponse, String> getFromResponseTransfer() {
return (v) -> JSON.toJSONString(v);
}
}
... ...
package com.yoho.search.recall.scene.models.req;
import java.util.List;
public class ShopProductResponse {
private String hr_shop_id;
private Integer shop_id;
private String shop_name;
private List<ShopProduct> shop_product_list;
public static class ShopProduct {
private Integer product_skn;
private String product_name;
private String gender;
private String default_images;
private String cover_1;
private String cover_2;
private Double sales_price;
private Object product_price_plan_list;
private String brand_name;
private String brand_ico;
public Integer getProduct_skn() {
return product_skn;
}
public void setProduct_skn(Integer product_skn) {
this.product_skn = product_skn;
}
public String getProduct_name() {
return product_name;
}
public void setProduct_name(String product_name) {
this.product_name = product_name;
}
public Double getSales_price() {
return sales_price;
}
public void setSales_price(Double sales_price) {
this.sales_price = sales_price;
}
public String getDefault_images() {
return default_images;
}
public void setDefault_images(String default_images) {
this.default_images = default_images;
}
public String getCover_1() {
return cover_1;
}
public void setCover_1(String cover_1) {
this.cover_1 = cover_1;
}
public String getCover_2() {
return cover_2;
}
public void setCover_2(String cover_2) {
this.cover_2 = cover_2;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public Object getProduct_price_plan_list() {
return product_price_plan_list;
}
public void setProduct_price_plan_list(Object product_price_plan_list) {
this.product_price_plan_list = product_price_plan_list;
}
public String getBrand_name() {
return brand_name;
}
public void setBrand_name(String brand_name) {
this.brand_name = brand_name;
}
public String getBrand_ico() {
return brand_ico;
}
public void setBrand_ico(String brand_ico) {
this.brand_ico = brand_ico;
}
}
public Integer getShop_id() {
return shop_id;
}
public void setShop_id(Integer shop_id) {
this.shop_id = shop_id;
}
public String getShop_name() {
return shop_name;
}
public void setShop_name(String shop_name) {
this.shop_name = shop_name;
}
public String getHr_shop_id() {
return hr_shop_id;
}
public void setHr_shop_id(String hr_shop_id) {
this.hr_shop_id = hr_shop_id;
}
public List<ShopProduct> getShop_product_list() {
return shop_product_list;
}
public void setShop_product_list(List<ShopProduct> shop_product_list) {
this.shop_product_list = shop_product_list;
}
}
... ...
package com.yoho.search.recall.scene.models.req;
import com.alibaba.fastjson.JSON;
import com.yoho.search.base.utils.Transfer;
import com.yoho.search.recall.scene.models.common.AbstractCacheRequestResponse;
public class SknImgsRequestResponse extends AbstractCacheRequestResponse<SknImgsResquest, SknImgsResponse> {
public SknImgsRequestResponse(SknImgsResquest request) {
super(request);
}
@Override
public Transfer<String, SknImgsResponse> getToResponseTransfer() {
return (v) -> JSON.parseObject(v, SknImgsResponse.class);
}
@Override
public Transfer<SknImgsResponse, String> getFromResponseTransfer() {
return (v) -> JSON.toJSONString(v);
}
}
... ...
package com.yoho.search.recall.scene.models.req;
public class SknImgsResponse {
private String default_images;
private String skn_default_img;
private String cover_1;
private String cover_2;
private String gender;
public String getDefault_images() {
return default_images;
}
public void setDefault_images(String default_images) {
this.default_images = default_images;
}
public String getSkn_default_img() {
return skn_default_img;
}
public void setSkn_default_img(String skn_default_img) {
this.skn_default_img = skn_default_img;
}
public String getCover_1() {
return cover_1;
}
public void setCover_1(String cover_1) {
this.cover_1 = cover_1;
}
public String getCover_2() {
return cover_2;
}
public void setCover_2(String cover_2) {
this.cover_2 = cover_2;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
}
... ...
package com.yoho.search.recall.scene.models.req;
import com.yoho.core.redis.cluster.operations.serializer.RedisKeyBuilder;
import com.yoho.search.base.utils.ProductIndexEsField;
import com.yoho.search.recall.scene.constants.CacheTimeConstants;
import com.yoho.search.recall.scene.models.common.ICacheRequest;
import java.util.Arrays;
import java.util.List;
public class SknImgsResquest implements ICacheRequest {
private static final List<String> includeFields = Arrays.asList(ProductIndexEsField.productSkn,ProductIndexEsField.defaultImages, ProductIndexEsField.sknDefaultImg, ProductIndexEsField.goodsList,ProductIndexEsField.gender);
private Integer productSkn;
public SknImgsResquest(Integer productSkn){
this.productSkn = productSkn;
}
@Override
public RedisKeyBuilder redisKeyBuilder() {
return RedisKeyBuilder.newInstance().appendFixed("YOHOSEARCH:").appendFixed("SKN_DEFAULT_IMG:").appendVar(cacheTimeInMinute()).appendFixed(":").appendVar(productSkn);
}
@Override
public int cacheTimeInMinute() {
return CacheTimeConstants.CACHE_60_MINUTE;
}
public Integer getProductSkn() {
return productSkn;
}
public List<String> includeFields(){
return includeFields;
}
}
... ...
package com.yoho.search.restapi.others;
import com.yoho.search.common.utils.HttpServletRequestUtils;
import com.yoho.search.models.SearchApiResult;
import com.yoho.search.service.base.SearchRequestParams;
import com.yoho.search.service.service.impl.SearchHongRenService;
import com.yoho.search.service.service.impl.SearchSortGroupService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
@RestController
@RequestMapping("/hr")
public class HrDistributionController {
@Autowired
private SearchSortGroupService searchSortGroupService;
@Autowired
private SearchHongRenService searchHongRenService;
/**
* 对分类进行分组查询
* @param request
* @return
*/
@RequestMapping(method = RequestMethod.GET, value = "/sortgroup")
public SearchApiResult sortGroup(HttpServletRequest request) {
Map<String, String> paramMap = HttpServletRequestUtils.transParamType(request);
if (!checkRequestParam(paramMap)) {
return new SearchApiResult().setCode(400).setMessage("入参缺少hrShopId参数");
}
return searchSortGroupService.sortGroup(paramMap);
}
@RequestMapping(method = RequestMethod.GET, value = "/shopList")
public SearchApiResult getShopList(HttpServletRequest request) {
Map<String, String> paramMap = HttpServletRequestUtils.transParamType(request);
if (!checkRequestParam(paramMap)) {
return new SearchApiResult().setCode(400).setMessage("入参缺少hrShopId参数");
}
return searchHongRenService.shopList(paramMap);
}
@RequestMapping(method = RequestMethod.GET, value = "/productList")
public SearchApiResult productList(HttpServletRequest request) {
Map<String, String> paramMap = HttpServletRequestUtils.transParamType(request);
if (!checkRequestParam(paramMap)) {
return new SearchApiResult().setCode(400).setMessage("入参缺少hrShopId参数");
}
SearchApiResult searchApiResult = searchHongRenService.productList(paramMap);
return searchApiResult;
}
@RequestMapping(method = RequestMethod.GET, value = "/productListForFuzzy")
public SearchApiResult fuzzyProductList(HttpServletRequest request) {
Map<String, String> paramMap = HttpServletRequestUtils.transParamType(request);
if (!checkRequestParam(paramMap)) {
return new SearchApiResult().setCode(400).setMessage("入参缺少hrShopId参数");
}
SearchApiResult searchApiResult = searchHongRenService.productListForFuzzy(paramMap);
return searchApiResult;
}
private boolean checkRequestParam(Map<String, String> paramMap) {
return paramMap.containsKey(SearchRequestParams.PRODUCTINDEX_HRSHOPID);
}
}
... ...
... ... @@ -52,4 +52,11 @@ public class CommonSecneController {
Map<String, String> paramMap = HttpServletRequestUtils.transParamType(request);
return commonSceneService.aggregations(paramMap);
}
@RequestMapping(method = RequestMethod.GET, value = "/common/sknImgs")
@ResponseBody
public SearchApiResult sknImgs(HttpServletRequest request) {
Map<String, String> paramMap = HttpServletRequestUtils.transParamType(request);
return commonSceneService.sknImgs(paramMap);
}
}
... ...
... ... @@ -141,4 +141,8 @@ public class AggregationFactoryService {
public IAggregation getCustomizeTagAggregation(Map<String, String> paramMap) {
return new CustomizeTagAggregation(customizeTagBaseService, paramMap);
}
public IAggregation getShopAndSknAggregation(int aggCount) {
return new ShopAndSknAggregation(aggCount);
}
}
... ...
package com.yoho.search.service.aggregations.impls;
import com.yoho.search.base.utils.ProductIndexEsField;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.search.aggregations.Aggregation;
import org.springframework.util.CollectionUtils;
import java.util.*;
import java.util.stream.Collectors;
public class ShopAndSknAggregation extends AbstractSingleFieldAggregation{
public ShopAndSknAggregation(int count) {
super(count);
}
@Override
public String aggName() {
return "shopAndSknAgg";
}
@Override
public String filterName() {
return "shop";
}
protected String getField() {
return ProductIndexEsField.shopId;
}
@Override
public Object getAggregationResponseMap(Map<String, Aggregation> aggMaps) {
List<String> shopIdList = (List<String>) super.getAggregationResponseMap(aggMaps);
List<Integer> shopIdResult = new ArrayList<>();
if (!CollectionUtils.isEmpty(shopIdList)) {
shopIdResult = shopIdList.stream().filter(StringUtils::isNotBlank).map(Integer::valueOf).filter(shopId -> shopId > 0).collect(Collectors.toList());
}
return shopIdResult;
}
}
... ...
... ... @@ -53,7 +53,7 @@ public class SearchCommonService implements ApplicationEventPublisherAware {
}
QueryBuilder filter = searchParam.getFiter();
String filterString = (filter == null ? "" : filter.toString());
if (!filterString.contains(ProductIndexEsField.poolId)) {
if (!filterString.contains(ProductIndexEsField.poolIds)) {
return;
}
publisher.publishEvent(new SearchEvent(indexName, EventReportEnum.SEARCHCOMMONSERVICE_DOSEARCH.getFunctionName(), EventReportEnum.SEARCHCOMMONSERVICE_DOSEARCH
... ...
... ... @@ -129,4 +129,6 @@ public class SearchRequestParams {
public static final String PROMOTIONINDEX_ISDEL = "isDel";
public static final String PROMOTIONINDEX_COMMONBANNER= "commonBanner";
public static final String PRODUCTINDEX_HRSHOPID= "hrShopId";
}
... ...
... ... @@ -279,7 +279,7 @@ public class ProductIndexBaseService {
*/
public List<Map<String, Object>> getProductListWithPricePlan(List<Map<String, Object>> productEsSourceList) {
if (productEsSourceList == null || productEsSourceList.isEmpty()) {
return new ArrayList<Map<String, Object>>();
return new ArrayList<>();
}
// 获取搜索结果的skn,根据它们来获取product_price_plan
String[] sknStr = new String[productEsSourceList.size()];
... ...
... ... @@ -377,22 +377,6 @@ public class SearchCommonHelper {
}
/**
* 构造商品池相关的过滤条件
*
* @param paramMap
* @return
*/
public BoolQueryBuilder getPoolIdTermsBuilder(Map<String, String> paramMap) {
// 增加商品池相关的过滤条件
if (paramMap.containsKey("filter_poolId") && StringUtils.isNotBlank("filter_poolId")) {
BoolQueryBuilder nestedBoolFilter = QueryBuilders.boolQuery();
nestedBoolFilter.must(QueryBuilders.termQuery("pools.pool_id", paramMap.get("filter_poolId")));
return nestedBoolFilter;
}
return null;
}
/**
* 自定义标签过滤
*
* @param paramMap
... ...
... ... @@ -469,7 +469,7 @@ public class SearchServiceHelper {
// 处理filter_poolId
if (this.checkParamNotFiltered(paramMap, filterParamName, SearchRequestParams.PARAM_SEARCH_FILTER_POOLID)) {
boolFilter.must(QueryBuilders.termsQuery(ProductIndexEsField.poolId, paramMap.get(SearchRequestParams.PARAM_SEARCH_FILTER_POOLID).split(",")));
boolFilter.must(QueryBuilders.termsQuery(ProductIndexEsField.poolIds, paramMap.get(SearchRequestParams.PARAM_SEARCH_FILTER_POOLID).split(",")));
}
// 处理not_productSkn
... ... @@ -524,6 +524,11 @@ public class SearchServiceHelper {
}
}
}
//hrShopIds
if (this.checkParamNotFiltered(paramMap, filterParamName, SearchRequestParams.PRODUCTINDEX_HRSHOPID)) {
int[] hrShopIds = ConvertUtils.stringToIntArray(paramMap.get(SearchRequestParams.PRODUCTINDEX_HRSHOPID), ",");
boolFilter.must(QueryBuilders.termsQuery(ProductIndexEsField.hrShopIds, hrShopIds));
}
if (boolFilter.hasClauses()) {
return boolFilter;
... ...
... ... @@ -239,14 +239,6 @@ public class SearchSortHelper {
activitySort.setNestedFilter(activitiesTermsBuilder);
}
sortBuilders.add(activitySort);
} else if (fieldName.contains("pools")) {
BoolQueryBuilder poolsTermsBuilder = searchCommonHelper.getPoolIdTermsBuilder(paramMap);
String flag = sortOrder.toString().equals("desc") ? "_last" : "_first";
FieldSortBuilder poolsFieldSortBuilder = SortBuilders.fieldSort(fieldName).order(sortOrder).setNestedPath("pools").missing(flag);
if (poolsFieldSortBuilder != null) {
poolsFieldSortBuilder.setNestedFilter(poolsTermsBuilder);
}
sortBuilders.add(poolsFieldSortBuilder);
} else {
this.addSortBuildSorts(sortBuilders, filteredFieldNames, fieldName, sortOrder);
}
... ...
... ... @@ -12,10 +12,12 @@ import com.yoho.search.service.base.ProductListSortService;
import com.yoho.search.service.base.SearchCommonService;
import com.yoho.search.service.base.SearchRequestParams;
import com.yoho.search.service.base.index.ProductIndexBaseService;
import com.yoho.search.service.helper.ProductListHelper;
import com.yoho.search.service.helper.SearchCommonHelper;
import com.yoho.search.service.helper.SearchParamHelper;
import com.yoho.search.service.helper.SearchSortHelper;
import com.yoho.search.service.scene.common.AbstractCacheAbleService;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
... ... @@ -27,20 +29,15 @@ import java.util.Map;
@Service
public class FuzzySceneProductListService extends AbstractCacheAbleService {
private static final Logger logger = LoggerFactory.getLogger(ProductListSwitchService.class);
@Autowired
private SearchCommonService searchCommonService;
@Autowired
private ProductIndexBaseService productIndexBaseService;
@Autowired
private SearchParamHelper searchParamHelper;
@Autowired
private SearchSortHelper searchSortHelper;
@Autowired
private ProductListSortService productListSortService;
@Autowired
private SearchCommonHelper searchCommonHelper;
@Autowired
private ProductListHelper productListHelper;
@Override
public SearchCache getSearchCache() {
... ... @@ -48,7 +45,7 @@ public class FuzzySceneProductListService extends AbstractCacheAbleService {
}
/**
* 获取商品列表
* 模糊搜索获取商品列表
*
* @param paramMap
* @return
... ... @@ -56,13 +53,13 @@ public class FuzzySceneProductListService extends AbstractCacheAbleService {
*/
public SearchApiResult productList(Map<String, String> paramMap) {
try {
// 0)定义页面为模糊搜索的页面
// 1)定义页面为模糊搜索的页面
paramMap.put(SearchRequestParams.PARAM_SEARCH_PAGEID, SearchPageIdDefine.PAGE_ID_SEARCH);
// 1)构造搜索参数
SearchParam searchParam = this.buildProductListSearchParam(paramMap);
// 2)构造搜索参数
SearchParam searchParam = productListHelper.buildProductListSearchParam(paramMap, true);
// 2)从缓存中获取数据
// 3)从缓存中获取数据
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
JSONObject cacheObject = searchCacheService.getJSONObjectFromCache(this.searchCache, indexName, searchParam);
if (cacheObject != null) {
... ... @@ -70,56 +67,23 @@ public class FuzzySceneProductListService extends AbstractCacheAbleService {
return new SearchApiResult().setData(cacheObject);
}
// 3)查询ES
// 4)查询ES
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
if (searchResult == null) {
return new SearchApiResult().setCode(500).setMessage("execption");
}
// 4)构造返回结果
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());
List<Map<String, Object>> product_list = productIndexBaseService.getProductListWithPricePlan(searchResult.getResultList());
if(searchCommonHelper.isOrderEmpty(paramMap)){
product_list = productListSortService.sortProductList(product_list);// 处理一下商品的顺序;
}
//加入到手价字段
product_list = productIndexBaseService.getProductListWithPriceInHand(product_list);
dataMap.put("product_list",product_list);
// 5)构造返回结果
boolean needResort = searchCommonHelper.isOrderEmpty(paramMap) ? true : false;
JSONObject productListResult = productListHelper.buildProductListResult(searchResult, searchParam.getSize(), needResort);
// 5)将结果存进缓存
searchCacheService.addJSONObjectToCache(this.searchCache, indexName, searchParam, dataMap);
return new SearchApiResult().setData(dataMap);
// 6)将结果存进缓存
searchCacheService.addJSONObjectToCache(this.searchCache, indexName, searchParam, productListResult);
return new SearchApiResult().setData(productListResult);
} catch (Exception e) {
logger.error(e.getMessage(), e);
return new SearchApiResult().setCode(500).setMessage("scene productList exception").setData(new JSONObject());
}
}
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 > 100) {
pageSize = 100;
}
// 2)构建基本查询参数
SearchParam searchParam = searchParamHelper.buildWithPersional(paramMap, true);
searchParam.setAggregationBuilders(null);
searchParam.setOffset((page - 1) * pageSize);
searchParam.setSize(pageSize);
// 3)设置排序字段
searchParam.setSortBuilders(searchSortHelper.buildSortList(paramMap));
// 4)设置返回的参数【节省带宽】
List<String> includeFields = productIndexBaseService.getProductIndexIncludeFields();
searchParam.setIncludeFields(includeFields);
return searchParam;
}
}
... ...
package com.yoho.search.service.scene;
import com.google.common.base.Splitter;
import com.yoho.search.base.utils.SearchPageIdDefine;
import com.yoho.search.common.utils.SearchApiResultUtils;
import com.yoho.search.models.SearchApiResult;
import com.yoho.search.recall.scene.beans.cache.SknImgsCacheBean;
import com.yoho.search.recall.scene.models.req.SknImgsResponse;
import com.yoho.search.service.base.SearchRequestParams;
import com.yoho.search.service.list.ProductListSwitchService;
import com.yoho.search.service.scene.common.AbstractSceneService;
import com.yoho.search.service.scene.common.SceneRecommendBrandsService;
import com.yoho.search.service.scene.common.SceneSelectionsService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.Map;
@Service
... ... @@ -25,6 +31,8 @@ public class CommonSceneService extends AbstractSceneService {
private SceneSelectionsService sceneSelectionsService;
@Autowired
private SceneRecommendBrandsService sceneRecommendBrandsService;
@Autowired
private SknImgsCacheBean sknImgsCacheBean;
@Override
public String pageId() {
... ... @@ -63,4 +71,14 @@ public class CommonSceneService extends AbstractSceneService {
return SearchApiResultUtils.errorSearchApiResult("CommonAggregations", paramMap, e);
}
}
public SearchApiResult sknImgs(Map<String, String> paramMap) {
SearchApiResult searchApiResult = new SearchApiResult().setCode(200).setMessage("skn defalut image List.").setData(Collections.EMPTY_MAP);
String productSkn = paramMap.get(SearchRequestParams.PARAM_SEARCH_PRODUCT_SKN);
if (StringUtils.isNotEmpty(productSkn) && productSkn.split(",").length > 0) {
Map<String, SknImgsResponse> result = sknImgsCacheBean.querySknImgs(Splitter.on(",").trimResults().splitToList(productSkn));
searchApiResult.setData(result);
}
return searchApiResult;
}
}
... ...
package com.yoho.search.service.service;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.yoho.error.event.SearchEvent;
import com.yoho.search.base.utils.EventReportEnum;
import com.yoho.search.base.utils.ISearchConstants;
... ... @@ -9,11 +11,18 @@ 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.recall.scene.beans.cache.ShopProductCacheBean;
import com.yoho.search.recall.scene.models.common.ParamQueryFilter;
import com.yoho.search.recall.scene.models.req.ShopProductRequest;
import com.yoho.search.recall.scene.models.req.ShopProductResponse;
import com.yoho.search.service.aggregations.impls.AggregationFactoryService;
import com.yoho.search.service.base.SearchCommonService;
import com.yoho.search.service.base.SearchRequestParams;
import com.yoho.search.service.helper.SearchCommonHelper;
import com.yoho.search.service.helper.SearchParamHelper;
import com.yoho.search.service.scene.common.AbstractCacheAbleService;
import org.apache.commons.collections.CollectionUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.aggregations.Aggregation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
... ... @@ -22,8 +31,8 @@ import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
@Service
public class AggregationService extends AbstractCacheAbleService implements ApplicationEventPublisherAware {
... ... @@ -36,6 +45,10 @@ public class AggregationService extends AbstractCacheAbleService implements Appl
private SearchCommonService searchCommonService;
@Autowired
private SearchParamHelper searchParamHelper;
@Autowired
private ShopProductCacheBean shopSknCacheBean;
@Autowired
private SearchCommonHelper searchCommonHelper;
@Override
public SearchCache getSearchCache() {
... ... @@ -252,4 +265,46 @@ public class AggregationService extends AbstractCacheAbleService implements Appl
return this.getAggNameAndResponseWithCache(standardAggregation, searchParam);
}
/**
* 获取店铺聚合结果。
*/
public JSONObject getShopAndSknAggregationResult(Map<String, String> paramMap, int page, int pageSize, int aggCount) throws Exception {
IAggregation shopAndSknAggregation = aggregationFactoryService.getShopAndSknAggregation(aggCount);
SearchParam searchParam = this.genSearchParamForAgg(shopAndSknAggregation, paramMap, null, 0);
JSONObject aggResult = getAggNameAndResponseWithCache(shopAndSknAggregation, searchParam);
JSONObject dataMap = new JSONObject();
if (aggResult != null) {
List<Integer> shopIds = JSON.parseObject(aggResult.getJSONArray("shopAndSknAgg").toJSONString(), new TypeReference<List<Integer>>() {});
if (CollectionUtils.isNotEmpty(shopIds)) {
dataMap.put("page", page);
dataMap.put("page_size", pageSize);
dataMap.put("total", shopIds.size());
dataMap.put("page_total", searchCommonHelper.getTotalPage(shopIds.size(), pageSize));
dataMap.put("shop_product_list", Collections.emptyList());
List<Integer> subShopIds = subList(shopIds, pageSize, page);
if (CollectionUtils.isNotEmpty(subShopIds)) {
List<ShopProductRequest> shopProductRequests = subShopIds.stream().map(shopId -> {
return new ShopProductRequest(new ParamQueryFilter(searchParam.getQuery(), (BoolQueryBuilder)searchParam.getFiter()), shopId);
}).collect(Collectors.toList());
String hrShopIds = paramMap.get(SearchRequestParams.PRODUCTINDEX_HRSHOPID);
List<ShopProductResponse> responseList = shopSknCacheBean.getShopSknByShopId(shopProductRequests, hrShopIds);
dataMap.put("shop_product_list", responseList);
}
}
}
return dataMap;
}
private List<Integer> subList(List<Integer> sourceList, int pageSize, int page) {
int fromIndex = pageSize * (page - 1);
if (fromIndex >= sourceList.size()) {
return null;
}
int toIndex = pageSize * page;
if (toIndex > sourceList.size()) {
toIndex = sourceList.size();
}
return sourceList.subList(fromIndex, toIndex);
}
}
... ...
package com.yoho.search.service.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.yoho.search.common.utils.SearchApiResultUtils;
import com.yoho.search.models.SearchApiResult;
import com.yoho.search.service.base.SearchCacheService;
import com.yoho.search.service.base.SearchRequestParams;
import com.yoho.search.service.helper.SearchCommonHelper;
import com.yoho.search.service.helper.SearchKeyWordHelper;
import com.yoho.search.service.list.FuzzySceneProductListService;
import com.yoho.search.service.list.ProductListSwitchService;
import com.yoho.search.service.scene.common.AbstractSceneService;
import com.yoho.search.service.service.AggregationService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Map;
@Service
public class SearchHongRenService extends AbstractSceneService {
@Autowired
protected SearchCacheService searchCacheService;
@Autowired
private AggregationService aggregationService;
@Autowired
private ProductListSwitchService productListSwitchService;
@Autowired
private FuzzySceneProductListService fuzzySceneProductListService;
@Autowired
private SearchCommonHelper searchCommonHelper;
@Autowired
private SearchKeyWordHelper searchKeyWordService;
public SearchApiResult shopList(Map<String, String> paramMap) {
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 || page * pageSize > 1000000) {
return new SearchApiResult().setCode(400).setMessage("分页参数不合法");
}
if (pageSize > 100) {
paramMap.put("viewNum", "100");
pageSize = 100;
}
SearchApiResult searchApiResult = new SearchApiResult().setCode(200).setMessage("Shop product List .");
try {
JSONObject dataMap = aggregationService.getShopAndSknAggregationResult(paramMap, page, pageSize, 10000);
searchApiResult.setData(dataMap);
} catch (Exception e) {
return new SearchApiResult().setData(null).setMessage("ShopProductList Exception").setCode(500);
}
return searchApiResult;
}
public SearchApiResult productList(Map<String, String> paramMap) {
try {
// 1、添加默认参数
addParamsToParamMap(paramMap);
return productListSwitchService.productList(newParamMap(paramMap));
} catch (Exception e) {
return new SearchApiResult().setData(null).setMessage("hrSortProductList Exception").setCode(500);
}
}
public SearchApiResult productListForFuzzy(Map<String, String> paramMap) {
try {
// 1、参数校验
if (StringUtils.isBlank(paramMap.get(SearchRequestParams.PARAM_SEARCH_QUERY))) {
return new SearchApiResult().setCode(400).setMessage("请传query参数");
}
// 2、添加默认参数
this.addParamsToParamMap(paramMap);
// 3、获取商品列表
SearchApiResult productListResult = fuzzySceneProductListService.productList(this.newParamMap(paramMap));
// 7、模糊搜索页记录关键字对应的查询结果
String queryWord = paramMap.get("query");
if (!StringUtils.isBlank(queryWord) && !searchCommonHelper.isQuerySknOrSku(queryWord)) {
long total = ((JSONObject) productListResult.getData()).getLongValue("total");
searchKeyWordService.recordKeyWordByResultCount(queryWord, total);
}
return productListResult;
} catch (Exception e) {
return SearchApiResultUtils.errorSearchApiResult("hrfuzzyProductList", paramMap, e);
}
}
@Override
public void addParamsToParamMap(Map<String, String> paramMap) {
super.addDefaultParamsToParamMap(paramMap);
}
@Override
public String pageId() {
return null;
}
@Override
public SearchApiResult aggregations(Map<String, String> paramMap) {
return null;
}
}
... ...