...
|
...
|
@@ -29,187 +29,186 @@ import com.yoho.search.service.aggregations.common.SimpleFieldAgg; |
|
|
|
|
|
public class AggCommonHelper {
|
|
|
|
|
|
private static final Logger logger = LoggerFactory.getLogger(AggCommonHelper.class);
|
|
|
|
|
|
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 topHitFieldCount
|
|
|
* @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;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 获取聚合出来的商品列表,并按特定顺序截取
|
|
|
*
|
|
|
* @param aggregation
|
|
|
* @param viewNum
|
|
|
* @param sortField
|
|
|
* @param sortOrder
|
|
|
* @return
|
|
|
*/
|
|
|
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");
|
|
|
if (topHits != null) {
|
|
|
SearchHits hits = topHits.getHits();
|
|
|
for (SearchHit hit : hits.getHits()) {
|
|
|
Map<String, Object> source = hit.getSource();
|
|
|
float _score = hit.getScore();
|
|
|
source.put("_score", _score);
|
|
|
results.add(source);
|
|
|
}
|
|
|
}
|
|
|
} 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<Map<String, Object>>();
|
|
|
}
|
|
|
// 再按照某个字段对商品排序
|
|
|
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不好处理]
|
|
|
*
|
|
|
* @param aggregation
|
|
|
* @param viewNum
|
|
|
* @param sortField
|
|
|
* @param sortOrder
|
|
|
* @return
|
|
|
*/
|
|
|
public static List<KeyTopHitModel> getTopHitListGroupByKey(Map<String, Aggregation> aggMaps, SimpleFieldAgg simpleFieldAgg) {
|
|
|
String aggName = simpleFieldAgg.getAggName();
|
|
|
if (!aggMaps.containsKey(aggName)) {
|
|
|
return new ArrayList<KeyTopHitModel>();
|
|
|
}
|
|
|
List<? extends Bucket> bucketList = ((MultiBucketsAggregation) aggMaps.get(aggName)).getBuckets();
|
|
|
if (bucketList.isEmpty()) {
|
|
|
return new ArrayList<KeyTopHitModel>();
|
|
|
}
|
|
|
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, Object>>();
|
|
|
Map<String, Aggregation> aggMap = bucket.getAggregations().getAsMap();
|
|
|
if (aggMap.containsKey("topHit")) {
|
|
|
TopHits topHits = bucket.getAggregations().get("topHit");
|
|
|
if (topHits != null) {
|
|
|
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);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
KeyTopHitModel keyTopHitModel = new KeyTopHitModel(key, count, topHitList);
|
|
|
results.add(keyTopHitModel);
|
|
|
}
|
|
|
return results;
|
|
|
}
|
|
|
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;
|
|
|
}
|
|
|
|
|
|
} |
...
|
...
|
|