Repository: searchbox-io/Jest
Pull request #535 (2017-08-21 12:26:45)

implement Children Aggregation support
implement Children Aggregation support 
Ticket: #534


Patch:
diff --git a/jest-common/src/main/java/io/searchbox/core/search/aggregation/ChildrenAggregation.java b/jest-common/src/main/java/io/searchbox/core/search/aggregation/ChildrenAggregation.java
new file mode 100644
index 00000000..2f3bd520
--- /dev/null
+++ b/jest-common/src/main/java/io/searchbox/core/search/aggregation/ChildrenAggregation.java
@@ -0,0 +1,15 @@
+package io.searchbox.core.search.aggregation;
+
+import com.google.gson.JsonObject;
+
+public class ChildrenAggregation extends MetricAggregation {
+
+	protected String name;
+	protected JsonObject jsonRoot;
+	public static final String TYPE = "child";
+
+	public ChildrenAggregation(String name, JsonObject childrenAggregation) {
+
+		super(name, childrenAggregation);
+	}
+}
diff --git a/jest-common/src/main/java/io/searchbox/core/search/aggregation/MetricAggregation.java b/jest-common/src/main/java/io/searchbox/core/search/aggregation/MetricAggregation.java
index d5e8a3b6..e2bcb91c 100644
--- a/jest-common/src/main/java/io/searchbox/core/search/aggregation/MetricAggregation.java
+++ b/jest-common/src/main/java/io/searchbox/core/search/aggregation/MetricAggregation.java
@@ -1,5 +1,6 @@
 package io.searchbox.core.search.aggregation;
 
+import com.google.gson.Gson;
 import com.google.gson.JsonObject;
 
 import java.lang.reflect.Constructor;
@@ -248,8 +249,31 @@ public abstract class MetricAggregation extends Aggregation {
         return jsonRoot.has(aggName) ? new ValueCountAggregation(aggName, jsonRoot.getAsJsonObject(aggName)) : null;
     }
     
+    /**
+     * @param aggName Name of the TopHitsAggregation
+     * @return a new TopHitsAggregation object if aggName is found within sub-aggregations of current aggregation level or null if not found
+     */
     public TopHitsAggregation getTopHitsAggregation(String aggName) {
-	return jsonRoot.has(aggName) ? new TopHitsAggregation(aggName, jsonRoot.getAsJsonObject(aggName)) : null;
+    		return jsonRoot.has(aggName) ? new TopHitsAggregation(aggName, jsonRoot.getAsJsonObject(aggName)) : null;
+    }
+    
+    /**
+     * @param aggName Name of the TopHitsAggregation
+     * @param gson Custom Gson parser for top hit results
+     * @return a new TopHitsAggregation object if aggName is found within sub-aggregations of current aggregation level or null if not found
+     */
+    public TopHitsAggregation getTopHitsAggregation(String aggName, Gson gson) {
+    		return jsonRoot.has(aggName) ? new TopHitsAggregation(aggName, jsonRoot.getAsJsonObject(aggName), gson) : null;
     }
 
+    
+    /**
+     * @param aggName Name of the ChildrenAggregation
+     * @return a new ChildrenAggregation object if aggName is found within sub-aggregations of current aggregation level or null if not found
+     */
+
+    public ChildrenAggregation getChildrenAggregation(String aggName) {
+		return jsonRoot.has(aggName) ? new ChildrenAggregation(aggName, jsonRoot.getAsJsonObject(aggName)) : null;
+}
+
 }
diff --git a/jest-common/src/main/java/io/searchbox/core/search/aggregation/TopHitsAggregation.java b/jest-common/src/main/java/io/searchbox/core/search/aggregation/TopHitsAggregation.java
index 83344b3c..8a974941 100644
--- a/jest-common/src/main/java/io/searchbox/core/search/aggregation/TopHitsAggregation.java
+++ b/jest-common/src/main/java/io/searchbox/core/search/aggregation/TopHitsAggregation.java
@@ -9,21 +9,24 @@ import io.searchbox.core.SearchResult;
 
 public class TopHitsAggregation extends SearchResult {
 
-    protected String name;
-    protected JsonObject jsonRoot;
-    public static final String TYPE = "top_hits";
+	protected String name;
+	protected JsonObject jsonRoot;
+	public static final String TYPE = "top_hits";
 
-    public TopHitsAggregation(String name, JsonObject topHitAggregation) {
-	super(new Gson());
-	this.name = name;
+	public TopHitsAggregation(String name, JsonObject topHitAggregation) {
+		this(name, topHitAggregation, null);
+	}
 	
-	this.setSucceeded(true);
-	this.setJsonObject(topHitAggregation);
-	//this.setJsonString(topHitAggregation.getAsString());
-	this.setPathToResult("hits/hits/_source");
-    }
-
-    public String getName() {
-	return name;
-    }
+	public TopHitsAggregation(String name, JsonObject topHitAggregation, Gson gson) {
+		super(gson == null ? new Gson() : gson);
+		this.name = name;
+
+		this.setSucceeded(true);
+		this.setJsonObject(topHitAggregation);
+		this.setPathToResult("hits/hits/_source");
+	}
+
+	public String getName() {
+		return name;
+	}
 }


Test patch:
diff --git a/jest-common/src/test/java/io/searchbox/search/aggregation/ChildAggregationTest.java b/jest-common/src/test/java/io/searchbox/search/aggregation/ChildAggregationTest.java
new file mode 100644
index 00000000..1223a644
--- /dev/null
+++ b/jest-common/src/test/java/io/searchbox/search/aggregation/ChildAggregationTest.java
@@ -0,0 +1,135 @@
+package io.searchbox.search.aggregation;
+
+import static org.junit.Assert.*;
+
+import java.util.List;
+
+import org.junit.Test;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonParser;
+
+import io.searchbox.core.SearchResult;
+import io.searchbox.core.search.aggregation.ChildrenAggregation;
+import io.searchbox.core.search.aggregation.TermsAggregation;
+import io.searchbox.core.search.aggregation.TermsAggregation.Entry;
+import io.searchbox.core.search.aggregation.TopHitsAggregation;
+
+public class ChildAggregationTest {
+
+	// @formatter:off
+    String json = "{\n" +
+            "    \"_shards\":{\n" +
+            "        \"total\" : 5,\n" +
+            "        \"successful\" : 5,\n" +
+            "        \"failed\" : 0\n" +
+            "    },\n" +
+            "    \"hits\":{\n" +
+            "        \"total\" : 1,\n" +
+            "	     \"hits\": []\n" +
+            "    },\n" +
+            "    \"aggregations\": {\n" +
+            "        \"childtest\": {\n" +
+            "            \"test\": {\n" +
+            "                \"doc_count_error_upper_bound\": 1,\n" +
+            "                \"sum_other_doc_count\": 2,\n" +
+            "                \"buckets\": [\n" +
+            "                    {\n" +
+            "                        \"key\": \"keyTest1\",\n" +
+            "                        \"doc_count\": 2,\n" +
+            "                        \"top_hits_test\": {\n" +
+            "                            \"hits\": {\n" +
+            "                                \"total\": 2,\n" +
+            "                                \"max_score\": 1.22222,\n" +
+            "                                \"hits\": [\n" +
+            "                                    {\n" +
+            "                                        \"_index\": \"indexName\",\n" +
+            "                                        \"_type\": \"typeName\",\n" +
+            "                                        \"_id\": \"testId1\",\n" +
+            "                                        \"_score\": 1.11111,\n" +
+            "                                        \"_source\": {\n" +
+            "                                            \"field1\": \"field1Content\"\n" +
+            "                                        }\n" +
+            "                                    },\n" +
+            "                                    {\n" +
+            "                                        \"_index\": \"indexName\",\n" +
+            "                                        \"_type\": \"typeName\",\n" +
+            "                                        \"_id\": \"testId2\",\n" +
+            "                                        \"_score\": 1.0000,\n" +
+            "                                        \"_source\": {\n" +
+            "                                            \"field1\": \"field2Content\"\n" +
+            "                                        }\n" +
+            "                                    }\n" +
+            "                                ]\n" +
+            "                            }\n" +
+            "                        }\n" +
+            "                    },\n" +
+            "                    {\n" +
+            "                        \"key\": \"keyTest2\",\n" +
+            "                        \"doc_count\": 2,\n" +
+            "                        \"top_hits_test\": {\n" +
+            "                            \"hits\": {\n" +
+            "                                \"total\": 2,\n" +
+            "                                \"max_score\": 1.22222,\n" +
+            "                                \"hits\": [\n" +
+            "                                    {\n" +
+            "                                        \"_index\": \"indexName\",\n" +
+            "                                        \"_type\": \"typeName\",\n" +
+            "                                        \"_id\": \"testId21\",\n" +
+            "                                        \"_score\": 1.11111,\n" +
+            "                                        \"_source\": {\n" +
+            "                                            \"field1\": \"field21Content\"\n" +
+            "                                        }\n" +
+            "                                    },\n" +
+            "                                    {\n" +
+            "                                        \"_index\": \"indexName\",\n" +
+            "                                        \"_type\": \"typeName\",\n" +
+            "                                        \"_id\": \"testId22\",\n" +
+            "                                        \"_score\": 1.0000,\n" +
+            "                                        \"_source\": {\n" +
+            "                                            \"field1\": \"field22Content\"\n" +
+            "                                        }\n" +
+            "                                    }\n" +
+            "                                ]\n" +
+            "                            }\n" +
+            "                        }\n" +
+            "                    }\n" +
+            "                ]\n" +
+            "            }\n" +
+            "        }\n" +
+            "    }\n" + 
+            "}";
+	// @formatter:on
+
+	@Test
+	public void testGetMaxScoreWhenMissingWithChildren() {
+		System.out.println(json);
+		
+		SearchResult searchResult = new SearchResult(new Gson());
+		searchResult.setSucceeded(true);
+		searchResult.setJsonString(json);
+		searchResult.setJsonObject(new JsonParser().parse(json).getAsJsonObject());
+		searchResult.setPathToResult("hits/hits/_source");
+
+		Float maxScore = searchResult.getMaxScore();
+		assertNull(maxScore);
+		
+		ChildrenAggregation childAgg = searchResult.getAggregations().getChildrenAggregation("childtest");
+		assertNotNull(childAgg);
+
+		TermsAggregation termsAgg = childAgg.getTermsAggregation("test");
+
+		assertEquals(new Long(1), termsAgg.getDocCountErrorUpperBound());
+		assertEquals(new Long(2), termsAgg.getSumOtherDocCount());
+
+		List<Entry> termBuckets = termsAgg.getBuckets();
+
+		for (Entry entry : termBuckets) {
+			TopHitsAggregation topHitAgg = entry.getTopHitsAggregation("top_hits_test");
+
+			List<String> hits = topHitAgg.getSourceAsStringList();
+
+			assertEquals(2, hits.size());
+		}
+	}
+}