Skip to content

Commit

Permalink
Issue searchbox-io#146 Adding aggregation support
Browse files Browse the repository at this point in the history
Changes to reflect suggestions by kramer
  • Loading branch information
Clayton F Stout authored and Clayton F Stout committed Feb 18, 2015
1 parent 9a29e31 commit b7bf2a8
Show file tree
Hide file tree
Showing 30 changed files with 378 additions and 580 deletions.
101 changes: 27 additions & 74 deletions jest-common/src/main/java/io/searchbox/core/SearchResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ protected <T, K> List<Hit<T, K>> getHits(Class<T> sourceType, Class<K> explanati
} else if (obj.isJsonArray()) {
for (JsonElement hitElement : obj.getAsJsonArray()) {
sourceList.add(extractHit(sourceType, explanationType, hitElement, sourceKey));
if (returnSingle) break;
if (returnSingle) {
break;
}
}
}
}
Expand All @@ -98,7 +100,9 @@ protected <T, K> Hit<T, K> extractHit(Class<T> sourceType, Class<K> explanationT
JsonObject highlight = hitObject.getAsJsonObject(HIGHLIGHT_KEY);
JsonElement id = hitObject.get("_id");

if (id != null) source.add(ES_METADATA_ID, id);
if (id != null) {
source.add(ES_METADATA_ID, id);
}
hit = new Hit<T, K>(sourceType, source, explanationType, explanation, extractHighlight(highlight));
}
}
Expand Down Expand Up @@ -128,14 +132,18 @@ protected Map<String, List<String>> extractHighlight(JsonObject highlight) {
public Integer getTotal() {
Integer total = null;
JsonElement obj = getPath(PATH_TO_TOTAL);
if (obj != null) total = obj.getAsInt();
if (obj != null) {
total = obj.getAsInt();
}
return total;
}

public Float getMaxScore() {
Float maxScore = null;
JsonElement obj = getPath(PATH_TO_MAX_SCORE);
if (obj != null) maxScore = obj.getAsFloat();
if (obj != null) {
maxScore = obj.getAsFloat();
}
return maxScore;
}

Expand All @@ -144,7 +152,9 @@ protected JsonElement getPath(String[] path) {
if (jsonObject != null) {
JsonElement obj = jsonObject;
for (String component : path) {
if (obj == null) break;
if (obj == null) {
break;
}
obj = ((JsonObject) obj).get(component);
}
retval = obj;
Expand All @@ -158,8 +168,9 @@ public <T extends Facet> List<T> getFacets(Class<T> type) {
Constructor<T> c;
try {
JsonObject facetsMap = (JsonObject) jsonObject.get("facets");
if (facetsMap == null)
if (facetsMap == null) {
return facets;
}
for (Map.Entry<String, JsonElement> facetEntry : facetsMap.entrySet()) {
JsonObject facet = facetEntry.getValue().getAsJsonObject();
if (facet.get("_type").getAsString().equalsIgnoreCase(type.getField("TYPE").get(null).toString())) {
Expand All @@ -178,77 +189,19 @@ public <T extends Facet> List<T> getFacets(Class<T> type) {
return facets;
}

/**
*
* @param nameToTypeMap A map of all the names expected to be found in the
* aggregation results to the expected return type.
* This map takes the place of the _type metadata
* previously provided in results from faceting.
* @return A map from the name of the aggregation expected in the return to
* that aggregation.
*/
public <T extends Aggregation> Map<String, T> getAggregations(Map<String, Class<T>> nameToTypeMap) {
Map<String, T> nameToAggregationMap = new HashMap<String, T>();
if(jsonObject != null) {
Constructor<T> c;
try {
JsonObject aggregationsMap;
if (jsonObject.has("aggregations")) {
aggregationsMap = (JsonObject) jsonObject.get("aggregations");
} else if (jsonObject.has("aggs")) {
aggregationsMap = (JsonObject) jsonObject.get("aggs");
} else {
return nameToAggregationMap;
}
for (Map.Entry<String, JsonElement> aggregationEntry: aggregationsMap.entrySet()) {
String name = aggregationEntry.getKey();
JsonObject aggregation = aggregationEntry.getValue().getAsJsonObject();
Class<T> type = nameToTypeMap.get(name);

c = type.getConstructor(String.class, JsonObject.class, Map.class);
nameToAggregationMap.put(name, c.newInstance(name, aggregationEntry.getValue(), nameToTypeMap));
}
return nameToAggregationMap;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
return nameToAggregationMap;
}

/**
* Because aggregations no longer return the _type metadata,
* it is impossible to determine the type of an aggregation
* based on the json alone.
*
* The intended use is for the user to call Aggregation.getFields() to
* determine the non-null fields before calling the get method for these values.
* Sub aggregations can be iterated recursively in the same manner
*
* @return A list of non-typed aggregation objects.
*/
public List<TypeInvariantAggregation> getAggregations() {
List<TypeInvariantAggregation> aggregations = new ArrayList<TypeInvariantAggregation>();
public Aggregation getAggregations() {
if (jsonObject != null) {
try {
JsonObject aggregationsMap;
if (jsonObject.has("aggregations")) {
aggregationsMap = (JsonObject) jsonObject.get("aggregations");
} else if (jsonObject.has("aggs")) {
aggregationsMap = (JsonObject) jsonObject.get("aggs");
} else {
return aggregations;
}
for (Map.Entry<String, JsonElement> aggregationEntry : aggregationsMap.entrySet()) {
TypeInvariantAggregation aggregation = new TypeInvariantAggregation(aggregationEntry.getKey(), aggregationEntry.getValue().getAsJsonObject());
aggregations.add(aggregation);
}
return aggregations;
} catch (Exception e) {
throw new RuntimeException(e);
JsonObject aggregationsMap;
if (jsonObject.has("aggregations")) {
aggregationsMap = (JsonObject) jsonObject.get("aggregations");
} else if (jsonObject.has("aggs")) {
aggregationsMap = (JsonObject) jsonObject.get("aggs");
} else {
return new Aggregation("aggs", new JsonObject());
}
return new Aggregation("aggs", aggregationsMap);
}
return aggregations;
return new Aggregation("aggs", new JsonObject());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,150 @@
import com.google.gson.JsonObject;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
* @author cfstout
*/

public abstract class Aggregation {
public class Aggregation <T extends Aggregation> {

protected String name;
protected List<Aggregation> subAggregations;
protected JsonObject jsonRoot;

public String getName() {
return name;
}

public List<Aggregation> getSubAggregations() {
return subAggregations;
public Aggregation(String name, JsonObject jsonRoot) {
this.name = name;
this.jsonRoot = jsonRoot;
}

public boolean hasSubAggregations() {
return !(subAggregations == null || subAggregations.isEmpty());
public String getName() {
return name;
}

public <T extends Aggregation> void addSubAggregations(JsonObject rootAggregation, Map<String, Class<T>> nameToTypeMap) {
public List<T> getAggregations(Map<String, Class<T>> nameToTypeMap) {
List<T> aggregations = new ArrayList<T>();
for (String nameCandidate : nameToTypeMap.keySet()) {
if (rootAggregation.has(nameCandidate)) {
if (jsonRoot.has(nameCandidate)) {
try {
Class<T> type = nameToTypeMap.get(name);
Constructor<T> c = type.getConstructor(String.class, JsonObject.class, Map.class);
this.subAggregations.add(c.newInstance(nameCandidate, rootAggregation.get(nameCandidate).getAsJsonObject(), nameToTypeMap));
Constructor<T> c = type.getConstructor(String.class, JsonObject.class);
aggregations.add(c.newInstance(nameCandidate, jsonRoot.get(nameCandidate).getAsJsonObject()));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
return aggregations;
}

public Aggregation getAggregation(String aggName, Class<T> aggType) {
if(jsonRoot.has(aggName)) {
try {
Constructor<T> c = aggType.getConstructor(String.class, JsonObject.class);
c.newInstance(aggName, jsonRoot.get(aggName).getAsJsonObject());
} catch(Exception e) {
throw new RuntimeException(e);
}
}
//aggregation name/type not found
//better way to handle this?
return null;
}

public AvgAggregation getAvgAggregation(String aggName) {
return jsonRoot.has(aggName) ? new AvgAggregation(aggName, jsonRoot.get(aggName).getAsJsonObject()) : null;
}

public DateHistogramAggregation getDateHistogramAggregation(String aggName) {
return jsonRoot.has(aggName) ? new DateHistogramAggregation(aggName, jsonRoot.get(aggName).getAsJsonObject()) : null;
}

public DateRangeAggregation getDateRangeAggregation(String aggName) {
return jsonRoot.has(aggName) ? new DateRangeAggregation(aggName, jsonRoot.get(aggName).getAsJsonObject()) : null;
}

public ExtendedStatsAggregation getExtendedStatsAggregation(String aggName) {
return jsonRoot.has(aggName) ? new ExtendedStatsAggregation(aggName, jsonRoot.get(aggName).getAsJsonObject()) : null;
}

public FilterAggregation getFilterAggregation(String aggName) {
return jsonRoot.has(aggName) ? new FilterAggregation(aggName, jsonRoot.get(aggName).getAsJsonObject()) : null;
}

public FiltersAggregation getFiltersAggregation(String aggName) {
return jsonRoot.has(aggName) ? new FiltersAggregation(aggName, jsonRoot.get(aggName).getAsJsonObject()) : null;
}

public GeoBoundsAggregation getGeoBoundsAggregation(String aggName) {
return jsonRoot.has(aggName) ? new GeoBoundsAggregation(aggName, jsonRoot.get(aggName).getAsJsonObject()) : null;
}

public GeoDistanceAggregation getGeoDistanceAggregation(String aggName) {
return jsonRoot.has(aggName) ? new GeoDistanceAggregation(aggName, jsonRoot.get(aggName).getAsJsonObject()) : null;
}

public GeohashGridAggregation getGeohashGridAggregation(String aggName) {
return jsonRoot.has(aggName) ? new GeohashGridAggregation(aggName, jsonRoot.get(aggName).getAsJsonObject()) : null;
}

public HistogramAggregation getHistogramAggregation(String aggName) {
return jsonRoot.has(aggName) ? new HistogramAggregation(aggName, jsonRoot.get(aggName).getAsJsonObject()) : null;
}

public Ipv4RangeAggregation getIpv4RangeAggregation(String aggName) {
return jsonRoot.has(aggName) ? new Ipv4RangeAggregation(aggName, jsonRoot.get(aggName).getAsJsonObject()) : null;
}

public MaxAggregation getMaxAggregation(String aggName) {
return jsonRoot.has(aggName) ? new MaxAggregation(aggName, jsonRoot.get(aggName).getAsJsonObject()) : null;
}

public MinAggregation getMinAggregation(String aggName) {
return jsonRoot.has(aggName) ? new MinAggregation(aggName, jsonRoot.get(aggName).getAsJsonObject()) : null;
}

public MissingAggregation getMissingAggregation(String aggName) {
return jsonRoot.has(aggName) ? new MissingAggregation(aggName, jsonRoot.get(aggName).getAsJsonObject()) : null;
}

public PercentileRanksAggregation getPercentileRanksAggregation(String aggName) {
return jsonRoot.has(aggName) ? new PercentileRanksAggregation(aggName, jsonRoot.get(aggName).getAsJsonObject()) : null;
}

public PercentilesAggregation getPercentilesAggregation(String aggName) {
return jsonRoot.has(aggName) ? new PercentilesAggregation(aggName, jsonRoot.get(aggName).getAsJsonObject()) : null;
}

public RangeAggregation getRangeAggregation(String aggName) {
return jsonRoot.has(aggName) ? new RangeAggregation(aggName, jsonRoot.get(aggName).getAsJsonObject()) : null;
}

public ScriptedMetricAggregation getScriptedMetricAggregation(String aggName) {
return jsonRoot.has(aggName) ? new ScriptedMetricAggregation(aggName, jsonRoot.get(aggName).getAsJsonObject()) : null;
}

public SignificantTermsAggregation getSignificantTermsAggregation(String aggName) {
return jsonRoot.has(aggName) ? new SignificantTermsAggregation(aggName, jsonRoot.get(aggName).getAsJsonObject()) : null;
}

public StatsAggregation getStatsAggregation(String aggName) {
return jsonRoot.has(aggName) ? new StatsAggregation(aggName, jsonRoot.get(aggName).getAsJsonObject()) : null;
}

public SumAggregation getSumAggregation(String aggName) {
return jsonRoot.has(aggName) ? new SumAggregation(aggName, jsonRoot.get(aggName).getAsJsonObject()) : null;
}

public TermsAggregation getTermsAggregation(String aggName) {
return jsonRoot.has(aggName) ? new TermsAggregation(aggName, jsonRoot.get(aggName).getAsJsonObject()) : null;
}

public ValueCountAggregation getValueCountAggregation(String aggName) {
return jsonRoot.has(aggName) ? new ValueCountAggregation(aggName, jsonRoot.get(aggName).getAsJsonObject()) : null;
}



}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,13 @@ public enum AggregationField {
VARIANCE("variance"),
STD_DEVIATION("std_deviation"),
STD_DEVIATION_BOUNDS("std_deviation_bounds"),
UPPER("upper"),
LOWER("lower"),
BOUNDS("bounds"),
TOP_LEFT("top_left"),
BOTTOM_RIGHT("bottom_right"),
LAT("lat"),
LON("lon"),
UNIT("unit"),
VALUES("values"),
SCORE("score"),
Expand All @@ -29,7 +35,9 @@ public enum AggregationField {
MIN("min"),
MAX("max"),
AVG("avg"),
SUM("sum");
SUM("sum"),
DOC_COUNT_ERROR_UPPER_BOUND("doc_count_error_upper_bound"),
SUM_OTHER_DOC_COUNT("sum_other_doc_count");

private final String field;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

import com.google.gson.JsonObject;

import java.lang.reflect.Constructor;
import java.util.Map;
import static io.searchbox.core.search.aggregation.AggregationField.VALUE;

/**
* @author cfstout
Expand All @@ -14,10 +13,9 @@ public class AvgAggregation extends Aggregation {

private Double avg;

public <T extends Aggregation> AvgAggregation(String name, JsonObject avgAggregation, Map<String, Class<T>> nameToTypeMap) {
this.name = name;
avg = avgAggregation.get("value").getAsDouble();
addSubAggregations(avgAggregation, nameToTypeMap);
public <T extends Aggregation> AvgAggregation(String name, JsonObject avgAggregation) {
super(name, avgAggregation);
avg = avgAggregation.get(String.valueOf(VALUE)).getAsDouble();
}

public Double getAvg() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import com.google.gson.JsonObject;

import java.util.Map;
import static io.searchbox.core.search.aggregation.AggregationField.VALUE;

/**
* @author cfstout
Expand All @@ -13,10 +13,9 @@ public class CardinalityAggregation extends Aggregation{

private Long cardinality;

public <T extends Aggregation> CardinalityAggregation(String name, JsonObject cardinalityAggregation, Map<String, Class<T>> nameToTypeMap) {
this.name = name;
cardinality = cardinalityAggregation.get("value").getAsLong();
addSubAggregations(cardinalityAggregation, nameToTypeMap);
public <T extends Aggregation> CardinalityAggregation(String name, JsonObject cardinalityAggregation) {
super(name, cardinalityAggregation);
cardinality = cardinalityAggregation.get(String.valueOf(VALUE)).getAsLong();
}

public Long getCardinality() {
Expand Down
Loading

0 comments on commit b7bf2a8

Please # to comment.