diff --git a/src/main/java/org/elasticsearch/search/aggregations/bucket/tophits/InternalTopHits.java b/src/main/java/org/elasticsearch/search/aggregations/bucket/tophits/InternalTopHits.java index 3f74391529b..1cb58544fd1 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/bucket/tophits/InternalTopHits.java +++ b/src/main/java/org/elasticsearch/search/aggregations/bucket/tophits/InternalTopHits.java @@ -73,7 +73,7 @@ public class InternalTopHits extends InternalAggregation implements TopHits, ToX public InternalTopHits(String name, InternalSearchHits searchHits) { this.name = name; this.searchHits = searchHits; - this.topDocs = new TopDocs(0, Lucene.EMPTY_SCORE_DOCS, 0); + this.topDocs = Lucene.EMPTY_TOP_DOCS; } diff --git a/src/main/java/org/elasticsearch/search/aggregations/bucket/tophits/TopHitsAggregator.java b/src/main/java/org/elasticsearch/search/aggregations/bucket/tophits/TopHitsAggregator.java index 165f9e5198d..fab02ac4cd2 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/bucket/tophits/TopHitsAggregator.java +++ b/src/main/java/org/elasticsearch/search/aggregations/bucket/tophits/TopHitsAggregator.java @@ -23,6 +23,7 @@ import org.apache.lucene.index.AtomicReaderContext; import org.apache.lucene.search.*; import org.elasticsearch.ExceptionsHelper; import org.elasticsearch.common.lease.Releasables; +import org.elasticsearch.common.lucene.Lucene; import org.elasticsearch.common.lucene.ScorerAware; import org.elasticsearch.common.util.LongObjectPagedHashMap; import org.elasticsearch.search.aggregations.*; @@ -31,6 +32,7 @@ import org.elasticsearch.search.aggregations.support.AggregationContext; import org.elasticsearch.search.fetch.FetchPhase; import org.elasticsearch.search.fetch.FetchSearchResult; import org.elasticsearch.search.internal.InternalSearchHit; +import org.elasticsearch.search.internal.InternalSearchHits; import java.io.IOException; @@ -94,7 +96,7 @@ public class TopHitsAggregator extends BucketsAggregator implements ScorerAware @Override public InternalAggregation buildEmptyAggregation() { - return new InternalTopHits(); + return new InternalTopHits(name, topHitsContext.size(), topHitsContext.sort(), Lucene.EMPTY_TOP_DOCS, InternalSearchHits.empty()); } @Override diff --git a/src/main/java/org/elasticsearch/search/aggregations/bucket/tophits/TopHitsBuilder.java b/src/main/java/org/elasticsearch/search/aggregations/bucket/tophits/TopHitsBuilder.java index 785fadff2d7..285b21b2647 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/bucket/tophits/TopHitsBuilder.java +++ b/src/main/java/org/elasticsearch/search/aggregations/bucket/tophits/TopHitsBuilder.java @@ -368,7 +368,7 @@ public class TopHitsBuilder extends AbstractAggregationBuilder { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { builder.startObject(name).field(type); - sourceBuilder.toXContent(builder, params); + sourceBuilder().toXContent(builder, params); return builder.endObject(); } diff --git a/src/main/java/org/elasticsearch/search/internal/InternalSearchHits.java b/src/main/java/org/elasticsearch/search/internal/InternalSearchHits.java index 6d08e56864f..d86f119c337 100644 --- a/src/main/java/org/elasticsearch/search/internal/InternalSearchHits.java +++ b/src/main/java/org/elasticsearch/search/internal/InternalSearchHits.java @@ -90,6 +90,10 @@ public class InternalSearchHits implements SearchHits { return cache.get().reset(); } + public static InternalSearchHits empty() { + // We shouldn't use static final instance, since that could directly be returned by native transport clients + return new InternalSearchHits(EMPTY, 0, 0); + } public static final InternalSearchHit[] EMPTY = new InternalSearchHit[0]; diff --git a/src/main/java/org/elasticsearch/search/internal/InternalSearchResponse.java b/src/main/java/org/elasticsearch/search/internal/InternalSearchResponse.java index c48ad7c0930..b86e97d5ddf 100644 --- a/src/main/java/org/elasticsearch/search/internal/InternalSearchResponse.java +++ b/src/main/java/org/elasticsearch/search/internal/InternalSearchResponse.java @@ -41,7 +41,7 @@ import static org.elasticsearch.search.internal.InternalSearchHits.readSearchHit public class InternalSearchResponse implements Streamable, ToXContent { public static InternalSearchResponse empty() { - return new InternalSearchResponse(new InternalSearchHits(new InternalSearchHit[0], 0, 0), null, null, null, false); + return new InternalSearchResponse(InternalSearchHits.empty(), null, null, null, false); } private InternalSearchHits hits; diff --git a/src/test/java/org/elasticsearch/search/aggregations/bucket/TopHitsTests.java b/src/test/java/org/elasticsearch/search/aggregations/bucket/TopHitsTests.java index c990d745c5d..2c4fb2fee9e 100644 --- a/src/test/java/org/elasticsearch/search/aggregations/bucket/TopHitsTests.java +++ b/src/test/java/org/elasticsearch/search/aggregations/bucket/TopHitsTests.java @@ -64,6 +64,7 @@ public class TopHitsTests extends ElasticsearchIntegrationTest { @Override public void setupSuiteScopeCluster() throws Exception { createIndex("idx"); + createIndex("empty"); List builders = new ArrayList<>(); for (int i = 0; i < 50; i++) { builders.add(client().prepareIndex("idx", "type", Integer.toString(i)).setSource(jsonBuilder() @@ -363,4 +364,17 @@ public class TopHitsTests extends ElasticsearchIntegrationTest { } } + @Test + public void testEmptyIndex() throws Exception { + SearchResponse response = client().prepareSearch("empty").setTypes("type") + .addAggregation(topHits("hits")) + .get(); + assertSearchResponse(response); + + TopHits hits = response.getAggregations().get("hits"); + assertThat(hits, notNullValue()); + assertThat(hits.getName(), equalTo("hits")); + assertThat(hits.getHits().totalHits(), equalTo(0l)); + } + }