package org.nlpcn.es4sql.domain;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHitField;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.filter.InternalFilter;
import org.elasticsearch.search.aggregations.bucket.terms.InternalTerms;
import org.elasticsearch.search.aggregations.bucket.terms.LongTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms.Bucket;
import org.elasticsearch.search.aggregations.metrics.InternalNumericMetricsAggregation;
import org.elasticsearch.search.aggregations.metrics.tophits.InternalTopHits;
import org.elasticsearch.search.aggregations.metrics.valuecount.InternalValueCount;
import org.nlpcn.es4sql.exception.SqlParseException;
public class SearchResult {
/**
* 查询结果
*/
private List<Map<String, Object>> results;
private long total;
double maxScore = 0;
public SearchResult(SearchResponse resp) {
SearchHits hits = resp.getHits();
this.total = hits.getTotalHits();
results = new ArrayList<>(hits.getHits().length);
for (SearchHit searchHit : hits.getHits()) {
if (searchHit.getSource() != null) {
results.add(searchHit.getSource());
} else if (searchHit.getFields() != null) {
Map<String, SearchHitField> fields = searchHit.getFields();
results.add(toFieldsMap(fields));
}
}
}
public SearchResult(SearchResponse resp, Select select) throws SqlParseException {
Aggregations aggs = resp.getAggregations();
if (aggs.get("filter") != null) {
InternalFilter inf = aggs.get("filter");
aggs = inf.getAggregations();
}
if (aggs.get("group by") != null) {
InternalTerms terms = aggs.get("group by");
Collection<Bucket> buckets = terms.getBuckets();
this.total = buckets.size();
results = new ArrayList<>(buckets.size());
for (Bucket bucket : buckets) {
Map<String, Object> aggsMap = toAggsMap(bucket.getAggregations().getAsMap());
aggsMap.put("docCount", bucket.getDocCount());
results.add(aggsMap);
}
} else {
results = new ArrayList<>(1);
this.total = 1;
Map<String, Object> map = new HashMap<>();
for (Aggregation aggregation : aggs) {
map.put(aggregation.getName(), covenValue(aggregation));
}
results.add(map);
}
}
/**
* 讲es的field域转换为你Object
*
* @param fields
* @return
*/
private Map<String, Object> toFieldsMap(Map<String, SearchHitField> fields) {
Map<String, Object> result = new HashMap<>();
for (Entry<String, SearchHitField> entry : fields.entrySet()) {
if (entry.getValue().values().size() > 1) {
result.put(entry.getKey(), entry.getValue().values());
} else {
result.put(entry.getKey(), entry.getValue().value());
}
}
return result;
}
/**
* 讲es的field域转换为你Object
*
* @param fields
* @return
* @throws SqlParseException
*/
private Map<String, Object> toAggsMap(Map<String, Aggregation> fields) throws SqlParseException {
Map<String, Object> result = new HashMap<>();
for (Entry<String, Aggregation> entry : fields.entrySet()) {
result.put(entry.getKey(), covenValue(entry.getValue()));
}
return result;
}
private Object covenValue(Aggregation value) throws SqlParseException {
if (value instanceof InternalNumericMetricsAggregation.SingleValue) {
return ((InternalNumericMetricsAggregation.SingleValue) value).value();
} else if (value instanceof InternalValueCount) {
return ((InternalValueCount) value).getValue();
} else if (value instanceof InternalTopHits) {
return (value);
} else if (value instanceof LongTerms) {
return value;
} else {
throw new SqlParseException("unknow this agg type " + value.getClass());
}
}
public List<Map<String, Object>> getResults() {
return results;
}
public void setResults(List<Map<String, Object>> results) {
this.results = results;
}
public long getTotal() {
return total;
}
public void setTotal(long total) {
this.total = total;
}
public double getMaxScore() {
return maxScore;
}
public void setMaxScore(double maxScore) {
this.maxScore = maxScore;
}
}