Authored by hugufei

拆包

Showing 31 changed files with 2170 additions and 2198 deletions

Too many changes to show.

To preserve performance only 31 of 31+ files are displayed.

... ... @@ -14,7 +14,7 @@ import com.yoho.search.common.utils.HttpServletRequestUtils;
import com.yoho.search.models.SearchApiResult;
import com.yoho.search.service.service.BrandService;
import com.yoho.search.service.service.ProductCountService;
import com.yoho.search.service.service.ProductIndexService;
import com.yoho.search.service.aggregations.ProductIndexService;
import com.yoho.search.service.service.SelectionsForApp;
import com.yoho.search.service.service.SelectionsForPc;
... ...
... ... @@ -13,7 +13,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
import com.yoho.search.aop.downgrade.PersionalRateLimit;
import com.yoho.search.common.utils.HttpServletRequestUtils;
import com.yoho.search.models.SearchApiResult;
import com.yoho.search.service.service.AggRecommendService;
import com.yoho.search.service.aggregations.AggRecommendService;
@Controller
public class RecommendController {
... ...
... ... @@ -13,11 +13,11 @@ import org.springframework.web.bind.annotation.ResponseBody;
import com.yoho.search.aop.downgrade.PersionalRateLimit;
import com.yoho.search.common.utils.HttpServletRequestUtils;
import com.yoho.search.models.SearchApiResult;
import com.yoho.search.service.service.DiscountService;
import com.yoho.search.service.aggregations.service.DiscountService;
import com.yoho.search.service.service.ProductCountService;
import com.yoho.search.service.service.RecentService;
import com.yoho.search.service.aggregations.service.RecentService;
import com.yoho.search.service.service.SearchProductsServiceNew;
import com.yoho.search.service.service.SearchSortGroupService;
import com.yoho.search.service.aggregations.service.SearchSortGroupService;
@Controller
public class SearchNewController {
... ...
... ... @@ -13,8 +13,8 @@ import org.springframework.web.bind.annotation.ResponseBody;
import com.yoho.search.common.utils.HttpServletRequestUtils;
import com.yoho.search.models.SearchApiResult;
import com.yoho.search.models.SuggestApiResult;
import com.yoho.search.service.service.SearchRecommendService;
import com.yoho.search.service.service.SuggestService;
import com.yoho.search.service.scene.fuzzy.SearchRecommendService;
import com.yoho.search.service.scene.fuzzy.SuggestService;
@Controller
public class SuggestController {
... ...
... ... @@ -4,7 +4,7 @@ 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.SearchHongRenService;
import com.yoho.search.service.service.SearchSortGroupService;
import com.yoho.search.service.aggregations.service.SearchSortGroupService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
... ...
... ... @@ -13,7 +13,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
import com.yoho.search.aop.downgrade.PersionalRateLimit;
import com.yoho.search.common.utils.HttpServletRequestUtils;
import com.yoho.search.models.SearchApiResult;
import com.yoho.search.service.scene.AggProductListService;
import com.yoho.search.service.aggregations.AggProductListService;
/**
* 活动千人千面场景
... ...
... ... @@ -13,7 +13,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
import com.yoho.search.aop.downgrade.PersionalRateLimit;
import com.yoho.search.common.utils.HttpServletRequestUtils;
import com.yoho.search.models.SearchApiResult;
import com.yoho.search.service.scene.FuzzySceneService;
import com.yoho.search.service.scene.fuzzy.FuzzySceneService;
/**
* 模糊搜索接口
... ...
... ... @@ -17,8 +17,8 @@ import com.yoho.search.common.utils.HttpServletRequestUtils;
import com.yoho.search.models.SearchApiResult;
import com.yoho.search.service.scene.searchlike.SearchLikeInShopService;
import com.yoho.search.service.scene.searchlike.SearchLikeSceneService;
import com.yoho.search.service.service.ProductListWithSupplyService;
import com.yoho.search.service.service.SimilarProductService;
import com.yoho.search.service.scene.searchlike.ProductListWithSupplyService;
import com.yoho.search.service.scene.searchlike.SimilarProductService;
/**
* 找相似相关功能
... ...
... ... @@ -4,7 +4,7 @@ import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import com.yoho.search.service.service.WebNewShelveService;
import com.yoho.search.service.scene.web.WebNewShelveService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
... ... @@ -14,7 +14,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
import com.yoho.search.aop.downgrade.PersionalRateLimit;
import com.yoho.search.common.utils.HttpServletRequestUtils;
import com.yoho.search.models.SearchApiResult;
import com.yoho.search.service.scene.WebProductListService;
import com.yoho.search.service.scene.web.WebProductListService;
@Controller
public class WebProductListController {
... ...
package com.yoho.search.service.helper;
import java.util.*;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.MultiBucketsAggregation;
import org.elasticsearch.search.aggregations.bucket.MultiBucketsAggregation.Bucket;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.tophits.TopHits;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.yoho.search.base.utils.CollectionUtils;
import com.yoho.search.service.aggregations.common.FieldSortOrder;
import com.yoho.search.service.aggregations.common.KeyTopHitModel;
import com.yoho.search.service.aggregations.common.SimpleFieldAgg;
public class AggCommonHelper {
private static final Logger logger = LoggerFactory.getLogger(AggCommonHelper.class);
/**
* 从TopHits中获取_source
*
* @param topHits
* @return
*/
public static List<Map<String, Object>> getTopHitResultsWithScore(TopHits topHits) {
List<Map<String, Object>> topHitList = new ArrayList<>();
if (topHits == null) {
return topHitList;
}
SearchHits hits = topHits.getHits();
for (SearchHit hit : hits.getHits()) {
Map<String, Object> source = hit.getSource();
float _score = hit.getScore();
source.put("_score", _score);
topHitList.add(source);
}
return topHitList;
}
public static List<Integer> getIdsFromAggMaps(Map<String, Aggregation> aggMaps, String aggName) {
if (!aggMaps.containsKey(aggName)) {
return new ArrayList<>();
}
MultiBucketsAggregation aggregation = (MultiBucketsAggregation) aggMaps.get(aggName);
List<Integer> results = new ArrayList<Integer>();
Iterator<? extends MultiBucketsAggregation.Bucket> iterator = aggregation.getBuckets().iterator();
while (iterator.hasNext()) {
MultiBucketsAggregation.Bucket bucket = iterator.next();
if (StringUtils.isNumeric(bucket.getKeyAsString())) {
results.add(Integer.valueOf(bucket.getKeyAsString()));
}
}
return results;
}
/**
* 获取tophit的聚合结果
*
* @param simpleFieldAggs
* @param topHitOrder
* @param topHitCount
* @return
*/
public static AbstractAggregationBuilder<?> getTopHitAggregation(List<SimpleFieldAgg> simpleFieldAggs, String topHitOrder, int topHitCount) {
int length = simpleFieldAggs.size();
FieldSortOrder fieldSortOrder = new FieldSortOrder(topHitOrder);
SortBuilder<?> sortBuilder = null;
if (fieldSortOrder.isScoreOrder()) {
sortBuilder = SortBuilders.scoreSort();
} else {
sortBuilder = SortBuilders.fieldSort(fieldSortOrder.getSortField()).order(fieldSortOrder.getSortOrder());
}
AbstractAggregationBuilder<?> result = null;
for (int i = length - 1; i >= 0; i--) {
SimpleFieldAgg simpleFieldAgg = simpleFieldAggs.get(i);
TermsAggregationBuilder temp = AggregationBuilders.terms(simpleFieldAgg.getAggName()).field(simpleFieldAgg.getEsField()).size(simpleFieldAgg.getBucketCount());
// 如果是最小层面的聚合,则加上tophit的聚合
if (result == null) {
if (topHitCount > 0) {
temp.subAggregation(AggregationBuilders.max("sort").field(fieldSortOrder.getSortField()));
temp.subAggregation(AggregationBuilders.topHits("topHit").sort(sortBuilder).size(topHitCount));
}
result = temp;
} else {
result = temp.subAggregation(result);
}
}
return result;
}
/**
* 获取聚合出来的商品列表,并按特定顺序截取
*/
public static List<Map<String, Object>> getTopHitList(Map<String, Aggregation> aggMaps, List<SimpleFieldAgg> simpleFieldAggs, String topHitOrder, int totalCount) {
List<Map<String, Object>> results = new ArrayList<Map<String, Object>>();
getTopHitResults(results, aggMaps, simpleFieldAggs, 0);
results = sortListBySortField(results, topHitOrder, totalCount);
return results;
}
private static void getTopHitResults(List<Map<String, Object>> results, Map<String, Aggregation> aggMaps, List<SimpleFieldAgg> simpleFieldAggs, int index) {
try {
String aggName = simpleFieldAggs.get(index++).getAggName();
if (!aggMaps.containsKey(aggName)) {
return;
}
List<? extends Bucket> bucketList = ((MultiBucketsAggregation) aggMaps.get(aggName)).getBuckets();
if (bucketList.isEmpty()) {
return;
}
for (Bucket bucket : bucketList) {
Map<String, Aggregation> aggMap = bucket.getAggregations().getAsMap();
if (aggMap.containsKey("topHit")) {
TopHits topHits = bucket.getAggregations().get("topHit");
List<Map<String, Object>> topHitList = getTopHitResultsWithScore(topHits);
results.addAll(topHitList);
} else {
getTopHitResults(results, aggMap, simpleFieldAggs, index);
}
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
}
private static List<Map<String, Object>> sortListBySortField(List<Map<String, Object>> productList, String topHitOrder, int viewNum) {
if (productList == null || productList.isEmpty()) {
return new ArrayList<>();
}
// 再按照某个字段对商品排序
FieldSortOrder fieldSortOrder = new FieldSortOrder(topHitOrder);
Collections.sort(productList, new Comparator<Map<String, Object>>() {
public int compare(Map<String, Object> o1, Map<String, Object> o2) {
try {
double value1 = getDouble(o1.get(fieldSortOrder.getSortField()));
double value2 = getDouble(o2.get(fieldSortOrder.getSortField()));
if (fieldSortOrder.isDesc()) {
return value1 > value2 ? -1 : value1 < value2 ? 1 : 0;
} else {
return value1 > value2 ? 1 : value1 < value2 ? -1 : 0;
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
return -1;
}
}
});
if (productList.size() > viewNum) {
productList = CollectionUtils.safeSubList(productList, 0, viewNum);
}
return productList;
}
private static double getDouble(Object value) {
try {
if (value == null) {
return 0;
}
return Double.parseDouble(value.toString());
} catch (Exception e) {
return 0;
}
}
/**
* 按聚合的key获取聚合出来的商品列表[目前只支持一个field,多重field的话,key不好处理]
*
* @return
*/
public static List<KeyTopHitModel> getTopHitListGroupByKey(Map<String, Aggregation> aggMaps, SimpleFieldAgg simpleFieldAgg) {
String aggName = simpleFieldAgg.getAggName();
if (!aggMaps.containsKey(aggName)) {
return new ArrayList<>();
}
List<? extends Bucket> bucketList = ((MultiBucketsAggregation) aggMaps.get(aggName)).getBuckets();
if (bucketList.isEmpty()) {
return new ArrayList<>();
}
List<KeyTopHitModel> results = new ArrayList<KeyTopHitModel>();
for (Bucket bucket : bucketList) {
String key = bucket.getKeyAsString();
long count = bucket.getDocCount();
List<Map<String, Object>> topHitList = new ArrayList<>();
Map<String, Aggregation> aggMap = bucket.getAggregations().getAsMap();
if (aggMap.containsKey("topHit")) {
TopHits topHits = bucket.getAggregations().get("topHit");
List<Map<String, Object>> tempTopHitList = getTopHitResultsWithScore(topHits);
topHitList.addAll(tempTopHitList);
}
KeyTopHitModel keyTopHitModel = new KeyTopHitModel(key, count, topHitList);
results.add(keyTopHitModel);
}
return results;
}
/**
* 从聚合结果中获取参数,仅支持二层聚合
*
* @param aggregationMap
* @param firstAggName
* @param secondAggName
* @return
*/
public static List<AggKeyCountTwoLevel> getAggKeyCountTwoLevelList(Map<String, Aggregation> aggregationMap, String firstAggName, String secondAggName) {
List<AggKeyCountTwoLevel> result = new ArrayList<>();
if (!aggregationMap.containsKey(firstAggName)) {
return result;
}
MultiBucketsAggregation firstAggregation = (MultiBucketsAggregation) aggregationMap.get(firstAggName);
Iterator<? extends MultiBucketsAggregation.Bucket> firstAggregationIterator = firstAggregation.getBuckets().iterator();
while (firstAggregationIterator.hasNext()) {
MultiBucketsAggregation.Bucket firstAggregationBucket = firstAggregationIterator.next();
Map<String, Aggregation> secondAggregationMap = firstAggregationBucket.getAggregations().asMap();
if (secondAggregationMap == null || !secondAggregationMap.containsKey(secondAggName)) {
continue;
}
AggKeyCount firstKeyCount = genAggKeyCount(firstAggregationBucket);
List<AggKeyCount> secondKeyCountList = genAggKeyCountList((MultiBucketsAggregation) secondAggregationMap.get(secondAggName));
result.add(new AggKeyCountTwoLevel(firstKeyCount,secondKeyCountList));
}
return result;
}
private static List<AggKeyCount> genAggKeyCountList(MultiBucketsAggregation aggregation) {
List<AggKeyCount> results = new ArrayList<>();
if (aggregation == null) {
return results;
}
Iterator<? extends MultiBucketsAggregation.Bucket> bucketsIterator = aggregation.getBuckets().iterator();
while (bucketsIterator.hasNext()) {
MultiBucketsAggregation.Bucket bucket = bucketsIterator.next();
results.add(genAggKeyCount(bucket));
}
return results;
}
private static AggKeyCount genAggKeyCount(MultiBucketsAggregation.Bucket bucket){
Integer value = Integer.valueOf(bucket.getKeyAsString());
long count = bucket.getDocCount();
return new AggKeyCount(value,count);
}
}
package com.yoho.search.service.aggregations;
import java.util.*;
import com.yoho.search.service.aggregations.models.*;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.MultiBucketsAggregation;
import org.elasticsearch.search.aggregations.bucket.MultiBucketsAggregation.Bucket;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.tophits.TopHits;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.yoho.search.base.utils.CollectionUtils;
public class AggCommonHelper {
private static final Logger logger = LoggerFactory.getLogger(AggCommonHelper.class);
/**
* 从TopHits中获取_source
*
* @param topHits
* @return
*/
public static List<Map<String, Object>> getTopHitResultsWithScore(TopHits topHits) {
List<Map<String, Object>> topHitList = new ArrayList<>();
if (topHits == null) {
return topHitList;
}
SearchHits hits = topHits.getHits();
for (SearchHit hit : hits.getHits()) {
Map<String, Object> source = hit.getSource();
float _score = hit.getScore();
source.put("_score", _score);
topHitList.add(source);
}
return topHitList;
}
public static List<Integer> getIdsFromAggMaps(Map<String, Aggregation> aggMaps, String aggName) {
if (!aggMaps.containsKey(aggName)) {
return new ArrayList<>();
}
MultiBucketsAggregation aggregation = (MultiBucketsAggregation) aggMaps.get(aggName);
List<Integer> results = new ArrayList<Integer>();
Iterator<? extends MultiBucketsAggregation.Bucket> iterator = aggregation.getBuckets().iterator();
while (iterator.hasNext()) {
MultiBucketsAggregation.Bucket bucket = iterator.next();
if (StringUtils.isNumeric(bucket.getKeyAsString())) {
results.add(Integer.valueOf(bucket.getKeyAsString()));
}
}
return results;
}
/**
* 获取tophit的聚合结果
*
* @param simpleFieldAggs
* @param topHitOrder
* @param topHitCount
* @return
*/
public static AbstractAggregationBuilder<?> getTopHitAggregation(List<SimpleFieldAgg> simpleFieldAggs, String topHitOrder, int topHitCount) {
int length = simpleFieldAggs.size();
FieldSortOrder fieldSortOrder = new FieldSortOrder(topHitOrder);
SortBuilder<?> sortBuilder = null;
if (fieldSortOrder.isScoreOrder()) {
sortBuilder = SortBuilders.scoreSort();
} else {
sortBuilder = SortBuilders.fieldSort(fieldSortOrder.getSortField()).order(fieldSortOrder.getSortOrder());
}
AbstractAggregationBuilder<?> result = null;
for (int i = length - 1; i >= 0; i--) {
SimpleFieldAgg simpleFieldAgg = simpleFieldAggs.get(i);
TermsAggregationBuilder temp = AggregationBuilders.terms(simpleFieldAgg.getAggName()).field(simpleFieldAgg.getEsField()).size(simpleFieldAgg.getBucketCount());
// 如果是最小层面的聚合,则加上tophit的聚合
if (result == null) {
if (topHitCount > 0) {
temp.subAggregation(AggregationBuilders.max("sort").field(fieldSortOrder.getSortField()));
temp.subAggregation(AggregationBuilders.topHits("topHit").sort(sortBuilder).size(topHitCount));
}
result = temp;
} else {
result = temp.subAggregation(result);
}
}
return result;
}
/**
* 获取聚合出来的商品列表,并按特定顺序截取
*/
public static List<Map<String, Object>> getTopHitList(Map<String, Aggregation> aggMaps, List<SimpleFieldAgg> simpleFieldAggs, String topHitOrder, int totalCount) {
List<Map<String, Object>> results = new ArrayList<Map<String, Object>>();
getTopHitResults(results, aggMaps, simpleFieldAggs, 0);
results = sortListBySortField(results, topHitOrder, totalCount);
return results;
}
private static void getTopHitResults(List<Map<String, Object>> results, Map<String, Aggregation> aggMaps, List<SimpleFieldAgg> simpleFieldAggs, int index) {
try {
String aggName = simpleFieldAggs.get(index++).getAggName();
if (!aggMaps.containsKey(aggName)) {
return;
}
List<? extends Bucket> bucketList = ((MultiBucketsAggregation) aggMaps.get(aggName)).getBuckets();
if (bucketList.isEmpty()) {
return;
}
for (Bucket bucket : bucketList) {
Map<String, Aggregation> aggMap = bucket.getAggregations().getAsMap();
if (aggMap.containsKey("topHit")) {
TopHits topHits = bucket.getAggregations().get("topHit");
List<Map<String, Object>> topHitList = getTopHitResultsWithScore(topHits);
results.addAll(topHitList);
} else {
getTopHitResults(results, aggMap, simpleFieldAggs, index);
}
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
}
private static List<Map<String, Object>> sortListBySortField(List<Map<String, Object>> productList, String topHitOrder, int viewNum) {
if (productList == null || productList.isEmpty()) {
return new ArrayList<>();
}
// 再按照某个字段对商品排序
FieldSortOrder fieldSortOrder = new FieldSortOrder(topHitOrder);
Collections.sort(productList, new Comparator<Map<String, Object>>() {
public int compare(Map<String, Object> o1, Map<String, Object> o2) {
try {
double value1 = getDouble(o1.get(fieldSortOrder.getSortField()));
double value2 = getDouble(o2.get(fieldSortOrder.getSortField()));
if (fieldSortOrder.isDesc()) {
return value1 > value2 ? -1 : value1 < value2 ? 1 : 0;
} else {
return value1 > value2 ? 1 : value1 < value2 ? -1 : 0;
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
return -1;
}
}
});
if (productList.size() > viewNum) {
productList = CollectionUtils.safeSubList(productList, 0, viewNum);
}
return productList;
}
private static double getDouble(Object value) {
try {
if (value == null) {
return 0;
}
return Double.parseDouble(value.toString());
} catch (Exception e) {
return 0;
}
}
/**
* 按聚合的key获取聚合出来的商品列表[目前只支持一个field,多重field的话,key不好处理]
*
* @return
*/
public static List<KeyTopHitModel> getTopHitListGroupByKey(Map<String, Aggregation> aggMaps, SimpleFieldAgg simpleFieldAgg) {
String aggName = simpleFieldAgg.getAggName();
if (!aggMaps.containsKey(aggName)) {
return new ArrayList<>();
}
List<? extends Bucket> bucketList = ((MultiBucketsAggregation) aggMaps.get(aggName)).getBuckets();
if (bucketList.isEmpty()) {
return new ArrayList<>();
}
List<KeyTopHitModel> results = new ArrayList<KeyTopHitModel>();
for (Bucket bucket : bucketList) {
String key = bucket.getKeyAsString();
long count = bucket.getDocCount();
List<Map<String, Object>> topHitList = new ArrayList<>();
Map<String, Aggregation> aggMap = bucket.getAggregations().getAsMap();
if (aggMap.containsKey("topHit")) {
TopHits topHits = bucket.getAggregations().get("topHit");
List<Map<String, Object>> tempTopHitList = getTopHitResultsWithScore(topHits);
topHitList.addAll(tempTopHitList);
}
KeyTopHitModel keyTopHitModel = new KeyTopHitModel(key, count, topHitList);
results.add(keyTopHitModel);
}
return results;
}
/**
* 从聚合结果中获取参数,仅支持二层聚合
*
* @param aggregationMap
* @param firstAggName
* @param secondAggName
* @return
*/
public static List<AggKeyCountTwoLevel> getAggKeyCountTwoLevelList(Map<String, Aggregation> aggregationMap, String firstAggName, String secondAggName) {
List<AggKeyCountTwoLevel> result = new ArrayList<>();
if (!aggregationMap.containsKey(firstAggName)) {
return result;
}
MultiBucketsAggregation firstAggregation = (MultiBucketsAggregation) aggregationMap.get(firstAggName);
Iterator<? extends MultiBucketsAggregation.Bucket> firstAggregationIterator = firstAggregation.getBuckets().iterator();
while (firstAggregationIterator.hasNext()) {
MultiBucketsAggregation.Bucket firstAggregationBucket = firstAggregationIterator.next();
Map<String, Aggregation> secondAggregationMap = firstAggregationBucket.getAggregations().asMap();
if (secondAggregationMap == null || !secondAggregationMap.containsKey(secondAggName)) {
continue;
}
AggKeyCount firstKeyCount = genAggKeyCount(firstAggregationBucket);
List<AggKeyCount> secondKeyCountList = genAggKeyCountList((MultiBucketsAggregation) secondAggregationMap.get(secondAggName));
result.add(new AggKeyCountTwoLevel(firstKeyCount,secondKeyCountList));
}
return result;
}
private static List<AggKeyCount> genAggKeyCountList(MultiBucketsAggregation aggregation) {
List<AggKeyCount> results = new ArrayList<>();
if (aggregation == null) {
return results;
}
Iterator<? extends MultiBucketsAggregation.Bucket> bucketsIterator = aggregation.getBuckets().iterator();
while (bucketsIterator.hasNext()) {
MultiBucketsAggregation.Bucket bucket = bucketsIterator.next();
results.add(genAggKeyCount(bucket));
}
return results;
}
private static AggKeyCount genAggKeyCount(MultiBucketsAggregation.Bucket bucket){
Integer value = Integer.valueOf(bucket.getKeyAsString());
long count = bucket.getDocCount();
return new AggKeyCount(value,count);
}
}
... ...
package com.yoho.search.service.aggregations;
/**
* Created by xy on 2016/7/1.
*/
public class AggInterface {
public static final int AGE_LEVEL =1;
public static final int DISCOUNT =2;
public static final int GENDER = 3;
public static final int PRICE= 4;
public static final int COLOR= 5;
public static final int STYLE=6;
public static final int BRAND=7;
public static final int SIZE=8;
public static final int STANDARD=9;
public static final int RECENT_SHELVE_DAY =10;
public static final int IS_NEW = 11;
public static final int IS_LIMITED =12;
public static final int IS_SPECIAL =13;
}
package com.yoho.search.service.scene;
import com.alibaba.fastjson.JSONObject;
import com.yoho.error.event.SearchEvent;
import com.yoho.search.base.utils.CollectionUtils;
import com.yoho.search.base.utils.EventReportEnum;
import com.yoho.search.base.utils.ISearchConstants;
import com.yoho.search.base.utils.ProductIndexEsField;
import com.yoho.search.aop.cache.SearchCacheAble;
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.models.SearchApiResult;
import com.yoho.search.models.SearchSort;
import com.yoho.search.service.base.SearchCommonService;
import com.yoho.search.service.helper.*;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.MultiBucketsAggregation;
import org.elasticsearch.search.aggregations.bucket.MultiBucketsAggregation.Bucket;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.tophits.TopHits;
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.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.*;
@Service
public class AggProductListService implements ApplicationEventPublisherAware {
private static final Logger logger = LoggerFactory.getLogger(AggProductListService.class);
@Autowired
private SearchCommonHelper searchCommonHelper;
@Autowired
private SearchSortHelper searchSortHelper;
@Autowired
private SearchCommonService searchCommonService;
@Autowired
private SearchParamHelper searchParamHelper;
@Autowired
private ProductListHelper productListHelper;
private ApplicationEventPublisher publisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
private Map<String, String> aggTypeToEsField = new HashMap<String, String>();
@PostConstruct
void init() {
aggTypeToEsField.put("msort", ProductIndexEsField.maxSortId);
aggTypeToEsField.put("misort", ProductIndexEsField.middleSortId);
aggTypeToEsField.put("sort", ProductIndexEsField.smallSortId);
aggTypeToEsField.put("brand", ProductIndexEsField.brandId);
}
/**
* 获取每个桶的商品数量
*
* @param paramMap
* @return
*/
private int getTopHitsBucketSize(Map<String, String> paramMap) {
try {
int count = Integer.parseInt(paramMap.get("aggTypeSize"));
return count <= 0 ? 1 : count;
} catch (Exception e) {
return 1;
}
}
private SearchSort genSearchSort(String order) {
if (StringUtils.isBlank(order)) {
return null;
}
order = searchSortHelper.getLegalOrder(order, false);
if (StringUtils.isBlank(order)) {
return null;
}
String[] orderParts = order.split(":");
if (orderParts.length != 2) {
return null;
}
String sortField = orderParts[0];
SortOrder sortOrder = "desc".equals(orderParts[1]) ? SortOrder.DESC : SortOrder.ASC;
return new SearchSort(sortField, sortOrder);
}
/**
* @aggType=brand[聚合类型]
* @brand=1,2,3,4,5,6,7,8,9,10[聚合的值]
* @viewNum=10[总数]
* @aggTypeSize=1|2|3[每种品牌最多的个数]
* @second_order=shelve_time:desc[次要排序条件]
*/
@SearchCacheAble(cacheInMinute = 60, cacheName = "AGG_PRODUCT_LIST", excludeParams = { "order", "yh_channel", "pageId" })
public SearchApiResult aggProductList(Map<String, String> paramMap) {
logger.info("[func=aggProductList][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
// 1、参数校验
String aggType = paramMap.get("aggType");// 获取聚合类型
if (StringUtils.isBlank(aggType) || !aggTypeToEsField.containsKey(aggType)) {
return new SearchApiResult().setCode(400).setData("聚合类型非法");
}
if (!paramMap.containsKey(aggType)) {
return new SearchApiResult().setCode(400).setData("请传对应聚合类型的参数");
}
// 2、获取第一个聚合的字段
String firstAggField = aggTypeToEsField.get(aggType);
// 3、获取第一个聚合的桶大小
String[] aggTypeValues = paramMap.get(aggType).split(",");// 获取聚合类型的值
int firstAggBucketCount = (aggTypeValues == null ? 10 : aggTypeValues.length);// 获取聚合的桶大小
// 4、获取聚合排序条件
String aggOrder = "sales_num:desc";
if (searchCommonHelper.isNeedPersonalSearch(paramMap)) {
aggOrder = "_score:desc";
}
SearchSort aggSort = this.genSearchSort(aggOrder);
String second_order = paramMap.get("second_order");
// 5、获取次要排序条件,主要用作顺序打乱
SearchSort secondSearchSort = this.genSearchSort(second_order);
// 6、获取每个桶下面的商品数量
int topHitsBucketSize = this.getTopHitsBucketSize(paramMap);// 每个桶下面获取的商品数量
// 7、获取商品总数量
int totalViewNum = StringUtils.isBlank(paramMap.get("viewNum")) ? firstAggBucketCount * topHitsBucketSize : Integer.parseInt(paramMap.get("viewNum"));
// 8、执行查询
JSONObject jsonObject = this.getAggProductListJSONObject(paramMap, firstAggField, firstAggBucketCount, aggSort, topHitsBucketSize, secondSearchSort, totalViewNum);
if (jsonObject == null) {
jsonObject = new JSONObject();
}
return new SearchApiResult().setMessage("agg productList list").setData(jsonObject);
}
/**
* @viewNum=10[总数]
* @aggTypeSize=1|2|3[每种个品牌下面最多的个数]
* @second_order=shelve_time:desc[次要排序条件]
*/
@SearchCacheAble(cacheInMinute = 60, cacheName = "AGG_PRODUCT_LIST_BY_BRAND", excludeParams = { "order", "yh_channel", "pageId"})
public SearchApiResult aggProductListByBrand(Map<String, String> paramMap) {
logger.info("[func=aggProductListByBrand][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
// 1、获取商品总数量参数
int totalViewNum = StringUtils.isBlank(paramMap.get("viewNum")) ? 10 : Integer.parseInt(paramMap.get("viewNum"));
// 2、获取第一个聚合的字段
String firstAggField = ProductIndexEsField.brandId;
// 3、获取第一个聚合的桶大小
int firstAggBucketCount = 200 + totalViewNum;
// 4、获取聚合排序条件
String aggOrder = "sales_num:desc";
if (searchCommonHelper.isNeedPersonalSearch(paramMap)) {
aggOrder = "_score:desc";
}
SearchSort aggOrderSearchSort = this.genSearchSort(aggOrder);
// 5、获取次要排序条件,主要用作顺序打乱
String second_order = paramMap.get("second_order");
SearchSort secondSearchSort = this.genSearchSort(second_order);
// 6、获取每个桶下面的商品数量
int topHitsBucketSize = this.getTopHitsBucketSize(paramMap);// 每个桶下面获取的商品数量
// 7、执行搜索
JSONObject jsonObject = this.getAggProductListJSONObject(paramMap, firstAggField, firstAggBucketCount, aggOrderSearchSort, topHitsBucketSize, secondSearchSort,
totalViewNum);
if (jsonObject == null) {
jsonObject = new JSONObject();
}
return new SearchApiResult().setMessage("agg productList by brand list").setData(jsonObject);
}
/**
* @param firstAggField
* 【父聚合的字段名称】
* @param firstAggBucketCount
* 【父聚合的桶大小】
* @param aggSort
* 【聚合排序规则,即按什么排序推荐】
* @param secondSearchSort
* 【次要排序条件,即最终商品按什么排序】
* @param totalViewNum
* 【最终返回的总数量】
* @return
*/
private JSONObject getAggProductListJSONObject(Map<String, String> paramMap, String firstAggField, int firstAggBucketCount, SearchSort aggSort, int topHitsBucketSize,
SearchSort secondSearchSort, int totalViewNum) {
try {
// 1、构造查询条件
SearchParam searchParam = searchParamHelper.buildWithPersional(paramMap, true);
searchParam.setSize(0);
searchParam.setOffset(totalViewNum);
if (secondSearchSort != null) {
searchParam.setSortBuilders(Arrays.asList(new FieldSortBuilder(secondSearchSort.getSortField()).order(secondSearchSort.getSortOrder())));
}
// 2、构造聚合条件
final String firstAggName = "firstAgg";
List<AbstractAggregationBuilder<?>> list = new ArrayList<AbstractAggregationBuilder<?>>();
// 2.1)构造父聚合:品牌或品类聚合【同时按子聚合的sort字段排序】
TermsAggregationBuilder firstAggregationBuilder = AggregationBuilders.terms(firstAggName).field(firstAggField).order(Terms.Order.aggregation("sort", aggSort.asc()))
.size(firstAggBucketCount);
// 2.2)添加子聚合:取得分最大的值
firstAggregationBuilder.subAggregation(AggregationBuilders.max("sort").field(aggSort.getSortField()));
// 2.3)添加孙聚合:取打分最高的一个product
SortBuilder<?> sortBuilder = aggSort.isScoreOrder() ? SortBuilders.scoreSort().order(aggSort.getSortOrder()) : SortBuilders.fieldSort(aggSort.getSortField()).order(
aggSort.getSortOrder());
firstAggregationBuilder.subAggregation(AggregationBuilders.topHits("product").sort(sortBuilder).size(topHitsBucketSize));
list.add(firstAggregationBuilder);
searchParam.setAggregationBuilders(list);
// 3、执行搜索,并构造返回结果
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
if (searchResult == null || searchResult.getAggMaps() == null) {
return null;
}
Map<String, Aggregation> aggMaps = searchResult.getAggMaps();
if (!aggMaps.containsKey(firstAggName)) {
return null;
}
// 4、构造返回结果
List<Map<String, Object>> productList = this.getAggProductListResult(((MultiBucketsAggregation) aggMaps.get(firstAggName)), totalViewNum, aggSort, secondSearchSort);
JSONObject result = new JSONObject();
result.put("total", productList.size());
result.put("page", 1);
result.put("page_size", totalViewNum);
result.put("page_total", 1);
result.put("product_list", productList);
return result;
} catch (Exception e) {
logger.error("[func=getAggProductListJSONObject exception][param={}][Exception={}]", paramMap.toString(), e);
publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_AGG_PRODUCTLIST.getEventName(), EventReportEnum.SEARCHCONTROLLER_AGG_PRODUCTLIST
.getFunctionName(), EventReportEnum.SEARCHCONTROLLER_AGG_PRODUCTLIST.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
return null;
}
}
private List<Map<String, Object>> getAggProductListResult(final MultiBucketsAggregation aggregation, int viewNum, SearchSort firstOrder, SearchSort secondOrder) {
// 1、从聚合结果中获取原生数据
List<Map<String, Object>> productEsSourceList = this.getProductEsSourceListWithFromAggregation(aggregation);
// 2、按指定的首要规则排序
productEsSourceList = this.sortListBySortField(productEsSourceList, viewNum, firstOrder);
// 3、按指定的次要规则排序
productEsSourceList = this.sortListBySortField(productEsSourceList, Integer.MAX_VALUE, secondOrder);
// 4、获取最终结果
return productListHelper.buildReturnInfoByEsSourceList(productEsSourceList);
}
/**
* 从聚合结果中获取原生的商品列表
*
* @param aggregation
* @return
*/
private List<Map<String, Object>> getProductEsSourceListWithFromAggregation(final MultiBucketsAggregation aggregation) {
Iterator<? extends Bucket> itAgg = aggregation.getBuckets().iterator();
List<Map<String, Object>> productEsSourceList = new ArrayList<Map<String, Object>>();
while (itAgg.hasNext()) {
Bucket lt = itAgg.next();
if (lt.getAggregations().getAsMap().containsKey("product")) {
TopHits topHits = lt.getAggregations().get("product");
productEsSourceList.addAll(AggCommonHelper.getTopHitResultsWithScore(topHits));
}
}
return productEsSourceList;
}
private double getDouble(Object value) {
try {
return Double.parseDouble(value.toString());
} catch (Exception e) {
return 0;
}
}
private List<Map<String, Object>> sortListBySortField(List<Map<String, Object>> productEsSourceList, int viewNum, SearchSort searchSort) {
if (productEsSourceList == null || productEsSourceList.isEmpty() || searchSort == null) {
return productEsSourceList;
}
// 再按照某个字段对商品排序
boolean asc = searchSort.asc();
Collections.sort(productEsSourceList, new Comparator<Map<String, Object>>() {
public int compare(Map<String, Object> o1, Map<String, Object> o2) {
try {
double value1 = getDouble(o1.get(searchSort.getSortField()));
double value2 = getDouble(o2.get(searchSort.getSortField()));
if (value1 == value2) {
return 0;
}
if (asc) {
return value1 - value2 > 0 ? 1 : -1;
} else {
return value1 - value2 > 0 ? -1 : 1;
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
return -1;
}
}
});
if (productEsSourceList.size() > viewNum) {
productEsSourceList = CollectionUtils.safeSubList(productEsSourceList,0, viewNum);
}
return productEsSourceList;
}
}
package com.yoho.search.service.aggregations;
import com.alibaba.fastjson.JSONObject;
import com.yoho.error.event.SearchEvent;
import com.yoho.search.base.utils.CollectionUtils;
import com.yoho.search.base.utils.EventReportEnum;
import com.yoho.search.base.utils.ISearchConstants;
import com.yoho.search.base.utils.ProductIndexEsField;
import com.yoho.search.aop.cache.SearchCacheAble;
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.models.SearchApiResult;
import com.yoho.search.models.SearchSort;
import com.yoho.search.service.base.SearchCommonService;
import com.yoho.search.service.helper.*;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.MultiBucketsAggregation;
import org.elasticsearch.search.aggregations.bucket.MultiBucketsAggregation.Bucket;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.tophits.TopHits;
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.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.*;
@Service
public class AggProductListService implements ApplicationEventPublisherAware {
private static final Logger logger = LoggerFactory.getLogger(AggProductListService.class);
@Autowired
private SearchCommonHelper searchCommonHelper;
@Autowired
private SearchSortHelper searchSortHelper;
@Autowired
private SearchCommonService searchCommonService;
@Autowired
private SearchParamHelper searchParamHelper;
@Autowired
private ProductListHelper productListHelper;
private ApplicationEventPublisher publisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
private Map<String, String> aggTypeToEsField = new HashMap<String, String>();
@PostConstruct
void init() {
aggTypeToEsField.put("msort", ProductIndexEsField.maxSortId);
aggTypeToEsField.put("misort", ProductIndexEsField.middleSortId);
aggTypeToEsField.put("sort", ProductIndexEsField.smallSortId);
aggTypeToEsField.put("brand", ProductIndexEsField.brandId);
}
/**
* 获取每个桶的商品数量
*
* @param paramMap
* @return
*/
private int getTopHitsBucketSize(Map<String, String> paramMap) {
try {
int count = Integer.parseInt(paramMap.get("aggTypeSize"));
return count <= 0 ? 1 : count;
} catch (Exception e) {
return 1;
}
}
private SearchSort genSearchSort(String order) {
if (StringUtils.isBlank(order)) {
return null;
}
order = searchSortHelper.getLegalOrder(order, false);
if (StringUtils.isBlank(order)) {
return null;
}
String[] orderParts = order.split(":");
if (orderParts.length != 2) {
return null;
}
String sortField = orderParts[0];
SortOrder sortOrder = "desc".equals(orderParts[1]) ? SortOrder.DESC : SortOrder.ASC;
return new SearchSort(sortField, sortOrder);
}
/**
* @aggType=brand[聚合类型]
* @brand=1,2,3,4,5,6,7,8,9,10[聚合的值]
* @viewNum=10[总数]
* @aggTypeSize=1|2|3[每种品牌最多的个数]
* @second_order=shelve_time:desc[次要排序条件]
*/
@SearchCacheAble(cacheInMinute = 60, cacheName = "AGG_PRODUCT_LIST", excludeParams = { "order", "yh_channel", "pageId" })
public SearchApiResult aggProductList(Map<String, String> paramMap) {
logger.info("[func=aggProductList][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
// 1、参数校验
String aggType = paramMap.get("aggType");// 获取聚合类型
if (StringUtils.isBlank(aggType) || !aggTypeToEsField.containsKey(aggType)) {
return new SearchApiResult().setCode(400).setData("聚合类型非法");
}
if (!paramMap.containsKey(aggType)) {
return new SearchApiResult().setCode(400).setData("请传对应聚合类型的参数");
}
// 2、获取第一个聚合的字段
String firstAggField = aggTypeToEsField.get(aggType);
// 3、获取第一个聚合的桶大小
String[] aggTypeValues = paramMap.get(aggType).split(",");// 获取聚合类型的值
int firstAggBucketCount = (aggTypeValues == null ? 10 : aggTypeValues.length);// 获取聚合的桶大小
// 4、获取聚合排序条件
String aggOrder = "sales_num:desc";
if (searchCommonHelper.isNeedPersonalSearch(paramMap)) {
aggOrder = "_score:desc";
}
SearchSort aggSort = this.genSearchSort(aggOrder);
String second_order = paramMap.get("second_order");
// 5、获取次要排序条件,主要用作顺序打乱
SearchSort secondSearchSort = this.genSearchSort(second_order);
// 6、获取每个桶下面的商品数量
int topHitsBucketSize = this.getTopHitsBucketSize(paramMap);// 每个桶下面获取的商品数量
// 7、获取商品总数量
int totalViewNum = StringUtils.isBlank(paramMap.get("viewNum")) ? firstAggBucketCount * topHitsBucketSize : Integer.parseInt(paramMap.get("viewNum"));
// 8、执行查询
JSONObject jsonObject = this.getAggProductListJSONObject(paramMap, firstAggField, firstAggBucketCount, aggSort, topHitsBucketSize, secondSearchSort, totalViewNum);
if (jsonObject == null) {
jsonObject = new JSONObject();
}
return new SearchApiResult().setMessage("agg productList list").setData(jsonObject);
}
/**
* @viewNum=10[总数]
* @aggTypeSize=1|2|3[每种个品牌下面最多的个数]
* @second_order=shelve_time:desc[次要排序条件]
*/
@SearchCacheAble(cacheInMinute = 60, cacheName = "AGG_PRODUCT_LIST_BY_BRAND", excludeParams = { "order", "yh_channel", "pageId"})
public SearchApiResult aggProductListByBrand(Map<String, String> paramMap) {
logger.info("[func=aggProductListByBrand][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
// 1、获取商品总数量参数
int totalViewNum = StringUtils.isBlank(paramMap.get("viewNum")) ? 10 : Integer.parseInt(paramMap.get("viewNum"));
// 2、获取第一个聚合的字段
String firstAggField = ProductIndexEsField.brandId;
// 3、获取第一个聚合的桶大小
int firstAggBucketCount = 200 + totalViewNum;
// 4、获取聚合排序条件
String aggOrder = "sales_num:desc";
if (searchCommonHelper.isNeedPersonalSearch(paramMap)) {
aggOrder = "_score:desc";
}
SearchSort aggOrderSearchSort = this.genSearchSort(aggOrder);
// 5、获取次要排序条件,主要用作顺序打乱
String second_order = paramMap.get("second_order");
SearchSort secondSearchSort = this.genSearchSort(second_order);
// 6、获取每个桶下面的商品数量
int topHitsBucketSize = this.getTopHitsBucketSize(paramMap);// 每个桶下面获取的商品数量
// 7、执行搜索
JSONObject jsonObject = this.getAggProductListJSONObject(paramMap, firstAggField, firstAggBucketCount, aggOrderSearchSort, topHitsBucketSize, secondSearchSort,
totalViewNum);
if (jsonObject == null) {
jsonObject = new JSONObject();
}
return new SearchApiResult().setMessage("agg productList by brand list").setData(jsonObject);
}
/**
* @param firstAggField
* 【父聚合的字段名称】
* @param firstAggBucketCount
* 【父聚合的桶大小】
* @param aggSort
* 【聚合排序规则,即按什么排序推荐】
* @param secondSearchSort
* 【次要排序条件,即最终商品按什么排序】
* @param totalViewNum
* 【最终返回的总数量】
* @return
*/
private JSONObject getAggProductListJSONObject(Map<String, String> paramMap, String firstAggField, int firstAggBucketCount, SearchSort aggSort, int topHitsBucketSize,
SearchSort secondSearchSort, int totalViewNum) {
try {
// 1、构造查询条件
SearchParam searchParam = searchParamHelper.buildWithPersional(paramMap, true);
searchParam.setSize(0);
searchParam.setOffset(totalViewNum);
if (secondSearchSort != null) {
searchParam.setSortBuilders(Arrays.asList(new FieldSortBuilder(secondSearchSort.getSortField()).order(secondSearchSort.getSortOrder())));
}
// 2、构造聚合条件
final String firstAggName = "firstAgg";
List<AbstractAggregationBuilder<?>> list = new ArrayList<AbstractAggregationBuilder<?>>();
// 2.1)构造父聚合:品牌或品类聚合【同时按子聚合的sort字段排序】
TermsAggregationBuilder firstAggregationBuilder = AggregationBuilders.terms(firstAggName).field(firstAggField).order(Terms.Order.aggregation("sort", aggSort.asc()))
.size(firstAggBucketCount);
// 2.2)添加子聚合:取得分最大的值
firstAggregationBuilder.subAggregation(AggregationBuilders.max("sort").field(aggSort.getSortField()));
// 2.3)添加孙聚合:取打分最高的一个product
SortBuilder<?> sortBuilder = aggSort.isScoreOrder() ? SortBuilders.scoreSort().order(aggSort.getSortOrder()) : SortBuilders.fieldSort(aggSort.getSortField()).order(
aggSort.getSortOrder());
firstAggregationBuilder.subAggregation(AggregationBuilders.topHits("product").sort(sortBuilder).size(topHitsBucketSize));
list.add(firstAggregationBuilder);
searchParam.setAggregationBuilders(list);
// 3、执行搜索,并构造返回结果
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
if (searchResult == null || searchResult.getAggMaps() == null) {
return null;
}
Map<String, Aggregation> aggMaps = searchResult.getAggMaps();
if (!aggMaps.containsKey(firstAggName)) {
return null;
}
// 4、构造返回结果
List<Map<String, Object>> productList = this.getAggProductListResult(((MultiBucketsAggregation) aggMaps.get(firstAggName)), totalViewNum, aggSort, secondSearchSort);
JSONObject result = new JSONObject();
result.put("total", productList.size());
result.put("page", 1);
result.put("page_size", totalViewNum);
result.put("page_total", 1);
result.put("product_list", productList);
return result;
} catch (Exception e) {
logger.error("[func=getAggProductListJSONObject exception][param={}][Exception={}]", paramMap.toString(), e);
publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_AGG_PRODUCTLIST.getEventName(), EventReportEnum.SEARCHCONTROLLER_AGG_PRODUCTLIST
.getFunctionName(), EventReportEnum.SEARCHCONTROLLER_AGG_PRODUCTLIST.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
return null;
}
}
private List<Map<String, Object>> getAggProductListResult(final MultiBucketsAggregation aggregation, int viewNum, SearchSort firstOrder, SearchSort secondOrder) {
// 1、从聚合结果中获取原生数据
List<Map<String, Object>> productEsSourceList = this.getProductEsSourceListWithFromAggregation(aggregation);
// 2、按指定的首要规则排序
productEsSourceList = this.sortListBySortField(productEsSourceList, viewNum, firstOrder);
// 3、按指定的次要规则排序
productEsSourceList = this.sortListBySortField(productEsSourceList, Integer.MAX_VALUE, secondOrder);
// 4、获取最终结果
return productListHelper.buildReturnInfoByEsSourceList(productEsSourceList);
}
/**
* 从聚合结果中获取原生的商品列表
*
* @param aggregation
* @return
*/
private List<Map<String, Object>> getProductEsSourceListWithFromAggregation(final MultiBucketsAggregation aggregation) {
Iterator<? extends Bucket> itAgg = aggregation.getBuckets().iterator();
List<Map<String, Object>> productEsSourceList = new ArrayList<Map<String, Object>>();
while (itAgg.hasNext()) {
Bucket lt = itAgg.next();
if (lt.getAggregations().getAsMap().containsKey("product")) {
TopHits topHits = lt.getAggregations().get("product");
productEsSourceList.addAll(AggCommonHelper.getTopHitResultsWithScore(topHits));
}
}
return productEsSourceList;
}
private double getDouble(Object value) {
try {
return Double.parseDouble(value.toString());
} catch (Exception e) {
return 0;
}
}
private List<Map<String, Object>> sortListBySortField(List<Map<String, Object>> productEsSourceList, int viewNum, SearchSort searchSort) {
if (productEsSourceList == null || productEsSourceList.isEmpty() || searchSort == null) {
return productEsSourceList;
}
// 再按照某个字段对商品排序
boolean asc = searchSort.asc();
Collections.sort(productEsSourceList, new Comparator<Map<String, Object>>() {
public int compare(Map<String, Object> o1, Map<String, Object> o2) {
try {
double value1 = getDouble(o1.get(searchSort.getSortField()));
double value2 = getDouble(o2.get(searchSort.getSortField()));
if (value1 == value2) {
return 0;
}
if (asc) {
return value1 - value2 > 0 ? 1 : -1;
} else {
return value1 - value2 > 0 ? -1 : 1;
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
return -1;
}
}
});
if (productEsSourceList.size() > viewNum) {
productEsSourceList = CollectionUtils.safeSubList(productEsSourceList,0, viewNum);
}
return productEsSourceList;
}
}
... ...
package com.yoho.search.service.service;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yoho.search.base.utils.CollectionUtils;
import com.yoho.search.base.utils.ISearchConstants;
import com.yoho.search.cache.beans.AbstractCacheAbleService;
import com.yoho.search.cache.log.SearchCacheMatchLogger;
import com.yoho.search.cache.model.SearchCache;
import com.yoho.search.common.utils.SearchApiResultUtils;
import com.yoho.search.core.es.agg.IAggregation;
import com.yoho.search.core.es.model.SearchParam;
import com.yoho.search.service.aggregations.impls.AggregationFactoryService;
import com.yoho.search.service.base.SearchDynamicConfigService;
import com.yoho.search.service.base.SearchRequestParams;
import com.yoho.search.service.helper.SearchParamHelper;
import org.apache.commons.lang.StringUtils;
import com.yoho.search.models.SearchApiResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class AggRecommendService extends AbstractCacheAbleService {
private static final Logger logger = LoggerFactory.getLogger(AggRecommendService.class);
private static final int DEFAULT_AGGREGATION_COUNT = 100;
@Autowired
private AggregationService aggregationService;
@Autowired
private AggregationFactoryService aggregationFactoryService;
@Autowired
private SearchParamHelper searchParamHelper;
@Autowired
private SearchDynamicConfigService searchDynamicConfigService;
public SearchCache getSearchCache() {
return searchCacheFactory.getRecommendCache();
}
public SearchApiResult aggRecommendBrand(Map<String, String> paramMap) {
try {
logger.info("[func=aggRecommendBrand][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
// 0、开关支持是否关闭个性化
if (!searchDynamicConfigService.isRecommendPersionalOpen()) {
paramMap.remove("uid");
}
// 1、获取核心参数
boolean needPreAggregation = true;
String aggWithParamBrand = paramMap.get(SearchRequestParams.PARAM_SEARCH_AGG_WITH_PARAM_BRAND);
if ("Y".equals(aggWithParamBrand)) {
needPreAggregation = false;
}
int recommendBrandCount = Integer.parseInt(paramMap.getOrDefault(SearchRequestParams.PARAM_SEARCH_VIEWNUM, "8"));
// 2、构建带queryBuilder和filter的SearchParam
SearchParam searchParam = searchParamHelper.buildSearchParam(paramMap, true, null, needPreAggregation ? "brand" : null);
// 3、构造聚合
IAggregation recommendBrandAgg = aggregationFactoryService.getRecommendBrandAggregation(paramMap, recommendBrandCount);
searchParam.setAggregationBuilders(Arrays.asList(recommendBrandAgg.getBuilder()));
// 4、构建offset
searchParam.setOffset(recommendBrandCount);// justForCache
// 5、从缓存中获取
final String productIndexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
JSONArray cacheJSONArray = searchCacheService.getJSONArrayFromCache(searchCache, productIndexName, searchParam);
if (cacheJSONArray != null) {
SearchCacheMatchLogger.doSearchCacheMatchLog("/productindex/aggRecommendBrand.json", paramMap);
return new SearchApiResult().setData(cacheJSONArray);
}
// 6、从ES中获取
JSONObject recommendBrandResult = aggregationService.getAggNameAndResponse(recommendBrandAgg, searchParam);
if (recommendBrandResult == null) {
return new SearchApiResult().setData(500).setMessage("exception");
}
// 7、生成结果并且加入缓存
JSONArray brandJSONArray = recommendBrandResult.getJSONArray(recommendBrandAgg.aggName());
if (brandJSONArray != null) {
searchCacheService.addJSONArrayToCache(searchCache, productIndexName, searchParam, brandJSONArray);
}
return new SearchApiResult().setData(brandJSONArray);
} catch (Exception e) {
return SearchApiResultUtils.errorSearchApiResult("aggRecommendBrand", paramMap, e);
}
}
public SearchApiResult aggRecommendShop(Map<String, String> paramMap) {
try {
// 0、开关支持是否关闭个性化
if (!searchDynamicConfigService.isRecommendPersionalOpen()) {
paramMap.remove("uid");
}
// 1、获取核心参数
final int page = StringUtils.isBlank(paramMap.get("page")) ? 1 : Integer.parseInt(paramMap.get("page"));
final int count = StringUtils.isBlank(paramMap.get("viewNum")) ? 1 : Integer.parseInt(paramMap.get("viewNum"));
// 1.1添加默认参数
paramMap.remove(SearchRequestParams.PARAM_SEARCH_ORDER);// 此接口不支持order
paramMap.put(SearchRequestParams.PARAM_SEARCH_GLOBAL_FILTER_BRAND, "Y");// 页面屏蔽
paramMap.put(SearchRequestParams.PARAM_SEARCH_STATUS, "1");// 上架
paramMap.put(SearchRequestParams.PARAM_SEARCH_STOCKNUM, "1");// 有库存
paramMap.put(SearchRequestParams.PARAM_SEARCH_ISOUTLETS, "2");// 非奥莱
paramMap.put(SearchRequestParams.PARAM_SEARCH_ATTRIBUTE_NOT, "2");// 非赠品
// 2、构建带queryBuilder和filter的SearchParam
SearchParam searchParam = searchParamHelper.buildWithPersional(paramMap, true);
// 3、构造聚合操作
IAggregation recommendShopAgg = aggregationFactoryService.getRecommendShopAggregation(paramMap, 100, 2);
searchParam.setAggregationBuilders(Arrays.asList(recommendShopAgg.getBuilder()));
// 4、构建offset
searchParam.setOffset(DEFAULT_AGGREGATION_COUNT);// justForCache
// 5、从缓存中获取
final String productIndexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
JSONArray cacheJSONArray = searchCacheService.getJSONArrayFromCache(searchCache, productIndexName, searchParam);
if (cacheJSONArray != null) {
SearchCacheMatchLogger.doSearchCacheMatchLog("/productindex/aggRecommendShop.json", paramMap);
return this.getRecommendShopSearchApiResult(cacheJSONArray, page, count);
}
// 6、从ES中获取
JSONObject recommendShopResult = aggregationService.getAggNameAndResponse(recommendShopAgg, searchParam);
if (recommendShopResult == null) {
return new SearchApiResult().setData(500).setMessage("exception");
}
// 7、生成结果并且加入缓存
JSONArray recommendShops = recommendShopResult.getJSONArray(recommendShopAgg.aggName());
if (recommendShops != null) {
searchCacheService.addJSONArrayToCache(searchCache, productIndexName, searchParam, recommendShops);
return this.getRecommendShopSearchApiResult(recommendShops, page, count);
}
return new SearchApiResult().setData(new ArrayList<Map<String, Object>>());
} catch (Exception e) {
return SearchApiResultUtils.errorSearchApiResult("aggRecommendBrand", paramMap, e);
}
}
private SearchApiResult getRecommendShopSearchApiResult(JSONArray cacheJSONArray, int page, int count) {
List<Map<String, Object>> cacheList = new ArrayList<Map<String, Object>>();
for (int i = 0; i < cacheJSONArray.size(); i++) {
cacheList.add(cacheJSONArray.getJSONObject(i));
}
List<Map<String, Object>> results = CollectionUtils.memoryPaging(cacheList, page, count);
return new SearchApiResult().setData(results);
}
}
package com.yoho.search.service.aggregations;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yoho.search.base.utils.CollectionUtils;
import com.yoho.search.base.utils.ISearchConstants;
import com.yoho.search.cache.beans.AbstractCacheAbleService;
import com.yoho.search.cache.log.SearchCacheMatchLogger;
import com.yoho.search.cache.model.SearchCache;
import com.yoho.search.common.utils.SearchApiResultUtils;
import com.yoho.search.core.es.agg.IAggregation;
import com.yoho.search.core.es.model.SearchParam;
import com.yoho.search.service.aggregations.impls.AggregationFactoryService;
import com.yoho.search.service.base.SearchDynamicConfigService;
import com.yoho.search.service.base.SearchRequestParams;
import com.yoho.search.service.helper.SearchParamHelper;
import org.apache.commons.lang.StringUtils;
import com.yoho.search.models.SearchApiResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class AggRecommendService extends AbstractCacheAbleService {
private static final Logger logger = LoggerFactory.getLogger(AggRecommendService.class);
private static final int DEFAULT_AGGREGATION_COUNT = 100;
@Autowired
private AggregationService aggregationService;
@Autowired
private AggregationFactoryService aggregationFactoryService;
@Autowired
private SearchParamHelper searchParamHelper;
@Autowired
private SearchDynamicConfigService searchDynamicConfigService;
public SearchCache getSearchCache() {
return searchCacheFactory.getRecommendCache();
}
public SearchApiResult aggRecommendBrand(Map<String, String> paramMap) {
try {
logger.info("[func=aggRecommendBrand][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
// 0、开关支持是否关闭个性化
if (!searchDynamicConfigService.isRecommendPersionalOpen()) {
paramMap.remove("uid");
}
// 1、获取核心参数
boolean needPreAggregation = true;
String aggWithParamBrand = paramMap.get(SearchRequestParams.PARAM_SEARCH_AGG_WITH_PARAM_BRAND);
if ("Y".equals(aggWithParamBrand)) {
needPreAggregation = false;
}
int recommendBrandCount = Integer.parseInt(paramMap.getOrDefault(SearchRequestParams.PARAM_SEARCH_VIEWNUM, "8"));
// 2、构建带queryBuilder和filter的SearchParam
SearchParam searchParam = searchParamHelper.buildSearchParam(paramMap, true, null, needPreAggregation ? "brand" : null);
// 3、构造聚合
IAggregation recommendBrandAgg = aggregationFactoryService.getRecommendBrandAggregation(paramMap, recommendBrandCount);
searchParam.setAggregationBuilders(Arrays.asList(recommendBrandAgg.getBuilder()));
// 4、构建offset
searchParam.setOffset(recommendBrandCount);// justForCache
// 5、从缓存中获取
final String productIndexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
JSONArray cacheJSONArray = searchCacheService.getJSONArrayFromCache(searchCache, productIndexName, searchParam);
if (cacheJSONArray != null) {
SearchCacheMatchLogger.doSearchCacheMatchLog("/productindex/aggRecommendBrand.json", paramMap);
return new SearchApiResult().setData(cacheJSONArray);
}
// 6、从ES中获取
JSONObject recommendBrandResult = aggregationService.getAggNameAndResponse(recommendBrandAgg, searchParam);
if (recommendBrandResult == null) {
return new SearchApiResult().setData(500).setMessage("exception");
}
// 7、生成结果并且加入缓存
JSONArray brandJSONArray = recommendBrandResult.getJSONArray(recommendBrandAgg.aggName());
if (brandJSONArray != null) {
searchCacheService.addJSONArrayToCache(searchCache, productIndexName, searchParam, brandJSONArray);
}
return new SearchApiResult().setData(brandJSONArray);
} catch (Exception e) {
return SearchApiResultUtils.errorSearchApiResult("aggRecommendBrand", paramMap, e);
}
}
public SearchApiResult aggRecommendShop(Map<String, String> paramMap) {
try {
// 0、开关支持是否关闭个性化
if (!searchDynamicConfigService.isRecommendPersionalOpen()) {
paramMap.remove("uid");
}
// 1、获取核心参数
final int page = StringUtils.isBlank(paramMap.get("page")) ? 1 : Integer.parseInt(paramMap.get("page"));
final int count = StringUtils.isBlank(paramMap.get("viewNum")) ? 1 : Integer.parseInt(paramMap.get("viewNum"));
// 1.1添加默认参数
paramMap.remove(SearchRequestParams.PARAM_SEARCH_ORDER);// 此接口不支持order
paramMap.put(SearchRequestParams.PARAM_SEARCH_GLOBAL_FILTER_BRAND, "Y");// 页面屏蔽
paramMap.put(SearchRequestParams.PARAM_SEARCH_STATUS, "1");// 上架
paramMap.put(SearchRequestParams.PARAM_SEARCH_STOCKNUM, "1");// 有库存
paramMap.put(SearchRequestParams.PARAM_SEARCH_ISOUTLETS, "2");// 非奥莱
paramMap.put(SearchRequestParams.PARAM_SEARCH_ATTRIBUTE_NOT, "2");// 非赠品
// 2、构建带queryBuilder和filter的SearchParam
SearchParam searchParam = searchParamHelper.buildWithPersional(paramMap, true);
// 3、构造聚合操作
IAggregation recommendShopAgg = aggregationFactoryService.getRecommendShopAggregation(paramMap, 100, 2);
searchParam.setAggregationBuilders(Arrays.asList(recommendShopAgg.getBuilder()));
// 4、构建offset
searchParam.setOffset(DEFAULT_AGGREGATION_COUNT);// justForCache
// 5、从缓存中获取
final String productIndexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
JSONArray cacheJSONArray = searchCacheService.getJSONArrayFromCache(searchCache, productIndexName, searchParam);
if (cacheJSONArray != null) {
SearchCacheMatchLogger.doSearchCacheMatchLog("/productindex/aggRecommendShop.json", paramMap);
return this.getRecommendShopSearchApiResult(cacheJSONArray, page, count);
}
// 6、从ES中获取
JSONObject recommendShopResult = aggregationService.getAggNameAndResponse(recommendShopAgg, searchParam);
if (recommendShopResult == null) {
return new SearchApiResult().setData(500).setMessage("exception");
}
// 7、生成结果并且加入缓存
JSONArray recommendShops = recommendShopResult.getJSONArray(recommendShopAgg.aggName());
if (recommendShops != null) {
searchCacheService.addJSONArrayToCache(searchCache, productIndexName, searchParam, recommendShops);
return this.getRecommendShopSearchApiResult(recommendShops, page, count);
}
return new SearchApiResult().setData(new ArrayList<Map<String, Object>>());
} catch (Exception e) {
return SearchApiResultUtils.errorSearchApiResult("aggRecommendBrand", paramMap, e);
}
}
private SearchApiResult getRecommendShopSearchApiResult(JSONArray cacheJSONArray, int page, int count) {
List<Map<String, Object>> cacheList = new ArrayList<Map<String, Object>>();
for (int i = 0; i < cacheJSONArray.size(); i++) {
cacheList.add(cacheJSONArray.getJSONObject(i));
}
List<Map<String, Object>> results = CollectionUtils.memoryPaging(cacheList, page, count);
return new SearchApiResult().setData(results);
}
}
... ...
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;
import com.yoho.search.cache.model.SearchCache;
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.scene.shopproduct.ShopProductCacheBean;
import com.yoho.search.recall.models.common.ParamQueryFilter;
import com.yoho.search.service.scene.shopproduct.ShopProductRequest;
import com.yoho.search.service.scene.shopproduct.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.cache.beans.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;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
@Service
public class AggregationService extends AbstractCacheAbleService implements ApplicationEventPublisherAware {
private static final Logger logger = LoggerFactory.getLogger(AggregationService.class);
@Autowired
private AggregationFactoryService aggregationFactoryService;
@Autowired
private SearchCommonService searchCommonService;
@Autowired
private SearchParamHelper searchParamHelper;
@Autowired
private ShopProductCacheBean shopSknCacheBean;
@Autowired
private SearchCommonHelper searchCommonHelper;
@Override
public SearchCache getSearchCache() {
return searchCacheFactory.getAggregationSearchCache();
}
private ApplicationEventPublisher publisher;
private static final String AggregationServiceIndex = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
private SearchResult doSearchForAggregation(SearchParam searchParam) {
SearchParam searchParamClone = searchParam.clone();
return searchCommonService.doSearch(AggregationServiceIndex, searchParamClone);
}
public JSONObject getAggNameAndResponse(IAggregation aggregation, SearchParam searchParam) throws Exception {
SearchResult searchResult = this.doSearchForAggregation(searchParam);
Map<String, Aggregation> aggMaps = searchResult.getAggMaps();
JSONObject result = aggregation.getAggNameAndResponse(aggMaps);
return result;
}
public JSONObject getAggNameAndResponseWithTotal(IAggregation aggregation, SearchParam searchParam) throws Exception {
SearchResult searchResult = this.doSearchForAggregation(searchParam);
Map<String, Aggregation> aggMaps = searchResult.getAggMaps();
JSONObject result = aggregation.getAggNameAndResponse(aggMaps);
result.put("total", searchResult.getTotal());
return result;
}
private JSONObject getAggNameAndResponseWithCache(IAggregation aggregation, SearchParam searchParam) {
try {
JSONObject cacheObject = searchCacheService.getJSONObjectFromCache(this.searchCache, AggregationServiceIndex, searchParam);
if (cacheObject != null) {
cacheObject = aggregation.doSomethingAfterSerialized(cacheObject);
return cacheObject;
}
JSONObject result = this.getAggNameAndResponse(aggregation, searchParam);
if (result != null) {
searchCacheService.addJSONObjectToCache(this.searchCache, AggregationServiceIndex, searchParam, result);
}
return result;
} catch (Exception e) {
logger.error(e.getMessage());
publisher.publishEvent(new SearchEvent(EventReportEnum.AGGREGATIONSERVICE_GETAGGNAMEANDRESPONSE.getEventName(),
EventReportEnum.AGGREGATIONSERVICE_GETAGGNAMEANDRESPONSE.getFunctionName(), EventReportEnum.AGGREGATIONSERVICE_GETAGGNAMEANDRESPONSE.getMoudleName(),
"exception", IgnoreSomeException.filterSomeException(e), null));
return null;
}
}
private SearchParam genSearchParamForAgg(IAggregation aggregation, Map<String, String> paramMap, String filterParamName, int cacheSize) throws Exception {
SearchParam searchParam = searchParamHelper.buildWithFilterParam(paramMap, filterParamName);
searchParam.setAggregationBuilders(Arrays.asList(aggregation.getBuilder()));
searchParam.setOffset(cacheSize);// 只是用来做缓存的
return searchParam;
}
/**
* 获取性别层面的聚合结果
*/
public JSONObject getGenderNewAggregationResult(Map<String, String> paramMap, boolean needPreAggregation) throws Exception {
IAggregation aggregation = aggregationFactoryService.getGenderNewAggregation();
String filterParamName = needPreAggregation ? SearchRequestParams.PARAM_SEARCH_GENDER : null;
SearchParam searchParam = this.genSearchParamForAgg(aggregation, paramMap, filterParamName, 0);
return this.getAggNameAndResponseWithCache(aggregation, searchParam);
}
/**
* 获取年龄层的聚合结果
*/
public JSONObject getAgeLevelAggregationResult(Map<String, String> paramMap, boolean needPreAggregation) throws Exception {
IAggregation aggregation = aggregationFactoryService.getAgeLevelAggregation();
String filterParamName = needPreAggregation ? SearchRequestParams.PARAM_SEARCH_AGELEVEL : null;
SearchParam searchParam = this.genSearchParamForAgg(aggregation, paramMap, filterParamName, 0);
return this.getAggNameAndResponseWithCache(aggregation, searchParam);
}
/**
* 获取价格层面的聚合结果[结果经过缓存之后会变成无序的,此时需要手动转一下]
*/
public JSONObject getPriceAggregationResult(Map<String, String> paramMap, boolean needPreAggregation) throws Exception {
IAggregation priceAggregation = aggregationFactoryService.getPriceAggregation();
String filterParamName = needPreAggregation ? SearchRequestParams.PARAM_SEARCH_PRICE : null;
SearchParam searchParam = this.genSearchParamForAgg(priceAggregation, paramMap, filterParamName, 0);
return this.getAggNameAndResponseWithCache(priceAggregation, searchParam);
}
/**
* 获取颜色层面的聚合结果
*/
public JSONObject getColorAggregationResult(Map<String, String> paramMap, boolean needPreAggregation) throws Exception {
IAggregation colorAggregation = aggregationFactoryService.getColorAggregation(paramMap);
String filterParamName = needPreAggregation ? SearchRequestParams.PARAM_SEARCH_COLOR : null;
SearchParam searchParam = this.genSearchParamForAgg(colorAggregation, paramMap, filterParamName, 0);
return this.getAggNameAndResponseWithCache(colorAggregation, searchParam);
}
/**
* 获取风格层面的聚合结果
*/
public JSONObject getStyleAggregationResult(Map<String, String> paramMap, boolean needPreAggregation) throws Exception {
IAggregation styleAggregation = aggregationFactoryService.getStyleAggregation(paramMap);
String filterParamName = needPreAggregation ? SearchRequestParams.PARAM_SEARCH_STYLE : null;
SearchParam searchParam = this.genSearchParamForAgg(styleAggregation, paramMap, filterParamName, 0);
return this.getAggNameAndResponseWithCache(styleAggregation, searchParam);
}
/**
* 获取尺码层面的聚合结果
*/
public JSONObject getSizeAggregationResult(Map<String, String> paramMap, boolean needPreAggregation) throws Exception {
IAggregation sizeAggregation = aggregationFactoryService.getSizeAggregation();
String filterParamName = needPreAggregation ? SearchRequestParams.PARAM_SEARCH_SIZE : null;
SearchParam searchParam = this.genSearchParamForAgg(sizeAggregation, paramMap, filterParamName, 0);
return this.getAggNameAndResponseWithCache(sizeAggregation, searchParam);
}
/**
* 获取是否新品的聚合结果
*/
public JSONObject getIsNewAggregationResult(Map<String, String> paramMap, boolean needPreAggregation) throws Exception {
IAggregation isNewAggregation = aggregationFactoryService.getIsNewAggregation();
String filterParamName = needPreAggregation ? SearchRequestParams.PARAM_SEARCH_ISNEW : null;
SearchParam searchParam = this.genSearchParamForAgg(isNewAggregation, paramMap, filterParamName, 0);
return this.getAggNameAndResponseWithCache(isNewAggregation, searchParam);
}
/**
* 获取是否限量的聚合结果
*/
public JSONObject getIsLimitAggregationResult(Map<String, String> paramMap, boolean needPreAggregation) throws Exception {
IAggregation isLimitedAggregation = aggregationFactoryService.getIsLimitedAggregation();
String filterParamName = needPreAggregation ? SearchRequestParams.PARAM_SEARCH_ISLIMITED : null;
SearchParam searchParam = this.genSearchParamForAgg(isLimitedAggregation, paramMap, filterParamName, 0);
return this.getAggNameAndResponseWithCache(isLimitedAggregation, searchParam);
}
/**
* 获取是否特供的聚合结果
*/
public JSONObject getIsSecialofferAggregationResult(Map<String, String> paramMap, boolean needPreAggregation) throws Exception {
IAggregation isSecialofferAggregation = aggregationFactoryService.getIsSecialofferAggregation();
String filterParamName = needPreAggregation ? SearchRequestParams.PARAM_SEARCH_SPECIALOFFER : null;
SearchParam searchParam = this.genSearchParamForAgg(isSecialofferAggregation, paramMap, filterParamName, 0);
return this.getAggNameAndResponseWithCache(isSecialofferAggregation, searchParam);
}
/**
* 获取商品关键词的聚合,来源与风格、款式和属性。
*/
public JSONObject getKeywordAggregationResult(Map<String, String> paramMap, int aggCount) throws Exception {
IAggregation keywordAggregation = aggregationFactoryService.getKeywordAggregation(paramMap, aggCount);
String filterParamName = null;
SearchParam searchParam = this.genSearchParamForAgg(keywordAggregation, paramMap, filterParamName, 0);
return this.getAggNameAndResponseWithCache(keywordAggregation, searchParam);
}
/**
* 获取店铺聚合结果。
*/
public JSONObject getShopAggregationResult(Map<String, String> paramMap, int aggCount) throws Exception {
IAggregation shopAggregation = aggregationFactoryService.getShopAggregation(aggCount);
String filterParamName = null;
SearchParam searchParam = this.genSearchParamForAgg(shopAggregation, paramMap, filterParamName, 0);
return this.getAggNameAndResponseWithCache(shopAggregation, searchParam);
}
/**
* 获取专区名称面的聚合结果
*/
public JSONObject getPromotionAggregationResult(Map<String, String> paramMap, int aggCount) throws Exception {
IAggregation zqNameAggregation = aggregationFactoryService.getZqNameAggregation(aggCount);
String filterParamName = null;
Integer paramNum = Integer.valueOf(paramMap.getOrDefault(SearchRequestParams.PARAM_SEARCH_PARAMETPERNUM, "5"));
SearchParam searchParam = this.genSearchParamForAgg(zqNameAggregation, paramMap, filterParamName, paramNum);
return this.getAggNameAndResponseWithCache(zqNameAggregation, searchParam);
}
/**
* 获取规则层面的聚合结果
*/
public JSONObject getStandardAggregationResult(Map<String, String> paramMap) throws Exception {
IAggregation standardAggregation = aggregationFactoryService.getStandardAggregation(paramMap);
String filterParamName = null;
Integer paramNum = Integer.valueOf(paramMap.getOrDefault(SearchRequestParams.PARAM_SEARCH_PARAMETPERNUM, "5"));
SearchParam searchParam = this.genSearchParamForAgg(standardAggregation, paramMap, filterParamName, paramNum);
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.PARAM_SEARCH_HR_SHOP);
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.aggregations;
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;
import com.yoho.search.cache.model.SearchCache;
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.scene.shopproduct.ShopProductCacheBean;
import com.yoho.search.recall.models.common.ParamQueryFilter;
import com.yoho.search.service.scene.shopproduct.ShopProductRequest;
import com.yoho.search.service.scene.shopproduct.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.cache.beans.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;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
@Service
public class AggregationService extends AbstractCacheAbleService implements ApplicationEventPublisherAware {
private static final Logger logger = LoggerFactory.getLogger(AggregationService.class);
@Autowired
private AggregationFactoryService aggregationFactoryService;
@Autowired
private SearchCommonService searchCommonService;
@Autowired
private SearchParamHelper searchParamHelper;
@Autowired
private ShopProductCacheBean shopSknCacheBean;
@Autowired
private SearchCommonHelper searchCommonHelper;
@Override
public SearchCache getSearchCache() {
return searchCacheFactory.getAggregationSearchCache();
}
private ApplicationEventPublisher publisher;
private static final String AggregationServiceIndex = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
private SearchResult doSearchForAggregation(SearchParam searchParam) {
SearchParam searchParamClone = searchParam.clone();
return searchCommonService.doSearch(AggregationServiceIndex, searchParamClone);
}
public JSONObject getAggNameAndResponse(IAggregation aggregation, SearchParam searchParam) throws Exception {
SearchResult searchResult = this.doSearchForAggregation(searchParam);
Map<String, Aggregation> aggMaps = searchResult.getAggMaps();
JSONObject result = aggregation.getAggNameAndResponse(aggMaps);
return result;
}
public JSONObject getAggNameAndResponseWithTotal(IAggregation aggregation, SearchParam searchParam) throws Exception {
SearchResult searchResult = this.doSearchForAggregation(searchParam);
Map<String, Aggregation> aggMaps = searchResult.getAggMaps();
JSONObject result = aggregation.getAggNameAndResponse(aggMaps);
result.put("total", searchResult.getTotal());
return result;
}
private JSONObject getAggNameAndResponseWithCache(IAggregation aggregation, SearchParam searchParam) {
try {
JSONObject cacheObject = searchCacheService.getJSONObjectFromCache(this.searchCache, AggregationServiceIndex, searchParam);
if (cacheObject != null) {
cacheObject = aggregation.doSomethingAfterSerialized(cacheObject);
return cacheObject;
}
JSONObject result = this.getAggNameAndResponse(aggregation, searchParam);
if (result != null) {
searchCacheService.addJSONObjectToCache(this.searchCache, AggregationServiceIndex, searchParam, result);
}
return result;
} catch (Exception e) {
logger.error(e.getMessage());
publisher.publishEvent(new SearchEvent(EventReportEnum.AGGREGATIONSERVICE_GETAGGNAMEANDRESPONSE.getEventName(),
EventReportEnum.AGGREGATIONSERVICE_GETAGGNAMEANDRESPONSE.getFunctionName(), EventReportEnum.AGGREGATIONSERVICE_GETAGGNAMEANDRESPONSE.getMoudleName(),
"exception", IgnoreSomeException.filterSomeException(e), null));
return null;
}
}
private SearchParam genSearchParamForAgg(IAggregation aggregation, Map<String, String> paramMap, String filterParamName, int cacheSize) throws Exception {
SearchParam searchParam = searchParamHelper.buildWithFilterParam(paramMap, filterParamName);
searchParam.setAggregationBuilders(Arrays.asList(aggregation.getBuilder()));
searchParam.setOffset(cacheSize);// 只是用来做缓存的
return searchParam;
}
/**
* 获取性别层面的聚合结果
*/
public JSONObject getGenderNewAggregationResult(Map<String, String> paramMap, boolean needPreAggregation) throws Exception {
IAggregation aggregation = aggregationFactoryService.getGenderNewAggregation();
String filterParamName = needPreAggregation ? SearchRequestParams.PARAM_SEARCH_GENDER : null;
SearchParam searchParam = this.genSearchParamForAgg(aggregation, paramMap, filterParamName, 0);
return this.getAggNameAndResponseWithCache(aggregation, searchParam);
}
/**
* 获取年龄层的聚合结果
*/
public JSONObject getAgeLevelAggregationResult(Map<String, String> paramMap, boolean needPreAggregation) throws Exception {
IAggregation aggregation = aggregationFactoryService.getAgeLevelAggregation();
String filterParamName = needPreAggregation ? SearchRequestParams.PARAM_SEARCH_AGELEVEL : null;
SearchParam searchParam = this.genSearchParamForAgg(aggregation, paramMap, filterParamName, 0);
return this.getAggNameAndResponseWithCache(aggregation, searchParam);
}
/**
* 获取价格层面的聚合结果[结果经过缓存之后会变成无序的,此时需要手动转一下]
*/
public JSONObject getPriceAggregationResult(Map<String, String> paramMap, boolean needPreAggregation) throws Exception {
IAggregation priceAggregation = aggregationFactoryService.getPriceAggregation();
String filterParamName = needPreAggregation ? SearchRequestParams.PARAM_SEARCH_PRICE : null;
SearchParam searchParam = this.genSearchParamForAgg(priceAggregation, paramMap, filterParamName, 0);
return this.getAggNameAndResponseWithCache(priceAggregation, searchParam);
}
/**
* 获取颜色层面的聚合结果
*/
public JSONObject getColorAggregationResult(Map<String, String> paramMap, boolean needPreAggregation) throws Exception {
IAggregation colorAggregation = aggregationFactoryService.getColorAggregation(paramMap);
String filterParamName = needPreAggregation ? SearchRequestParams.PARAM_SEARCH_COLOR : null;
SearchParam searchParam = this.genSearchParamForAgg(colorAggregation, paramMap, filterParamName, 0);
return this.getAggNameAndResponseWithCache(colorAggregation, searchParam);
}
/**
* 获取风格层面的聚合结果
*/
public JSONObject getStyleAggregationResult(Map<String, String> paramMap, boolean needPreAggregation) throws Exception {
IAggregation styleAggregation = aggregationFactoryService.getStyleAggregation(paramMap);
String filterParamName = needPreAggregation ? SearchRequestParams.PARAM_SEARCH_STYLE : null;
SearchParam searchParam = this.genSearchParamForAgg(styleAggregation, paramMap, filterParamName, 0);
return this.getAggNameAndResponseWithCache(styleAggregation, searchParam);
}
/**
* 获取尺码层面的聚合结果
*/
public JSONObject getSizeAggregationResult(Map<String, String> paramMap, boolean needPreAggregation) throws Exception {
IAggregation sizeAggregation = aggregationFactoryService.getSizeAggregation();
String filterParamName = needPreAggregation ? SearchRequestParams.PARAM_SEARCH_SIZE : null;
SearchParam searchParam = this.genSearchParamForAgg(sizeAggregation, paramMap, filterParamName, 0);
return this.getAggNameAndResponseWithCache(sizeAggregation, searchParam);
}
/**
* 获取是否新品的聚合结果
*/
public JSONObject getIsNewAggregationResult(Map<String, String> paramMap, boolean needPreAggregation) throws Exception {
IAggregation isNewAggregation = aggregationFactoryService.getIsNewAggregation();
String filterParamName = needPreAggregation ? SearchRequestParams.PARAM_SEARCH_ISNEW : null;
SearchParam searchParam = this.genSearchParamForAgg(isNewAggregation, paramMap, filterParamName, 0);
return this.getAggNameAndResponseWithCache(isNewAggregation, searchParam);
}
/**
* 获取是否限量的聚合结果
*/
public JSONObject getIsLimitAggregationResult(Map<String, String> paramMap, boolean needPreAggregation) throws Exception {
IAggregation isLimitedAggregation = aggregationFactoryService.getIsLimitedAggregation();
String filterParamName = needPreAggregation ? SearchRequestParams.PARAM_SEARCH_ISLIMITED : null;
SearchParam searchParam = this.genSearchParamForAgg(isLimitedAggregation, paramMap, filterParamName, 0);
return this.getAggNameAndResponseWithCache(isLimitedAggregation, searchParam);
}
/**
* 获取是否特供的聚合结果
*/
public JSONObject getIsSecialofferAggregationResult(Map<String, String> paramMap, boolean needPreAggregation) throws Exception {
IAggregation isSecialofferAggregation = aggregationFactoryService.getIsSecialofferAggregation();
String filterParamName = needPreAggregation ? SearchRequestParams.PARAM_SEARCH_SPECIALOFFER : null;
SearchParam searchParam = this.genSearchParamForAgg(isSecialofferAggregation, paramMap, filterParamName, 0);
return this.getAggNameAndResponseWithCache(isSecialofferAggregation, searchParam);
}
/**
* 获取商品关键词的聚合,来源与风格、款式和属性。
*/
public JSONObject getKeywordAggregationResult(Map<String, String> paramMap, int aggCount) throws Exception {
IAggregation keywordAggregation = aggregationFactoryService.getKeywordAggregation(paramMap, aggCount);
String filterParamName = null;
SearchParam searchParam = this.genSearchParamForAgg(keywordAggregation, paramMap, filterParamName, 0);
return this.getAggNameAndResponseWithCache(keywordAggregation, searchParam);
}
/**
* 获取店铺聚合结果。
*/
public JSONObject getShopAggregationResult(Map<String, String> paramMap, int aggCount) throws Exception {
IAggregation shopAggregation = aggregationFactoryService.getShopAggregation(aggCount);
String filterParamName = null;
SearchParam searchParam = this.genSearchParamForAgg(shopAggregation, paramMap, filterParamName, 0);
return this.getAggNameAndResponseWithCache(shopAggregation, searchParam);
}
/**
* 获取专区名称面的聚合结果
*/
public JSONObject getPromotionAggregationResult(Map<String, String> paramMap, int aggCount) throws Exception {
IAggregation zqNameAggregation = aggregationFactoryService.getZqNameAggregation(aggCount);
String filterParamName = null;
Integer paramNum = Integer.valueOf(paramMap.getOrDefault(SearchRequestParams.PARAM_SEARCH_PARAMETPERNUM, "5"));
SearchParam searchParam = this.genSearchParamForAgg(zqNameAggregation, paramMap, filterParamName, paramNum);
return this.getAggNameAndResponseWithCache(zqNameAggregation, searchParam);
}
/**
* 获取规则层面的聚合结果
*/
public JSONObject getStandardAggregationResult(Map<String, String> paramMap) throws Exception {
IAggregation standardAggregation = aggregationFactoryService.getStandardAggregation(paramMap);
String filterParamName = null;
Integer paramNum = Integer.valueOf(paramMap.getOrDefault(SearchRequestParams.PARAM_SEARCH_PARAMETPERNUM, "5"));
SearchParam searchParam = this.genSearchParamForAgg(standardAggregation, paramMap, filterParamName, paramNum);
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.PARAM_SEARCH_HR_SHOP);
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;
import com.alibaba.fastjson.JSONObject;
import com.yoho.error.event.SearchEvent;
import com.yoho.search.base.utils.EventReportEnum;
import com.yoho.search.base.utils.JsonUtil;
import com.yoho.search.core.es.utils.IgnoreSomeException;
import com.yoho.search.models.SearchApiResult;
import com.yoho.search.service.base.SearchCommonService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.stream.Collectors;
@Service
public class ProductIndexService implements ApplicationEventPublisherAware {
private static final Logger logger = LoggerFactory.getLogger(ProductIndexService.class);
@Autowired
private AggregationService aggregationService;
ApplicationEventPublisher publisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
private SearchApiResult getSuccessResult(Object resultObject) {
SearchApiResult result = new SearchApiResult();
result.setCode(200);
result.setMessage("success");
result.setData(resultObject);
return result;
}
private SearchApiResult getErrorResult(String methodName, Object param, Exception e) {
logger.error("[※查询]失败:[func={}][param={}][message={}]", methodName, JsonUtil.toJson(param), e);
SearchApiResult result = new SearchApiResult();
result.setCode(500);
result.setMessage(e.getMessage());
result.setData(new JSONObject());
return result;
}
public interface Searcher {
public Object getResult() throws Exception;
}
private SearchApiResult getSearchApiResult(String methodName, Map<String, String> paramMap, ProductIndexService.Searcher searcher) {
long begin = System.currentTimeMillis();
logger.info("[model=ProductIndexService][func={}][param={}][begin={}]", methodName, paramMap.toString(), begin);
try {
Object resultObject = searcher.getResult();
return this.getSuccessResult(resultObject);
} catch (Exception e) {
publisher.publishEvent(new SearchEvent(EventReportEnum.PRODUCTINDEXSERVICEIMPL_GETSEARCHAPIRESULT.getEventName(),
EventReportEnum.PRODUCTINDEXSERVICEIMPL_GETSEARCHAPIRESULT.getFunctionName(), EventReportEnum.PRODUCTINDEXSERVICEIMPL_GETSEARCHAPIRESULT.getMoudleName(),
"exception", IgnoreSomeException.filterSomeException(e), null));
return this.getErrorResult(methodName, paramMap, e);
} finally {
long end = System.currentTimeMillis();
logger.info("[model=ProductIndexService][func={}][param={}][end={}][cost={}ms]", methodName, paramMap.toString(), end, end - begin);
}
}
public SearchApiResult aggAgeLevel(Map<String, String> paramMap) {
return this.getSearchApiResult("aggAgeLevel", paramMap, new ProductIndexService.Searcher() {
@Override
public Object getResult() throws Exception {
JSONObject jsonObject = aggregationService.getAgeLevelAggregationResult(paramMap, false);
return jsonObject.get("ageLevelAgg");
}
});
}
public SearchApiResult aggGender(Map<String, String> paramMap) {
return this.getSearchApiResult("aggGender", paramMap, new ProductIndexService.Searcher() {
@Override
public Object getResult() throws Exception {
JSONObject jsonObject = aggregationService.getGenderNewAggregationResult(paramMap, false);
return jsonObject.get("genderAgg");
}
});
}
public SearchApiResult aggPrice(Map<String, String> paramMap) {
return this.getSearchApiResult("aggPrice", paramMap, new ProductIndexService.Searcher() {
@Override
public Object getResult() throws Exception {
JSONObject jsonObject = aggregationService.getPriceAggregationResult(paramMap, false);
return jsonObject.get("priceAgg");
}
});
}
public SearchApiResult aggColor(Map<String, String> paramMap) {
return this.getSearchApiResult("aggColor", paramMap, new ProductIndexService.Searcher() {
@Override
public Object getResult() throws Exception {
JSONObject jsonObject = aggregationService.getColorAggregationResult(paramMap, false);
return jsonObject.get("colorAgg");
}
});
}
public SearchApiResult aggStyle(Map<String, String> paramMap) {
return this.getSearchApiResult("aggStyle", paramMap, new ProductIndexService.Searcher() {
@Override
public Object getResult() throws Exception {
JSONObject jsonObject = aggregationService.getStyleAggregationResult(paramMap, false);
return jsonObject.get("styleAgg");
}
});
}
public SearchApiResult aggStandard(Map<String, String> paramMap) {
return this.getSearchApiResult("aggStandard", paramMap, new ProductIndexService.Searcher() {
@Override
public Object getResult() throws Exception {
JSONObject jsonObject = aggregationService.getStandardAggregationResult(paramMap);
return jsonObject.get("standardAgg");
}
});
}
public SearchApiResult aggSize(Map<String, String> paramMap) {
return this.getSearchApiResult("aggSize", paramMap, new ProductIndexService.Searcher() {
@Override
public Object getResult() throws Exception {
JSONObject jsonObject = aggregationService.getSizeAggregationResult(paramMap, false);
return jsonObject.get("sizeAgg");
}
});
}
public SearchApiResult aggPromotion(Map<String, String> paramMap) {
return this.getSearchApiResult("aggPromotion", paramMap, new ProductIndexService.Searcher() {
@Override
public Object getResult() throws Exception {
JSONObject jsonObject = aggregationService.getPromotionAggregationResult(paramMap, 1000);
return jsonObject.get("promotionAgg");
}
});
}
public SearchApiResult aggShops(Map<String, String> paramMap) {
return this.getSearchApiResult("aggShops", paramMap, new ProductIndexService.Searcher() {
@Override
public Object getResult() throws Exception {
JSONObject jsonObject = aggregationService.getShopAggregationResult(paramMap, 100);
return jsonObject.get("shopAgg");
}
});
}
public SearchApiResult aggNew(Map<String, String> paramMap) {
return this.getSearchApiResult("aggNew", paramMap, new ProductIndexService.Searcher() {
@Override
public Object getResult() throws Exception {
JSONObject jsonObject = aggregationService.getIsNewAggregationResult(paramMap, false);
Object isNewResponse = jsonObject.get("isnewAgg");
if (isNewResponse != null && ((Boolean) isNewResponse).booleanValue()) {
return "Y";
} else {
return "N";
}
}
});
}
public SearchApiResult aggLimited(Map<String, String> paramMap) {
return this.getSearchApiResult("aggLimited", paramMap, new ProductIndexService.Searcher() {
@Override
public Object getResult() throws Exception {
JSONObject jsonObject = aggregationService.getIsLimitAggregationResult(paramMap, false);
Object islimitedAgg = jsonObject.get("islimitedAgg");
if (islimitedAgg != null && ((Boolean) islimitedAgg).booleanValue()) {
return "Y";
} else {
return "N";
}
}
});
}
public SearchApiResult aggSpecialoffer(Map<String, String> paramMap) {
return this.getSearchApiResult("aggSpecialoffer", paramMap, new ProductIndexService.Searcher() {
@Override
public Object getResult() throws Exception {
JSONObject jsonObject = aggregationService.getIsSecialofferAggregationResult(paramMap, false);
Object specialofferAgg = jsonObject.get("specialofferAgg");
if (specialofferAgg != null && ((Boolean) specialofferAgg).booleanValue()) {
return "Y";
} else {
return "N";
}
}
});
}
public SearchApiResult aggKeywords(Map<String, String> paramMap) {
final int randomKeywordCount = StringUtils.isBlank(paramMap.get("keyword_count")) ? 8 : Integer.parseInt(paramMap.get("keyword_count"));
return this.getSearchApiResult("aggKeywords", paramMap, new ProductIndexService.Searcher() {
@Override
public Object getResult() throws Exception {
JSONObject jsonObject = aggregationService.getKeywordAggregationResult(paramMap, 50);
@SuppressWarnings("unchecked")
List<String> keywordList = (List<String>) jsonObject.get("keywordAgg");
return getRandomKeywords(keywordList, randomKeywordCount);
}
});
}
private List<String> getRandomKeywords(List<String> keywordList, int randomKeywordCount) {
if (keywordList == null || keywordList.size() <= randomKeywordCount) {
return keywordList;
}
return new Random().ints(0, keywordList.size()).distinct().limit(randomKeywordCount).mapToObj(index -> keywordList.get(index)).collect(Collectors.toList());
}
}
package com.yoho.search.service.aggregations;
import com.alibaba.fastjson.JSONObject;
import com.yoho.error.event.SearchEvent;
import com.yoho.search.base.utils.EventReportEnum;
import com.yoho.search.base.utils.JsonUtil;
import com.yoho.search.core.es.utils.IgnoreSomeException;
import com.yoho.search.models.SearchApiResult;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.stream.Collectors;
@Service
public class ProductIndexService implements ApplicationEventPublisherAware {
private static final Logger logger = LoggerFactory.getLogger(ProductIndexService.class);
@Autowired
private AggregationService aggregationService;
ApplicationEventPublisher publisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
private SearchApiResult getSuccessResult(Object resultObject) {
SearchApiResult result = new SearchApiResult();
result.setCode(200);
result.setMessage("success");
result.setData(resultObject);
return result;
}
private SearchApiResult getErrorResult(String methodName, Object param, Exception e) {
logger.error("[※查询]失败:[func={}][param={}][message={}]", methodName, JsonUtil.toJson(param), e);
SearchApiResult result = new SearchApiResult();
result.setCode(500);
result.setMessage(e.getMessage());
result.setData(new JSONObject());
return result;
}
public interface Searcher {
public Object getResult() throws Exception;
}
private SearchApiResult getSearchApiResult(String methodName, Map<String, String> paramMap, ProductIndexService.Searcher searcher) {
long begin = System.currentTimeMillis();
logger.info("[model=ProductIndexService][func={}][param={}][begin={}]", methodName, paramMap.toString(), begin);
try {
Object resultObject = searcher.getResult();
return this.getSuccessResult(resultObject);
} catch (Exception e) {
publisher.publishEvent(new SearchEvent(EventReportEnum.PRODUCTINDEXSERVICEIMPL_GETSEARCHAPIRESULT.getEventName(),
EventReportEnum.PRODUCTINDEXSERVICEIMPL_GETSEARCHAPIRESULT.getFunctionName(), EventReportEnum.PRODUCTINDEXSERVICEIMPL_GETSEARCHAPIRESULT.getMoudleName(),
"exception", IgnoreSomeException.filterSomeException(e), null));
return this.getErrorResult(methodName, paramMap, e);
} finally {
long end = System.currentTimeMillis();
logger.info("[model=ProductIndexService][func={}][param={}][end={}][cost={}ms]", methodName, paramMap.toString(), end, end - begin);
}
}
public SearchApiResult aggAgeLevel(Map<String, String> paramMap) {
return this.getSearchApiResult("aggAgeLevel", paramMap, new ProductIndexService.Searcher() {
@Override
public Object getResult() throws Exception {
JSONObject jsonObject = aggregationService.getAgeLevelAggregationResult(paramMap, false);
return jsonObject.get("ageLevelAgg");
}
});
}
public SearchApiResult aggGender(Map<String, String> paramMap) {
return this.getSearchApiResult("aggGender", paramMap, new ProductIndexService.Searcher() {
@Override
public Object getResult() throws Exception {
JSONObject jsonObject = aggregationService.getGenderNewAggregationResult(paramMap, false);
return jsonObject.get("genderAgg");
}
});
}
public SearchApiResult aggPrice(Map<String, String> paramMap) {
return this.getSearchApiResult("aggPrice", paramMap, new ProductIndexService.Searcher() {
@Override
public Object getResult() throws Exception {
JSONObject jsonObject = aggregationService.getPriceAggregationResult(paramMap, false);
return jsonObject.get("priceAgg");
}
});
}
public SearchApiResult aggColor(Map<String, String> paramMap) {
return this.getSearchApiResult("aggColor", paramMap, new ProductIndexService.Searcher() {
@Override
public Object getResult() throws Exception {
JSONObject jsonObject = aggregationService.getColorAggregationResult(paramMap, false);
return jsonObject.get("colorAgg");
}
});
}
public SearchApiResult aggStyle(Map<String, String> paramMap) {
return this.getSearchApiResult("aggStyle", paramMap, new ProductIndexService.Searcher() {
@Override
public Object getResult() throws Exception {
JSONObject jsonObject = aggregationService.getStyleAggregationResult(paramMap, false);
return jsonObject.get("styleAgg");
}
});
}
public SearchApiResult aggStandard(Map<String, String> paramMap) {
return this.getSearchApiResult("aggStandard", paramMap, new ProductIndexService.Searcher() {
@Override
public Object getResult() throws Exception {
JSONObject jsonObject = aggregationService.getStandardAggregationResult(paramMap);
return jsonObject.get("standardAgg");
}
});
}
public SearchApiResult aggSize(Map<String, String> paramMap) {
return this.getSearchApiResult("aggSize", paramMap, new ProductIndexService.Searcher() {
@Override
public Object getResult() throws Exception {
JSONObject jsonObject = aggregationService.getSizeAggregationResult(paramMap, false);
return jsonObject.get("sizeAgg");
}
});
}
public SearchApiResult aggPromotion(Map<String, String> paramMap) {
return this.getSearchApiResult("aggPromotion", paramMap, new ProductIndexService.Searcher() {
@Override
public Object getResult() throws Exception {
JSONObject jsonObject = aggregationService.getPromotionAggregationResult(paramMap, 1000);
return jsonObject.get("promotionAgg");
}
});
}
public SearchApiResult aggShops(Map<String, String> paramMap) {
return this.getSearchApiResult("aggShops", paramMap, new ProductIndexService.Searcher() {
@Override
public Object getResult() throws Exception {
JSONObject jsonObject = aggregationService.getShopAggregationResult(paramMap, 100);
return jsonObject.get("shopAgg");
}
});
}
public SearchApiResult aggNew(Map<String, String> paramMap) {
return this.getSearchApiResult("aggNew", paramMap, new ProductIndexService.Searcher() {
@Override
public Object getResult() throws Exception {
JSONObject jsonObject = aggregationService.getIsNewAggregationResult(paramMap, false);
Object isNewResponse = jsonObject.get("isnewAgg");
if (isNewResponse != null && ((Boolean) isNewResponse).booleanValue()) {
return "Y";
} else {
return "N";
}
}
});
}
public SearchApiResult aggLimited(Map<String, String> paramMap) {
return this.getSearchApiResult("aggLimited", paramMap, new ProductIndexService.Searcher() {
@Override
public Object getResult() throws Exception {
JSONObject jsonObject = aggregationService.getIsLimitAggregationResult(paramMap, false);
Object islimitedAgg = jsonObject.get("islimitedAgg");
if (islimitedAgg != null && ((Boolean) islimitedAgg).booleanValue()) {
return "Y";
} else {
return "N";
}
}
});
}
public SearchApiResult aggSpecialoffer(Map<String, String> paramMap) {
return this.getSearchApiResult("aggSpecialoffer", paramMap, new ProductIndexService.Searcher() {
@Override
public Object getResult() throws Exception {
JSONObject jsonObject = aggregationService.getIsSecialofferAggregationResult(paramMap, false);
Object specialofferAgg = jsonObject.get("specialofferAgg");
if (specialofferAgg != null && ((Boolean) specialofferAgg).booleanValue()) {
return "Y";
} else {
return "N";
}
}
});
}
public SearchApiResult aggKeywords(Map<String, String> paramMap) {
final int randomKeywordCount = StringUtils.isBlank(paramMap.get("keyword_count")) ? 8 : Integer.parseInt(paramMap.get("keyword_count"));
return this.getSearchApiResult("aggKeywords", paramMap, new ProductIndexService.Searcher() {
@Override
public Object getResult() throws Exception {
JSONObject jsonObject = aggregationService.getKeywordAggregationResult(paramMap, 50);
@SuppressWarnings("unchecked")
List<String> keywordList = (List<String>) jsonObject.get("keywordAgg");
return getRandomKeywords(keywordList, randomKeywordCount);
}
});
}
private List<String> getRandomKeywords(List<String> keywordList, int randomKeywordCount) {
if (keywordList == null || keywordList.size() <= randomKeywordCount) {
return keywordList;
}
return new Random().ints(0, keywordList.size()).distinct().limit(randomKeywordCount).mapToObj(index -> keywordList.get(index)).collect(Collectors.toList());
}
}
... ...
package com.yoho.search.service.scene.aggregations;
import com.yoho.search.base.utils.CollectionUtils;
import com.yoho.search.base.utils.ISearchConstants;
import com.yoho.search.aop.cache.SearchCacheAble;
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.models.RecommendPromotionAggVO;
import com.yoho.search.models.SearchApiResult;
import com.yoho.search.service.aggregations.impls.AggregationFactoryService;
import com.yoho.search.service.base.SearchCommonService;
import com.yoho.search.service.base.index.promotion.PromotionIndexBaseService;
import com.yoho.search.service.helper.SearchParamHelper;
import org.elasticsearch.search.aggregations.Aggregation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.*;
@Component
public class SceneAggregationsHelper {
private static final Logger logger = LoggerFactory.getLogger(SceneAggregationsHelper.class);
@Autowired
private AggregationFactoryService aggregationFactoryService;
@Autowired
private SearchParamHelper searchParamHelper;
@Autowired
private SearchCommonService searchCommonService;
@Autowired
private PromotionIndexBaseService promotionIndexBaseService;
private Object getAggregationResponse(IAggregation aggregation, Map<String, String> paramMap) throws Exception {
// 1、构造SearchParam
SearchParam searchParam = searchParamHelper.buildDefault(paramMap);
searchParam.setAggregationBuilders(Arrays.asList(aggregation.getBuilder()));
searchParam.setOffset(0);
searchParam.setSize(0);
// 2、查询es
SearchResult searchResult = searchCommonService.doSearch(ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
Map<String, Aggregation> aggMaps = searchResult.getAggMaps();
return aggregation.getAggregationResponseMap(aggMaps);
}
/**
* 聚合规则-非个性化
*
* @param paramMap
* @return
*/
@SearchCacheAble(cacheName = "SCENE_AGG_STANDARD", cacheInMinute = 15, excludeParams = { "uid","udid", "order", "page", "viewNum", "yh_channel" })
public SearchApiResult sceneAggStandard(Map<String, String> paramMap) {
try {
IAggregation standardAggregation = aggregationFactoryService.getStandardAggregation(paramMap);
Object standardAggregationRsp = this.getAggregationResponse(standardAggregation, paramMap);
return new SearchApiResult().setData(standardAggregationRsp);
} catch (Exception e) {
logger.error(e.getMessage(), e);
return new SearchApiResult().setCode(500).setMessage("sceneAggStandard Exception");
}
}
/**
* 聚合自定义标签-非个性化
*
* @param paramMap
* @return
*/
@SearchCacheAble(cacheName = "SCENE_AGG_CUSTOMIZETAG", cacheInMinute = 15, excludeParams = { "uid","udid","order", "page", "viewNum", "yh_channel" })
public SearchApiResult sceneAggCustomizeTag(Map<String, String> paramMap) {
try {
IAggregation customizeAggregation = aggregationFactoryService.getCustomizeTagAggregation(paramMap);
Object respone = this.getAggregationResponse(customizeAggregation, paramMap);
return new SearchApiResult().setData(respone);
} catch (Exception e) {
logger.error(e.getMessage(), e);
return new SearchApiResult().setCode(500).setMessage("secneAggCustomizeTag Exception");
}
}
/**
* 聚合促销专题-非个性化
*
* @param paramMap
* @return
*/
@SearchCacheAble(cacheName = "SCENE_AGG_PROMOTION", cacheInMinute = 15, excludeParams = { "uid","udid", "order", "page", "viewNum", "yh_channel" })
public SearchApiResult sceneAggPromotion(Map<String, String> paramMap) {
try {
// 1、获取aggregation
IAggregation aggregation = aggregationFactoryService.getRecommendPromotionAggregation(50);
Object ids = this.getAggregationResponse(aggregation, paramMap);
List<RecommendPromotionAggVO> result = new ArrayList<>();
if(ids == null){
return new SearchApiResult().setData(result);
}
result = promotionIndexBaseService.getPromotionInfoByIds(ISearchConstants.INDEX_NAME_PROMOTIONINDEX, (List<Integer>) ids, true);
return new SearchApiResult().setData(result);
} catch (Exception e) {
logger.error(e.getMessage(), e);
return new SearchApiResult().setCode(500).setMessage("secneAggrecommendPromotion Exception");
}
}
/**
* 聚合促销专题-非个性化
*
* @param paramMap
* @return
*/
@SearchCacheAble(cacheName = "AGG_PROMOTION", cacheInMinute = 15, excludeParams = { "uid", "udid", "order", "page", "viewNum", "yh_channel"})
public List<RecommendPromotionAggVO> aggPromotion(Map<String, String> paramMap) {
try {
IAggregation aggregation = aggregationFactoryService.getPromotionAggregation(50);
Object ids = this.getAggregationResponse(aggregation, paramMap);
if(ids == null){
return Collections.emptyList();
}
return promotionIndexBaseService.getPromotionInfoByIds(ISearchConstants.INDEX_NAME_PROMOTIONINDEX, (List<Integer>) ids, false);
} catch (Exception e) {
logger.error(e.getMessage(), e);
return Collections.emptyList();
}
}
/**
* 从缓存中获取数据后按分页参数截取
*
* @param recommendPromotions
* @param page
* @param count
* @return
*/
public List<?> subRecommendPromotions(Object recommendPromotions, int page, int count) {
try {
if (recommendPromotions == null || !(recommendPromotions instanceof List)) {
return new ArrayList<Object>();
}
List<?> recommendPromotionList = (List<?>) recommendPromotions;
if (recommendPromotionList.isEmpty()) {
return recommendPromotionList;
}
int totalCount = recommendPromotionList.size();
int start = (page - 1) * count;
int end = start + count;
if (start >= totalCount) {
return Collections.emptyList();
}
if (end > totalCount) {
end = totalCount;
}
return CollectionUtils.safeSubList(recommendPromotionList, start, end);
} catch (Exception e) {
logger.error(e.getMessage(), e);
return new ArrayList<Object>();
}
}
}
package com.yoho.search.service.aggregations;
import com.yoho.search.base.utils.CollectionUtils;
import com.yoho.search.base.utils.ISearchConstants;
import com.yoho.search.aop.cache.SearchCacheAble;
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.models.RecommendPromotionAggVO;
import com.yoho.search.models.SearchApiResult;
import com.yoho.search.service.aggregations.impls.AggregationFactoryService;
import com.yoho.search.service.base.SearchCommonService;
import com.yoho.search.service.base.index.promotion.PromotionIndexBaseService;
import com.yoho.search.service.helper.SearchParamHelper;
import org.elasticsearch.search.aggregations.Aggregation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.*;
@Component
public class SceneAggregationsHelper {
private static final Logger logger = LoggerFactory.getLogger(SceneAggregationsHelper.class);
@Autowired
private AggregationFactoryService aggregationFactoryService;
@Autowired
private SearchParamHelper searchParamHelper;
@Autowired
private SearchCommonService searchCommonService;
@Autowired
private PromotionIndexBaseService promotionIndexBaseService;
private Object getAggregationResponse(IAggregation aggregation, Map<String, String> paramMap) throws Exception {
// 1、构造SearchParam
SearchParam searchParam = searchParamHelper.buildDefault(paramMap);
searchParam.setAggregationBuilders(Arrays.asList(aggregation.getBuilder()));
searchParam.setOffset(0);
searchParam.setSize(0);
// 2、查询es
SearchResult searchResult = searchCommonService.doSearch(ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
Map<String, Aggregation> aggMaps = searchResult.getAggMaps();
return aggregation.getAggregationResponseMap(aggMaps);
}
/**
* 聚合规则-非个性化
*
* @param paramMap
* @return
*/
@SearchCacheAble(cacheName = "SCENE_AGG_STANDARD", cacheInMinute = 15, excludeParams = { "uid","udid", "order", "page", "viewNum", "yh_channel" })
public SearchApiResult sceneAggStandard(Map<String, String> paramMap) {
try {
IAggregation standardAggregation = aggregationFactoryService.getStandardAggregation(paramMap);
Object standardAggregationRsp = this.getAggregationResponse(standardAggregation, paramMap);
return new SearchApiResult().setData(standardAggregationRsp);
} catch (Exception e) {
logger.error(e.getMessage(), e);
return new SearchApiResult().setCode(500).setMessage("sceneAggStandard Exception");
}
}
/**
* 聚合自定义标签-非个性化
*
* @param paramMap
* @return
*/
@SearchCacheAble(cacheName = "SCENE_AGG_CUSTOMIZETAG", cacheInMinute = 15, excludeParams = { "uid","udid","order", "page", "viewNum", "yh_channel" })
public SearchApiResult sceneAggCustomizeTag(Map<String, String> paramMap) {
try {
IAggregation customizeAggregation = aggregationFactoryService.getCustomizeTagAggregation(paramMap);
Object respone = this.getAggregationResponse(customizeAggregation, paramMap);
return new SearchApiResult().setData(respone);
} catch (Exception e) {
logger.error(e.getMessage(), e);
return new SearchApiResult().setCode(500).setMessage("secneAggCustomizeTag Exception");
}
}
/**
* 聚合促销专题-非个性化
*
* @param paramMap
* @return
*/
@SearchCacheAble(cacheName = "SCENE_AGG_PROMOTION", cacheInMinute = 15, excludeParams = { "uid","udid", "order", "page", "viewNum", "yh_channel" })
public SearchApiResult sceneAggPromotion(Map<String, String> paramMap) {
try {
// 1、获取aggregation
IAggregation aggregation = aggregationFactoryService.getRecommendPromotionAggregation(50);
Object ids = this.getAggregationResponse(aggregation, paramMap);
List<RecommendPromotionAggVO> result = new ArrayList<>();
if(ids == null){
return new SearchApiResult().setData(result);
}
result = promotionIndexBaseService.getPromotionInfoByIds(ISearchConstants.INDEX_NAME_PROMOTIONINDEX, (List<Integer>) ids, true);
return new SearchApiResult().setData(result);
} catch (Exception e) {
logger.error(e.getMessage(), e);
return new SearchApiResult().setCode(500).setMessage("secneAggrecommendPromotion Exception");
}
}
/**
* 聚合促销专题-非个性化
*
* @param paramMap
* @return
*/
@SearchCacheAble(cacheName = "AGG_PROMOTION", cacheInMinute = 15, excludeParams = { "uid", "udid", "order", "page", "viewNum", "yh_channel"})
public List<RecommendPromotionAggVO> aggPromotion(Map<String, String> paramMap) {
try {
IAggregation aggregation = aggregationFactoryService.getPromotionAggregation(50);
Object ids = this.getAggregationResponse(aggregation, paramMap);
if(ids == null){
return Collections.emptyList();
}
return promotionIndexBaseService.getPromotionInfoByIds(ISearchConstants.INDEX_NAME_PROMOTIONINDEX, (List<Integer>) ids, false);
} catch (Exception e) {
logger.error(e.getMessage(), e);
return Collections.emptyList();
}
}
/**
* 从缓存中获取数据后按分页参数截取
*
* @param recommendPromotions
* @param page
* @param count
* @return
*/
public List<?> subRecommendPromotions(Object recommendPromotions, int page, int count) {
try {
if (recommendPromotions == null || !(recommendPromotions instanceof List)) {
return new ArrayList<Object>();
}
List<?> recommendPromotionList = (List<?>) recommendPromotions;
if (recommendPromotionList.isEmpty()) {
return recommendPromotionList;
}
int totalCount = recommendPromotionList.size();
int start = (page - 1) * count;
int end = start + count;
if (start >= totalCount) {
return Collections.emptyList();
}
if (end > totalCount) {
end = totalCount;
}
return CollectionUtils.safeSubList(recommendPromotionList, start, end);
} catch (Exception e) {
logger.error(e.getMessage(), e);
return new ArrayList<Object>();
}
}
}
... ...
... ... @@ -14,10 +14,10 @@ import org.elasticsearch.search.aggregations.Aggregation;
import com.alibaba.fastjson.JSONObject;
import com.yoho.search.base.utils.ProductIndexEsField;
import com.yoho.search.core.es.agg.AbstractAggregation;
import com.yoho.search.service.aggregations.common.KeyTopHitModel;
import com.yoho.search.service.aggregations.common.SimpleFieldAgg;
import com.yoho.search.service.aggregations.models.KeyTopHitModel;
import com.yoho.search.service.aggregations.models.SimpleFieldAgg;
import com.yoho.search.service.base.index.BrandIndexBaseService;
import com.yoho.search.service.helper.AggCommonHelper;
import com.yoho.search.service.aggregations.AggCommonHelper;
/**
* 获取品牌信息,以及每个品牌下获取多少个商品
... ...
... ... @@ -14,10 +14,10 @@ import org.elasticsearch.search.aggregations.Aggregation;
import com.alibaba.fastjson.JSONObject;
import com.yoho.search.base.utils.ProductIndexEsField;
import com.yoho.search.core.es.agg.AbstractAggregation;
import com.yoho.search.service.aggregations.common.KeyTopHitModel;
import com.yoho.search.service.aggregations.common.SimpleFieldAgg;
import com.yoho.search.service.aggregations.models.KeyTopHitModel;
import com.yoho.search.service.aggregations.models.SimpleFieldAgg;
import com.yoho.search.service.base.index.ShopsIndexBaseService;
import com.yoho.search.service.helper.AggCommonHelper;
import com.yoho.search.service.aggregations.AggCommonHelper;
/**
* 获取店铺信息,以及每个店铺下有多少个商品
... ...
... ... @@ -9,9 +9,9 @@ import org.elasticsearch.search.aggregations.Aggregation;
import com.yoho.search.base.utils.ProductIndexEsField;
import com.yoho.search.core.es.agg.AbstractAggregation;
import com.yoho.search.service.aggregations.common.SimpleFieldAgg;
import com.yoho.search.service.aggregations.models.SimpleFieldAgg;
import com.yoho.search.service.base.index.BrandIndexBaseService;
import com.yoho.search.service.helper.AggCommonHelper;
import com.yoho.search.service.aggregations.AggCommonHelper;
import com.yoho.search.service.scorer.personal.PersonalVectorFeatureSearch;
public class RecommendBrandAggregation extends AbstractAggregation {
... ...
... ... @@ -11,10 +11,10 @@ import org.springframework.util.CollectionUtils;
import com.yoho.search.base.utils.ProductIndexEsField;
import com.yoho.search.core.es.agg.AbstractAggregation;
import com.yoho.search.service.aggregations.common.SimpleFieldAgg;
import com.yoho.search.service.aggregations.models.SimpleFieldAgg;
import com.yoho.search.service.base.index.ProductIndexBaseService;
import com.yoho.search.service.base.index.ShopsIndexBaseService;
import com.yoho.search.service.helper.AggCommonHelper;
import com.yoho.search.service.aggregations.AggCommonHelper;
import com.yoho.search.service.scorer.personal.PersonalVectorFeatureSearch;
public class RecommendShopAggregation extends AbstractAggregation {
... ...
package com.yoho.search.service.helper;
package com.yoho.search.service.aggregations.models;
public class AggKeyCount {
... ...
package com.yoho.search.service.aggregations.common;
import org.elasticsearch.search.sort.SortOrder;
public class FieldSortOrder {
private String sortField;
private SortOrder sortOrder;
private boolean desc;
public FieldSortOrder(String fieldOrder) {
String[] fieldAndOrders = fieldOrder.split(":");
this.sortField = fieldAndOrders[0];
String order = fieldAndOrders[1];
desc = "desc".equalsIgnoreCase(order) ? true : false;
sortOrder = desc ? SortOrder.DESC : SortOrder.ASC;
}
public String getSortField() {
return sortField;
}
public SortOrder getSortOrder() {
return sortOrder;
}
public boolean isDesc() {
return desc;
}
public boolean isScoreOrder() {
return sortField.equalsIgnoreCase("_score");
}
}
package com.yoho.search.service.aggregations.models;
import org.elasticsearch.search.sort.SortOrder;
public class FieldSortOrder {
private String sortField;
private SortOrder sortOrder;
private boolean desc;
public FieldSortOrder(String fieldOrder) {
String[] fieldAndOrders = fieldOrder.split(":");
this.sortField = fieldAndOrders[0];
String order = fieldAndOrders[1];
desc = "desc".equalsIgnoreCase(order) ? true : false;
sortOrder = desc ? SortOrder.DESC : SortOrder.ASC;
}
public String getSortField() {
return sortField;
}
public SortOrder getSortOrder() {
return sortOrder;
}
public boolean isDesc() {
return desc;
}
public boolean isScoreOrder() {
return sortField.equalsIgnoreCase("_score");
}
}
... ...
package com.yoho.search.service.aggregations.common;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class KeyTopHitModel {
private String key;
private long docCount;
private List<Map<String, Object>> topHitList = new ArrayList<Map<String, Object>>();
public KeyTopHitModel(String key, long docCount, List<Map<String, Object>> topHitList) {
this.key = key;
this.docCount = docCount;
this.topHitList = topHitList;
}
public String getKey() {
return key;
}
public long getDocCount() {
return docCount;
}
public List<Map<String, Object>> getTopHitList() {
return topHitList;
}
}
package com.yoho.search.service.aggregations.models;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class KeyTopHitModel {
private String key;
private long docCount;
private List<Map<String, Object>> topHitList = new ArrayList<Map<String, Object>>();
public KeyTopHitModel(String key, long docCount, List<Map<String, Object>> topHitList) {
this.key = key;
this.docCount = docCount;
this.topHitList = topHitList;
}
public String getKey() {
return key;
}
public long getDocCount() {
return docCount;
}
public List<Map<String, Object>> getTopHitList() {
return topHitList;
}
}
... ...
package com.yoho.search.service.aggregations.common;
public class SimpleFieldAgg {
private String aggName;
private String esField;
private int bucketCount;
public SimpleFieldAgg(String aggName, String esField, int bucketCount) {
super();
this.aggName = aggName;
this.esField = esField;
this.bucketCount = bucketCount;
}
public String getAggName() {
return aggName;
}
public String getEsField() {
return esField;
}
public int getBucketCount() {
return bucketCount;
}
}
package com.yoho.search.service.aggregations.models;
public class SimpleFieldAgg {
private String aggName;
private String esField;
private int bucketCount;
public SimpleFieldAgg(String aggName, String esField, int bucketCount) {
super();
this.aggName = aggName;
this.esField = esField;
this.bucketCount = bucketCount;
}
public String getAggName() {
return aggName;
}
public String getEsField() {
return esField;
}
public int getBucketCount() {
return bucketCount;
}
}
... ...
package com.yoho.search.service.service;
import java.util.Arrays;
import java.util.Map;
import com.yoho.error.event.SearchEvent;
import com.yoho.search.base.utils.EventReportEnum;
import com.yoho.search.base.utils.ISearchConstants;
import com.yoho.search.cache.beans.AbstractCacheAbleService;
import com.yoho.search.cache.model.SearchCache;
import com.yoho.search.common.utils.SearchApiResultUtils;
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.impls.AggregationFactoryService;
import com.yoho.search.service.base.SearchCommonService;
import com.yoho.search.service.helper.SearchAfterCacheHelper;
import com.yoho.search.service.helper.SearchParamHelper;
import org.elasticsearch.index.query.BoolQueryBuilder;
import com.alibaba.fastjson.JSONObject;
import com.yoho.search.models.SearchApiResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
@Service
public class DiscountService extends AbstractCacheAbleService implements ApplicationEventPublisherAware {
private static final Logger logger = LoggerFactory.getLogger(DiscountService.class);
@Autowired
private SearchParamHelper searchParamHelper;
@Autowired
private AggregationFactoryService aggregationFactoryService;
@Autowired
private SearchCommonService searchCommonService;
@Autowired
private SearchAfterCacheHelper searchAfterCacheService;
@Override
public SearchCache getSearchCache() {
return searchCacheFactory.getAggregationSearchCache();
}
private ApplicationEventPublisher publisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
public SearchApiResult discount(Map<String, String> paramMap) {
try {
logger.info("[func=discount][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
// 构造查询参数
SearchParam searchParam = searchParamHelper.buildDefault(paramMap);
// 按1-3,4-6,7-10折的规则进行聚合[按区间聚合]
IAggregation discountAggregation = aggregationFactoryService.getDiscountAggregation();
searchParam.setAggregationBuilders(Arrays.asList(discountAggregation.getBuilder()));
searchParam.setSize(0);
// 构造返回结果
SearchApiResult searchApiResult = new SearchApiResult().setMessage("discount List.");
// 先从缓存中获取,如果能取到,则直接返回
JSONObject cacheObject = searchCacheService.getJSONObjectFromCache(this.searchCache, ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
if (cacheObject != null) {
Object result = searchAfterCacheService.dealDiscountCacheObject(cacheObject);
searchApiResult.setData(result);
return searchApiResult;
}
// es检索
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
if (searchResult == null || searchResult.getAggMaps() == null) {
return searchApiResult.setData("");
}
Object discountAggResult = discountAggregation.getAggregationResponseMap(searchResult.getAggMaps());
if (discountAggResult == null) {
return searchApiResult.setData("");
}
JSONObject discountObject = new JSONObject();
discountObject.put("discount", discountAggResult);
searchCacheService.addJSONObjectToCache(this.searchCache, ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam, discountObject);
return searchApiResult.setData(discountObject);
} catch (Exception e) {
publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_DISCOUNT.getEventName(), EventReportEnum.SEARCHCONTROLLER_DISCOUNT.getFunctionName(),
EventReportEnum.SEARCHCONTROLLER_DISCOUNT.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
return SearchApiResultUtils.errorSearchApiResult("discount", paramMap, e);
}
}
public JSONObject discount(Map<String, String> paramMap, BoolQueryBuilder mustFilter) {
try {
logger.info("[func=discount][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
// 构造查询参数
SearchParam searchParam = searchParamHelper.buildWithMustFilter(paramMap, mustFilter);
// 按1-3,4-6,7-10折的规则进行聚合[按区间聚合]
IAggregation discountAggregation = aggregationFactoryService.getDiscountAggregation();
searchParam.setAggregationBuilders(Arrays.asList(discountAggregation.getBuilder()));
searchParam.setSize(0);
// 先从缓存中获取,如果能取到,则直接返回
JSONObject cacheObject = searchCacheService.getJSONObjectFromCache(this.searchCache, ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
if (cacheObject != null) {
return cacheObject.getJSONObject("discount");
}
// es检索
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
if (searchResult == null || searchResult.getAggMaps() == null) {
return null;
}
Object discountAggResult = discountAggregation.getAggregationResponseMap(searchResult.getAggMaps());
if (discountAggResult == null) {
return null;
}
JSONObject discountObject = new JSONObject();
discountObject.put("discount", discountAggResult);
searchCacheService.addJSONObjectToCache(this.searchCache, ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam, discountObject);
return discountObject.getJSONObject("discount");
} catch (Exception e) {
publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_DISCOUNT.getEventName(), EventReportEnum.SEARCHCONTROLLER_DISCOUNT.getFunctionName(),
EventReportEnum.SEARCHCONTROLLER_DISCOUNT.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
return null;
}
}
}
package com.yoho.search.service.aggregations.service;
import java.util.Arrays;
import java.util.Map;
import com.yoho.error.event.SearchEvent;
import com.yoho.search.base.utils.EventReportEnum;
import com.yoho.search.base.utils.ISearchConstants;
import com.yoho.search.cache.beans.AbstractCacheAbleService;
import com.yoho.search.cache.model.SearchCache;
import com.yoho.search.common.utils.SearchApiResultUtils;
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.impls.AggregationFactoryService;
import com.yoho.search.service.base.SearchCommonService;
import com.yoho.search.service.helper.SearchAfterCacheHelper;
import com.yoho.search.service.helper.SearchParamHelper;
import org.elasticsearch.index.query.BoolQueryBuilder;
import com.alibaba.fastjson.JSONObject;
import com.yoho.search.models.SearchApiResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
@Service
public class DiscountService extends AbstractCacheAbleService implements ApplicationEventPublisherAware {
private static final Logger logger = LoggerFactory.getLogger(DiscountService.class);
@Autowired
private SearchParamHelper searchParamHelper;
@Autowired
private AggregationFactoryService aggregationFactoryService;
@Autowired
private SearchCommonService searchCommonService;
@Autowired
private SearchAfterCacheHelper searchAfterCacheService;
@Override
public SearchCache getSearchCache() {
return searchCacheFactory.getAggregationSearchCache();
}
private ApplicationEventPublisher publisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
public SearchApiResult discount(Map<String, String> paramMap) {
try {
logger.info("[func=discount][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
// 构造查询参数
SearchParam searchParam = searchParamHelper.buildDefault(paramMap);
// 按1-3,4-6,7-10折的规则进行聚合[按区间聚合]
IAggregation discountAggregation = aggregationFactoryService.getDiscountAggregation();
searchParam.setAggregationBuilders(Arrays.asList(discountAggregation.getBuilder()));
searchParam.setSize(0);
// 构造返回结果
SearchApiResult searchApiResult = new SearchApiResult().setMessage("discount List.");
// 先从缓存中获取,如果能取到,则直接返回
JSONObject cacheObject = searchCacheService.getJSONObjectFromCache(this.searchCache, ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
if (cacheObject != null) {
Object result = searchAfterCacheService.dealDiscountCacheObject(cacheObject);
searchApiResult.setData(result);
return searchApiResult;
}
// es检索
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
if (searchResult == null || searchResult.getAggMaps() == null) {
return searchApiResult.setData("");
}
Object discountAggResult = discountAggregation.getAggregationResponseMap(searchResult.getAggMaps());
if (discountAggResult == null) {
return searchApiResult.setData("");
}
JSONObject discountObject = new JSONObject();
discountObject.put("discount", discountAggResult);
searchCacheService.addJSONObjectToCache(this.searchCache, ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam, discountObject);
return searchApiResult.setData(discountObject);
} catch (Exception e) {
publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_DISCOUNT.getEventName(), EventReportEnum.SEARCHCONTROLLER_DISCOUNT.getFunctionName(),
EventReportEnum.SEARCHCONTROLLER_DISCOUNT.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
return SearchApiResultUtils.errorSearchApiResult("discount", paramMap, e);
}
}
public JSONObject discount(Map<String, String> paramMap, BoolQueryBuilder mustFilter) {
try {
logger.info("[func=discount][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
// 构造查询参数
SearchParam searchParam = searchParamHelper.buildWithMustFilter(paramMap, mustFilter);
// 按1-3,4-6,7-10折的规则进行聚合[按区间聚合]
IAggregation discountAggregation = aggregationFactoryService.getDiscountAggregation();
searchParam.setAggregationBuilders(Arrays.asList(discountAggregation.getBuilder()));
searchParam.setSize(0);
// 先从缓存中获取,如果能取到,则直接返回
JSONObject cacheObject = searchCacheService.getJSONObjectFromCache(this.searchCache, ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
if (cacheObject != null) {
return cacheObject.getJSONObject("discount");
}
// es检索
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
if (searchResult == null || searchResult.getAggMaps() == null) {
return null;
}
Object discountAggResult = discountAggregation.getAggregationResponseMap(searchResult.getAggMaps());
if (discountAggResult == null) {
return null;
}
JSONObject discountObject = new JSONObject();
discountObject.put("discount", discountAggResult);
searchCacheService.addJSONObjectToCache(this.searchCache, ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam, discountObject);
return discountObject.getJSONObject("discount");
} catch (Exception e) {
publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_DISCOUNT.getEventName(), EventReportEnum.SEARCHCONTROLLER_DISCOUNT.getFunctionName(),
EventReportEnum.SEARCHCONTROLLER_DISCOUNT.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
return null;
}
}
}
... ...
package com.yoho.search.service.service;
import java.util.Arrays;
import java.util.Map;
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.cache.beans.AbstractCacheAbleService;
import com.yoho.search.cache.log.SearchCacheMatchLogger;
import com.yoho.search.cache.model.SearchCache;
import com.yoho.search.common.utils.SearchApiResultUtils;
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.models.SearchApiResult;
import com.yoho.search.service.aggregations.impls.AggregationFactoryService;
import com.yoho.search.service.base.SearchCommonService;
import com.yoho.search.service.helper.SearchAfterCacheHelper;
import com.yoho.search.service.helper.SearchParamHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
@Service
public class RecentService extends AbstractCacheAbleService implements ApplicationEventPublisherAware {
private static final Logger logger = LoggerFactory.getLogger(RecentService.class);
@Autowired
private AggregationFactoryService aggregationFactoryService;
@Autowired
private SearchCommonService searchCommonService;
@Autowired
private SearchAfterCacheHelper searchAfterCacheService;
@Autowired
private SearchParamHelper searchParamHelper;
@Override
public SearchCache getSearchCache() {
return searchCacheFactory.getAggregationSearchCache();
}
private ApplicationEventPublisher publisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
public SearchApiResult recent(Map<String, String> paramMap) {
try {
logger.info("[func=recent][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
// 构造查询参数
SearchParam searchParam = searchParamHelper.buildDefault(paramMap);
// 构造聚合参数
IAggregation recentShelveDayAggregation = aggregationFactoryService.getRecentShelveDayAggregation();
searchParam.setAggregationBuilders(Arrays.asList(recentShelveDayAggregation.getBuilder()));
searchParam.setSize(0);
// 构造返回结果
SearchApiResult searchApiResult = new SearchApiResult().setMessage("recentShelveDay List.");
// 先从缓存中获取,如果能取到,则直接返回
JSONObject cacheObject = searchCacheService.getJSONObjectFromCache(this.searchCache, ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
if (cacheObject != null) {
Object result = searchAfterCacheService.dealRecentCacheObject(cacheObject);
searchApiResult.setData(result);
SearchCacheMatchLogger.doSearchCacheMatchLog("/recent.json", paramMap);
return searchApiResult;
}
// 进行检索
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
if (searchResult == null) {
return searchApiResult.setData("");
}
// 获取聚合结果
Object recentShelveDayResponse = recentShelveDayAggregation.getAggregationResponseMap(searchResult.getAggMaps());
if (recentShelveDayResponse == null) {
return searchApiResult.setData("");
}
JSONObject jsonObject = new JSONObject();
jsonObject.put("recent", recentShelveDayResponse);
searchCacheService.addJSONObjectToCache(this.searchCache, ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam, jsonObject);
return searchApiResult.setData(jsonObject);
} catch (Exception e) {
publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_RECENT.getEventName(), EventReportEnum.SEARCHCONTROLLER_RECENT.getFunctionName(),
EventReportEnum.SEARCHCONTROLLER_RECENT.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
return SearchApiResultUtils.errorSearchApiResult("recent", paramMap, e);
}
}
}
package com.yoho.search.service.aggregations.service;
import java.util.Arrays;
import java.util.Map;
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.cache.beans.AbstractCacheAbleService;
import com.yoho.search.cache.log.SearchCacheMatchLogger;
import com.yoho.search.cache.model.SearchCache;
import com.yoho.search.common.utils.SearchApiResultUtils;
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.models.SearchApiResult;
import com.yoho.search.service.aggregations.impls.AggregationFactoryService;
import com.yoho.search.service.base.SearchCommonService;
import com.yoho.search.service.helper.SearchAfterCacheHelper;
import com.yoho.search.service.helper.SearchParamHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
@Service
public class RecentService extends AbstractCacheAbleService implements ApplicationEventPublisherAware {
private static final Logger logger = LoggerFactory.getLogger(RecentService.class);
@Autowired
private AggregationFactoryService aggregationFactoryService;
@Autowired
private SearchCommonService searchCommonService;
@Autowired
private SearchAfterCacheHelper searchAfterCacheService;
@Autowired
private SearchParamHelper searchParamHelper;
@Override
public SearchCache getSearchCache() {
return searchCacheFactory.getAggregationSearchCache();
}
private ApplicationEventPublisher publisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
public SearchApiResult recent(Map<String, String> paramMap) {
try {
logger.info("[func=recent][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
// 构造查询参数
SearchParam searchParam = searchParamHelper.buildDefault(paramMap);
// 构造聚合参数
IAggregation recentShelveDayAggregation = aggregationFactoryService.getRecentShelveDayAggregation();
searchParam.setAggregationBuilders(Arrays.asList(recentShelveDayAggregation.getBuilder()));
searchParam.setSize(0);
// 构造返回结果
SearchApiResult searchApiResult = new SearchApiResult().setMessage("recentShelveDay List.");
// 先从缓存中获取,如果能取到,则直接返回
JSONObject cacheObject = searchCacheService.getJSONObjectFromCache(this.searchCache, ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
if (cacheObject != null) {
Object result = searchAfterCacheService.dealRecentCacheObject(cacheObject);
searchApiResult.setData(result);
SearchCacheMatchLogger.doSearchCacheMatchLog("/recent.json", paramMap);
return searchApiResult;
}
// 进行检索
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
if (searchResult == null) {
return searchApiResult.setData("");
}
// 获取聚合结果
Object recentShelveDayResponse = recentShelveDayAggregation.getAggregationResponseMap(searchResult.getAggMaps());
if (recentShelveDayResponse == null) {
return searchApiResult.setData("");
}
JSONObject jsonObject = new JSONObject();
jsonObject.put("recent", recentShelveDayResponse);
searchCacheService.addJSONObjectToCache(this.searchCache, ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam, jsonObject);
return searchApiResult.setData(jsonObject);
} catch (Exception e) {
publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_RECENT.getEventName(), EventReportEnum.SEARCHCONTROLLER_RECENT.getFunctionName(),
EventReportEnum.SEARCHCONTROLLER_RECENT.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
return SearchApiResultUtils.errorSearchApiResult("recent", paramMap, e);
}
}
}
... ...
package com.yoho.search.service.service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
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.base.utils.ProductIndexEsField;
import com.yoho.search.cache.beans.AbstractCacheAbleService;
import com.yoho.search.cache.model.SearchCache;
import com.yoho.search.common.utils.HttpServletRequestUtils;
import com.yoho.search.common.utils.SearchApiResultUtils;
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.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 org.elasticsearch.index.query.BoolQueryBuilder;
import com.alibaba.fastjson.JSONArray;
import com.yoho.search.models.SearchApiResult;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
@Service
public class SearchSortGroupService extends AbstractCacheAbleService implements ApplicationEventPublisherAware {
private static Logger logger = LoggerFactory.getLogger(SearchSortGroupService.class);
private static Logger CACHE_MATCH_REQUEST = LoggerFactory.getLogger("CACHE_MATCH_REQUEST");
@Autowired
private SearchCommonHelper searchCommonHelper;
@Autowired
private SearchCommonService searchCommonService;
@Autowired
private AggregationFactoryService aggregationFactoryService;
@Autowired
private SearchParamHelper searchParamHelper;
@Override
public SearchCache getSearchCache() {
return searchCacheFactory.getAggregationSearchCache();
}
ApplicationEventPublisher publisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
/**
* 对分类进行分组查询
*
* @needAllSort=1时过滤条件status和gender生效
* @否则其他参数也会生效
* @param paramMap
* @return
* @throws Exception
*/
public SearchApiResult sortGroup(Map<String, String> paramMap) {
try {
long begin = System.currentTimeMillis();
logger.info("[model=SearchSortGroupService][func=sortGroup][param={}][begin={}]", paramMap.toString(), begin);
// 如果包含参数needAllSort=1
SearchParam searchParam = new SearchParam();
if (!paramMap.containsKey("needAllSort") || !"1".equals(paramMap.get("needAllSort"))) {
searchParam = searchParamHelper.buildDefault(paramMap);
} else {
// needAllSort=1时过滤条件只有status和gender生效
searchParam.setQuery(QueryBuilders.matchAllQuery());
BoolQueryBuilder boolFilter = QueryBuilders.boolQuery();
if (paramMap.containsKey(SearchRequestParams.PARAM_SEARCH_STATUS)) {
boolFilter.must(QueryBuilders.termQuery(SearchRequestParams.PARAM_SEARCH_STATUS, paramMap.get(SearchRequestParams.PARAM_SEARCH_STATUS)));
}
// 性别
if (paramMap.containsKey(SearchRequestParams.PARAM_SEARCH_GENDER)) {
String[] genders = paramMap.get(SearchRequestParams.PARAM_SEARCH_GENDER).split(",");
boolFilter.must(QueryBuilders.termsQuery(ProductIndexEsField.gender, genders));
}
// 如果contain_global!=Y,则过滤掉全球购的商品[全球购商品融合需求]
if (!searchCommonHelper.containGlobal(paramMap)) {
boolFilter.mustNot(QueryBuilders.termQuery(ProductIndexEsField.isGlobal, "Y"));
}
if (boolFilter.hasClauses()) {
searchParam.setFiter(boolFilter);
}
}
// 构造聚合条件
List<AbstractAggregationBuilder<?>> sortGroupBuilders = new ArrayList<AbstractAggregationBuilder<?>>();
IAggregation sortGroupAggregation = aggregationFactoryService.getSortGroupAggregation(paramMap);
sortGroupBuilders.add(sortGroupAggregation.getBuilder());
searchParam.setAggregationBuilders(sortGroupBuilders);
// 设置查询结果
searchParam.setOffset(1);// just for cache
searchParam.setSize(0);
// 构造返回结果
SearchApiResult searchApiResult = new SearchApiResult();
searchApiResult.setCode(200);
searchApiResult.setMessage("sort List.");
// 先从缓存中获取,如果能取到,则直接返回
JSONObject cacheObject = searchCacheService.getJSONObjectFromCache(this.searchCache, ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
if (cacheObject != null) {
searchApiResult.setData(cacheObject);
CACHE_MATCH_REQUEST.info("match cache , url is :/sortgroup.json?" + HttpServletRequestUtils.genParamString(paramMap));
return searchApiResult;
}
// 进行检索
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
if (searchResult == null || searchResult.getAggMaps() == null || !searchResult.getAggMaps().containsKey("maxAgg")) {
searchApiResult.setData("");
return searchApiResult;
}
// 获取品类聚合结果
JSONArray sortGroups = (JSONArray) sortGroupAggregation.getAggregationResponseMap(searchResult.getAggMaps());
if (sortGroups == null) {
searchApiResult.setData("");
return searchApiResult;
}
// 构造data并加入缓存
JSONObject sortResult = new JSONObject();
sortResult.put("sort", sortGroups);
searchCacheService.addJSONObjectToCache(this.searchCache, indexName, searchParam, sortResult);
return searchApiResult.setData(sortResult);
} catch (Exception e) {
publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_SORTGROUP.getEventName(), EventReportEnum.SEARCHCONTROLLER_SORTGROUP.getFunctionName(),
EventReportEnum.SEARCHCONTROLLER_SORTGROUP.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
return SearchApiResultUtils.errorSearchApiResult("sortGroup", paramMap, e);
}
}
public JSONArray sortGroup(Map<String, String> paramMap, BoolQueryBuilder mustFilter) {
try {
long begin = System.currentTimeMillis();
logger.info("[model=SearchSortGroupService][func=sortGroup][param={}][begin={}]", paramMap.toString(), begin);
SearchParam searchParam = searchParamHelper.buildWithMustFilter(paramMap, mustFilter);
// 构造聚合条件
List<AbstractAggregationBuilder<?>> sortGroupBuilders = new ArrayList<AbstractAggregationBuilder<?>>();
IAggregation sortGroupAggregation = aggregationFactoryService.getSortGroupAggregation(paramMap);
sortGroupBuilders.add(sortGroupAggregation.getBuilder());
searchParam.setAggregationBuilders(sortGroupBuilders);
// 设置返回结果为0
searchParam.setSize(0);
// 先从缓存中获取,如果能取到,则直接返回
JSONObject cacheObject = searchCacheService.getJSONObjectFromCache(this.searchCache, ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
if (cacheObject != null) {
return cacheObject.getJSONArray("sort");
}
// 进行检索
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
if (searchResult == null || searchResult.getAggMaps() == null || !searchResult.getAggMaps().containsKey("maxAgg")) {
return new JSONArray();
}
// 获取品类聚合结果
JSONArray sortGroups = (JSONArray) sortGroupAggregation.getAggregationResponseMap(searchResult.getAggMaps());
if (sortGroups == null) {
return new JSONArray();
}
JSONObject sortResult = new JSONObject();
sortResult.put("sort", sortGroups);
searchCacheService.addJSONObjectToCache(this.searchCache, indexName, searchParam, sortResult);
return sortGroups;
} catch (Exception e) {
publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_SORTGROUP.getEventName(), EventReportEnum.SEARCHCONTROLLER_SORTGROUP.getFunctionName(),
EventReportEnum.SEARCHCONTROLLER_SORTGROUP.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
return new JSONArray();
}
}
}
package com.yoho.search.service.aggregations.service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
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.base.utils.ProductIndexEsField;
import com.yoho.search.cache.beans.AbstractCacheAbleService;
import com.yoho.search.cache.model.SearchCache;
import com.yoho.search.common.utils.HttpServletRequestUtils;
import com.yoho.search.common.utils.SearchApiResultUtils;
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.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 org.elasticsearch.index.query.BoolQueryBuilder;
import com.alibaba.fastjson.JSONArray;
import com.yoho.search.models.SearchApiResult;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
@Service
public class SearchSortGroupService extends AbstractCacheAbleService implements ApplicationEventPublisherAware {
private static Logger logger = LoggerFactory.getLogger(SearchSortGroupService.class);
private static Logger CACHE_MATCH_REQUEST = LoggerFactory.getLogger("CACHE_MATCH_REQUEST");
@Autowired
private SearchCommonHelper searchCommonHelper;
@Autowired
private SearchCommonService searchCommonService;
@Autowired
private AggregationFactoryService aggregationFactoryService;
@Autowired
private SearchParamHelper searchParamHelper;
@Override
public SearchCache getSearchCache() {
return searchCacheFactory.getAggregationSearchCache();
}
ApplicationEventPublisher publisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
/**
* 对分类进行分组查询
*
* @needAllSort=1时过滤条件status和gender生效
* @否则其他参数也会生效
* @param paramMap
* @return
* @throws Exception
*/
public SearchApiResult sortGroup(Map<String, String> paramMap) {
try {
long begin = System.currentTimeMillis();
logger.info("[model=SearchSortGroupService][func=sortGroup][param={}][begin={}]", paramMap.toString(), begin);
// 如果包含参数needAllSort=1
SearchParam searchParam = new SearchParam();
if (!paramMap.containsKey("needAllSort") || !"1".equals(paramMap.get("needAllSort"))) {
searchParam = searchParamHelper.buildDefault(paramMap);
} else {
// needAllSort=1时过滤条件只有status和gender生效
searchParam.setQuery(QueryBuilders.matchAllQuery());
BoolQueryBuilder boolFilter = QueryBuilders.boolQuery();
if (paramMap.containsKey(SearchRequestParams.PARAM_SEARCH_STATUS)) {
boolFilter.must(QueryBuilders.termQuery(SearchRequestParams.PARAM_SEARCH_STATUS, paramMap.get(SearchRequestParams.PARAM_SEARCH_STATUS)));
}
// 性别
if (paramMap.containsKey(SearchRequestParams.PARAM_SEARCH_GENDER)) {
String[] genders = paramMap.get(SearchRequestParams.PARAM_SEARCH_GENDER).split(",");
boolFilter.must(QueryBuilders.termsQuery(ProductIndexEsField.gender, genders));
}
// 如果contain_global!=Y,则过滤掉全球购的商品[全球购商品融合需求]
if (!searchCommonHelper.containGlobal(paramMap)) {
boolFilter.mustNot(QueryBuilders.termQuery(ProductIndexEsField.isGlobal, "Y"));
}
if (boolFilter.hasClauses()) {
searchParam.setFiter(boolFilter);
}
}
// 构造聚合条件
List<AbstractAggregationBuilder<?>> sortGroupBuilders = new ArrayList<AbstractAggregationBuilder<?>>();
IAggregation sortGroupAggregation = aggregationFactoryService.getSortGroupAggregation(paramMap);
sortGroupBuilders.add(sortGroupAggregation.getBuilder());
searchParam.setAggregationBuilders(sortGroupBuilders);
// 设置查询结果
searchParam.setOffset(1);// just for cache
searchParam.setSize(0);
// 构造返回结果
SearchApiResult searchApiResult = new SearchApiResult();
searchApiResult.setCode(200);
searchApiResult.setMessage("sort List.");
// 先从缓存中获取,如果能取到,则直接返回
JSONObject cacheObject = searchCacheService.getJSONObjectFromCache(this.searchCache, ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
if (cacheObject != null) {
searchApiResult.setData(cacheObject);
CACHE_MATCH_REQUEST.info("match cache , url is :/sortgroup.json?" + HttpServletRequestUtils.genParamString(paramMap));
return searchApiResult;
}
// 进行检索
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
if (searchResult == null || searchResult.getAggMaps() == null || !searchResult.getAggMaps().containsKey("maxAgg")) {
searchApiResult.setData("");
return searchApiResult;
}
// 获取品类聚合结果
JSONArray sortGroups = (JSONArray) sortGroupAggregation.getAggregationResponseMap(searchResult.getAggMaps());
if (sortGroups == null) {
searchApiResult.setData("");
return searchApiResult;
}
// 构造data并加入缓存
JSONObject sortResult = new JSONObject();
sortResult.put("sort", sortGroups);
searchCacheService.addJSONObjectToCache(this.searchCache, indexName, searchParam, sortResult);
return searchApiResult.setData(sortResult);
} catch (Exception e) {
publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_SORTGROUP.getEventName(), EventReportEnum.SEARCHCONTROLLER_SORTGROUP.getFunctionName(),
EventReportEnum.SEARCHCONTROLLER_SORTGROUP.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
return SearchApiResultUtils.errorSearchApiResult("sortGroup", paramMap, e);
}
}
public JSONArray sortGroup(Map<String, String> paramMap, BoolQueryBuilder mustFilter) {
try {
long begin = System.currentTimeMillis();
logger.info("[model=SearchSortGroupService][func=sortGroup][param={}][begin={}]", paramMap.toString(), begin);
SearchParam searchParam = searchParamHelper.buildWithMustFilter(paramMap, mustFilter);
// 构造聚合条件
List<AbstractAggregationBuilder<?>> sortGroupBuilders = new ArrayList<AbstractAggregationBuilder<?>>();
IAggregation sortGroupAggregation = aggregationFactoryService.getSortGroupAggregation(paramMap);
sortGroupBuilders.add(sortGroupAggregation.getBuilder());
searchParam.setAggregationBuilders(sortGroupBuilders);
// 设置返回结果为0
searchParam.setSize(0);
// 先从缓存中获取,如果能取到,则直接返回
JSONObject cacheObject = searchCacheService.getJSONObjectFromCache(this.searchCache, ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
if (cacheObject != null) {
return cacheObject.getJSONArray("sort");
}
// 进行检索
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
if (searchResult == null || searchResult.getAggMaps() == null || !searchResult.getAggMaps().containsKey("maxAgg")) {
return new JSONArray();
}
// 获取品类聚合结果
JSONArray sortGroups = (JSONArray) sortGroupAggregation.getAggregationResponseMap(searchResult.getAggMaps());
if (sortGroups == null) {
return new JSONArray();
}
JSONObject sortResult = new JSONObject();
sortResult.put("sort", sortGroups);
searchCacheService.addJSONObjectToCache(this.searchCache, indexName, searchParam, sortResult);
return sortGroups;
} catch (Exception e) {
publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_SORTGROUP.getEventName(), EventReportEnum.SEARCHCONTROLLER_SORTGROUP.getFunctionName(),
EventReportEnum.SEARCHCONTROLLER_SORTGROUP.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
return new JSONArray();
}
}
}
... ...
... ... @@ -5,7 +5,7 @@ import com.yoho.search.base.utils.SearchPageIdDefine;
import com.yoho.search.models.SearchApiResult;
import com.yoho.search.service.base.SearchRequestParams;
import com.yoho.search.service.list.ProductListSwitchService;
import com.yoho.search.service.scene.aggregations.SceneAggregationsHelper;
import com.yoho.search.service.aggregations.SceneAggregationsHelper;
import com.yoho.search.service.scene.common.AbstractSceneService;
import com.yoho.search.service.scene.common.SceneRecommendBrandsService;
import com.yoho.search.service.scene.common.SceneSelectionsService;
... ...
... ... @@ -10,9 +10,9 @@ import com.yoho.search.core.es.model.SearchResult;
import com.yoho.search.recall.beans.builder.UserRecallRequestBuilder;
import com.yoho.search.recall.models.common.ParamQueryFilter;
import com.yoho.search.service.base.SearchCommonService;
import com.yoho.search.service.helper.AggCommonHelper;
import com.yoho.search.service.helper.AggKeyCount;
import com.yoho.search.service.helper.AggKeyCountTwoLevel;
import com.yoho.search.service.aggregations.AggCommonHelper;
import com.yoho.search.service.aggregations.models.AggKeyCount;
import com.yoho.search.service.aggregations.models.AggKeyCountTwoLevel;
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
... ...
package com.yoho.search.service.scene;
import com.alibaba.fastjson.JSONObject;
import com.yoho.search.base.utils.SearchPageIdDefine;
import com.yoho.search.common.utils.SearchApiResultUtils;
import com.yoho.search.models.SearchApiResult;
import com.yoho.search.service.base.SearchDynamicConfigService;
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.ProductListSwitchService;
import com.yoho.search.service.scene.aggregations.SceneAggregationsHelper;
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 com.yoho.search.service.service.SearchRecommendService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@Service
public class FuzzySceneService extends AbstractSceneService {
private static final Logger logger = LoggerFactory.getLogger(FuzzySceneService.class);
@Autowired
private SceneSelectionsService sceneSelectionsService;
@Autowired
private SearchCommonHelper searchCommonHelper;
@Autowired
private SearchRecommendService searchRecommendService;
@Autowired
private SearchDynamicConfigService searchDynamicConfigService;
@Autowired
private SearchKeyWordHelper searchKeyWordService;
@Autowired
private SceneAggregationsHelper sceneAggregationsHelper;
@Autowired
private SceneRecommendBrandsService sceneRecommendBrandsService;
@Autowired
private ProductListSwitchService productListSwitchService;
private ExecutorService executor = Executors.newFixedThreadPool(100);
// 当少于20个商品时 返回智能搜索词提示
private static final int SMART_SUGGESTION_PRODUCT_LIMIT = 20;
@Override
public String pageId() {
return SearchPageIdDefine.PAGE_ID_SEARCH;
}
@Override
public void addParamsToParamMap(Map<String, String> paramMap) {
super.addDefaultParamsToParamMap(paramMap);
paramMap.put(SearchRequestParams.PARAM_SEARCH_CONTAIN_GLOBAL, "Y");// 包含全球购
paramMap.put(SearchRequestParams.PARAM_SEARCH_NEED_SUGGESTION, "Y");// 返回建议词
}
/**
* @1、返回商品列表
* @2、数量太多则返回建议词
*/
@Override
public SearchApiResult productList(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、获取商品列表
CompletableFuture<SearchApiResult> productListuture = CompletableFuture.supplyAsync(() -> productListSwitchService.fuzzyProductList(this.newParamMap(paramMap)), executor);
// 4、获取自定义标签聚合结果
CompletableFuture<SearchApiResult> customizeTagFuture = CompletableFuture.supplyAsync(() -> sceneAggregationsHelper.sceneAggCustomizeTag(this.newParamMap(paramMap)), executor);
// 5、获取促销专题
CompletableFuture<SearchApiResult> promotionsFuture = CompletableFuture.supplyAsync(() -> sceneAggregationsHelper.sceneAggPromotion(this.newParamMap(paramMap)),
executor);
// 6、加入建议词
SearchApiResult productListResult = productListuture.get();
this.addSuggestion(productListResult, 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);
}
// 8、组合结果
SearchApiResult customizeTags = customizeTagFuture.get();
SearchApiResult promotions = promotionsFuture.get();
JSONObject dataMap = (JSONObject) productListResult.getData();
dataMap.put(CUSTOMIZE_TAG_LIST, customizeTags.getData());
dataMap.put(RECOMMEND_PROMOTION_LIST, sceneAggregationsHelper.subRecommendPromotions(promotions.getData(),this.getPage(paramMap),1));
return productListResult;
} catch (Exception e) {
logger.error(e.getMessage(), e);
return SearchApiResultUtils.errorSearchApiResult("fuzzyProductList", paramMap, e);
}
}
@Override
public SearchApiResult aggregations(Map<String, String> paramMap) {
try {
// 0、参数校验
if (StringUtils.isBlank(paramMap.get(SearchRequestParams.PARAM_SEARCH_QUERY))) {
return new SearchApiResult().setCode(400).setMessage("请传query参数");
}
// 1、添加默认参数
this.addParamsToParamMap(paramMap);
// 2、返回聚合结果
SearchApiResult result = sceneSelectionsService.aggregations(paramMap);
sceneRecommendBrandsService.getRecommendBrands(paramMap, result);
return result;
} catch (Exception e) {
logger.error(e.getMessage(), e);
return new SearchApiResult().setData(null).setMessage("FuzzyAggregations Exception").setCode(500);
}
}
/**
* 获取模糊搜索的推荐词
*
* @param paramMap
* @return
*/
public void addSuggestion(SearchApiResult searchResult, Map<String, String> paramMap) {
if (searchResult == null || searchResult.getCode() != 200 || searchResult.getData() == null) {
return;
}
// 1. 判断是否需要进行term推荐
// 1.1 query不为空
String queryWord = paramMap.get(SearchRequestParams.PARAM_SEARCH_QUERY);
if (StringUtils.isEmpty(queryWord) || (queryWord.length() > 30 && !searchCommonHelper.isQuerySknOrSku(queryWord))) {
return;
}
// 1.2不是第一页直接不返回
int page = this.getPage(paramMap);
if (page != 1) {
return;
}
// 1.3请求制定需要返回term推荐
if (!"Y".equalsIgnoreCase(paramMap.get(SearchRequestParams.PARAM_SEARCH_NEED_SUGGESTION))) {
return;
}
// 1.4打开智能推荐全局开关
if (!searchDynamicConfigService.isSearchSuggestionTipsOpen()) {
return;
}
// 1.5 搜索的数量小于20条
JSONObject dataMap = ((JSONObject) searchResult.getData());
if (dataMap.getIntValue("total") >= SMART_SUGGESTION_PRODUCT_LIMIT) {
return;
}
// 1.6加入推荐词
dataMap.put("suggestion", searchRecommendService.recommend(searchResult, paramMap));
}
}
package com.yoho.search.service.scene.fuzzy;
import com.alibaba.fastjson.JSONObject;
import com.yoho.search.base.utils.SearchPageIdDefine;
import com.yoho.search.common.utils.SearchApiResultUtils;
import com.yoho.search.models.SearchApiResult;
import com.yoho.search.service.base.SearchDynamicConfigService;
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.ProductListSwitchService;
import com.yoho.search.service.aggregations.SceneAggregationsHelper;
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.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@Service
public class FuzzySceneService extends AbstractSceneService {
private static final Logger logger = LoggerFactory.getLogger(FuzzySceneService.class);
@Autowired
private SceneSelectionsService sceneSelectionsService;
@Autowired
private SearchCommonHelper searchCommonHelper;
@Autowired
private SearchRecommendService searchRecommendService;
@Autowired
private SearchDynamicConfigService searchDynamicConfigService;
@Autowired
private SearchKeyWordHelper searchKeyWordService;
@Autowired
private SceneAggregationsHelper sceneAggregationsHelper;
@Autowired
private SceneRecommendBrandsService sceneRecommendBrandsService;
@Autowired
private ProductListSwitchService productListSwitchService;
private ExecutorService executor = Executors.newFixedThreadPool(100);
// 当少于20个商品时 返回智能搜索词提示
private static final int SMART_SUGGESTION_PRODUCT_LIMIT = 20;
@Override
public String pageId() {
return SearchPageIdDefine.PAGE_ID_SEARCH;
}
@Override
public void addParamsToParamMap(Map<String, String> paramMap) {
super.addDefaultParamsToParamMap(paramMap);
paramMap.put(SearchRequestParams.PARAM_SEARCH_CONTAIN_GLOBAL, "Y");// 包含全球购
paramMap.put(SearchRequestParams.PARAM_SEARCH_NEED_SUGGESTION, "Y");// 返回建议词
}
/**
* @1、返回商品列表
* @2、数量太多则返回建议词
*/
@Override
public SearchApiResult productList(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、获取商品列表
CompletableFuture<SearchApiResult> productListuture = CompletableFuture.supplyAsync(() -> productListSwitchService.fuzzyProductList(this.newParamMap(paramMap)), executor);
// 4、获取自定义标签聚合结果
CompletableFuture<SearchApiResult> customizeTagFuture = CompletableFuture.supplyAsync(() -> sceneAggregationsHelper.sceneAggCustomizeTag(this.newParamMap(paramMap)), executor);
// 5、获取促销专题
CompletableFuture<SearchApiResult> promotionsFuture = CompletableFuture.supplyAsync(() -> sceneAggregationsHelper.sceneAggPromotion(this.newParamMap(paramMap)),
executor);
// 6、加入建议词
SearchApiResult productListResult = productListuture.get();
this.addSuggestion(productListResult, 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);
}
// 8、组合结果
SearchApiResult customizeTags = customizeTagFuture.get();
SearchApiResult promotions = promotionsFuture.get();
JSONObject dataMap = (JSONObject) productListResult.getData();
dataMap.put(CUSTOMIZE_TAG_LIST, customizeTags.getData());
dataMap.put(RECOMMEND_PROMOTION_LIST, sceneAggregationsHelper.subRecommendPromotions(promotions.getData(),this.getPage(paramMap),1));
return productListResult;
} catch (Exception e) {
logger.error(e.getMessage(), e);
return SearchApiResultUtils.errorSearchApiResult("fuzzyProductList", paramMap, e);
}
}
@Override
public SearchApiResult aggregations(Map<String, String> paramMap) {
try {
// 0、参数校验
if (StringUtils.isBlank(paramMap.get(SearchRequestParams.PARAM_SEARCH_QUERY))) {
return new SearchApiResult().setCode(400).setMessage("请传query参数");
}
// 1、添加默认参数
this.addParamsToParamMap(paramMap);
// 2、返回聚合结果
SearchApiResult result = sceneSelectionsService.aggregations(paramMap);
sceneRecommendBrandsService.getRecommendBrands(paramMap, result);
return result;
} catch (Exception e) {
logger.error(e.getMessage(), e);
return new SearchApiResult().setData(null).setMessage("FuzzyAggregations Exception").setCode(500);
}
}
/**
* 获取模糊搜索的推荐词
*
* @param paramMap
* @return
*/
public void addSuggestion(SearchApiResult searchResult, Map<String, String> paramMap) {
if (searchResult == null || searchResult.getCode() != 200 || searchResult.getData() == null) {
return;
}
// 1. 判断是否需要进行term推荐
// 1.1 query不为空
String queryWord = paramMap.get(SearchRequestParams.PARAM_SEARCH_QUERY);
if (StringUtils.isEmpty(queryWord) || (queryWord.length() > 30 && !searchCommonHelper.isQuerySknOrSku(queryWord))) {
return;
}
// 1.2不是第一页直接不返回
int page = this.getPage(paramMap);
if (page != 1) {
return;
}
// 1.3请求制定需要返回term推荐
if (!"Y".equalsIgnoreCase(paramMap.get(SearchRequestParams.PARAM_SEARCH_NEED_SUGGESTION))) {
return;
}
// 1.4打开智能推荐全局开关
if (!searchDynamicConfigService.isSearchSuggestionTipsOpen()) {
return;
}
// 1.5 搜索的数量小于20条
JSONObject dataMap = ((JSONObject) searchResult.getData());
if (dataMap.getIntValue("total") >= SMART_SUGGESTION_PRODUCT_LIMIT) {
return;
}
// 1.6加入推荐词
dataMap.put("suggestion", searchRecommendService.recommend(searchResult, paramMap));
}
}
... ...