Skip to content

Commit 46b9140

Browse files
author
Andre van de Ven
committed
top hits aggregation IT
Signed-off-by: Andre van de Ven <andrevdv@amazon.com>
1 parent 96bc00f commit 46b9140

File tree

1 file changed

+114
-0
lines changed

1 file changed

+114
-0
lines changed

server/src/internalClusterTest/java/org/opensearch/search/profile/aggregation/AggregationProfilerIT.java

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.opensearch.action.index.IndexRequestBuilder;
3838
import org.opensearch.action.search.SearchResponse;
3939
import org.opensearch.common.settings.Settings;
40+
import org.opensearch.index.query.QueryBuilders;
4041
import org.opensearch.search.aggregations.Aggregator.SubAggCollectionMode;
4142
import org.opensearch.search.aggregations.BucketOrder;
4243
import org.opensearch.search.aggregations.InternalAggregation;
@@ -46,8 +47,11 @@
4647
import org.opensearch.search.aggregations.metrics.Stats;
4748
import org.opensearch.search.profile.ProfileResult;
4849
import org.opensearch.search.profile.ProfileShardResult;
50+
import org.opensearch.search.profile.fetch.FetchProfileShardResult;
4951
import org.opensearch.search.profile.query.CollectorResult;
5052
import org.opensearch.search.profile.query.QueryProfileShardResult;
53+
import org.opensearch.search.sort.SortBuilders;
54+
import org.opensearch.search.sort.SortOrder;
5155
import org.opensearch.test.OpenSearchIntegTestCase;
5256
import org.opensearch.test.ParameterizedStaticSettingsOpenSearchIntegTestCase;
5357
import org.hamcrest.core.IsNull;
@@ -69,6 +73,7 @@
6973
import static org.opensearch.search.aggregations.AggregationBuilders.max;
7074
import static org.opensearch.search.aggregations.AggregationBuilders.stats;
7175
import static org.opensearch.search.aggregations.AggregationBuilders.terms;
76+
import static org.opensearch.search.aggregations.AggregationBuilders.topHits;
7277
import static org.opensearch.test.hamcrest.OpenSearchAssertions.assertAcked;
7378
import static org.opensearch.test.hamcrest.OpenSearchAssertions.assertSearchResponse;
7479
import static org.hamcrest.Matchers.containsString;
@@ -80,6 +85,7 @@
8085
import static org.hamcrest.Matchers.lessThanOrEqualTo;
8186
import static org.hamcrest.Matchers.notNullValue;
8287
import static org.hamcrest.Matchers.sameInstance;
88+
import static org.junit.Assume.assumeTrue;
8389

8490
@OpenSearchIntegTestCase.SuiteScopeTestCase
8591
public class AggregationProfilerIT extends ParameterizedStaticSettingsOpenSearchIntegTestCase {
@@ -1000,4 +1006,112 @@ private void assertCollectorResultWithConcurrentSearchEnabled(QueryProfileShardR
10001006
assertThat(collectorResult.getCollectorResult().getProfiledChildren().get(1).getReason(), equalTo(REASON_AGGREGATION));
10011007
}
10021008
}
1009+
1010+
public void testTopHitsAggregationFetchProfiling() throws Exception {
1011+
try {
1012+
SearchResponse response = client().prepareSearch("idx")
1013+
.setProfile(true)
1014+
.setQuery(QueryBuilders.matchAllQuery())
1015+
.addAggregation(topHits("top_hits_agg1").size(1))
1016+
.addAggregation(topHits("top_hits_agg2").size(1).sort(SortBuilders.fieldSort(NUMBER_FIELD).order(SortOrder.DESC)))
1017+
.get();
1018+
1019+
assertSearchResponse(response);
1020+
Map<String, ProfileShardResult> profileResults = response.getProfileResults();
1021+
assertNotNull("Profile results should not be null", profileResults);
1022+
assertFalse("Profile results should not be empty", profileResults.isEmpty());
1023+
1024+
int shardsWithDocuments = 0;
1025+
int shardsWithCorrectProfile = 0;
1026+
1027+
for (ProfileShardResult shardResult : profileResults.values()) {
1028+
FetchProfileShardResult fetchProfileResult = shardResult.getFetchProfileResult();
1029+
if (fetchProfileResult != null && !fetchProfileResult.getFetchProfileResults().isEmpty()) {
1030+
shardsWithDocuments++;
1031+
List<ProfileResult> fetchProfileResults = fetchProfileResult.getFetchProfileResults();
1032+
1033+
assertEquals("Should have 3 fetch operations (1 main + 2 top_hits aggregations)", 3, fetchProfileResults.size());
1034+
1035+
ProfileResult mainFetch = null;
1036+
ProfileResult topHitsFetch1 = null;
1037+
ProfileResult topHitsFetch2 = null;
1038+
1039+
for (ProfileResult result : fetchProfileResults) {
1040+
if ("fetch".equals(result.getQueryName())) {
1041+
mainFetch = result;
1042+
} else if (result.getQueryName().contains("top_hits_agg1")) {
1043+
topHitsFetch1 = result;
1044+
} else if (result.getQueryName().contains("top_hits_agg2")) {
1045+
topHitsFetch2 = result;
1046+
}
1047+
}
1048+
1049+
assertNotNull("Should have main fetch operation", mainFetch);
1050+
assertEquals("fetch", mainFetch.getQueryName());
1051+
assertNotNull(mainFetch.getTimeBreakdown());
1052+
assertTrue("Main fetch should have children", !mainFetch.getProfiledChildren().isEmpty());
1053+
1054+
assertNotNull("Should have top_hits_agg1 fetch operation", topHitsFetch1);
1055+
assertTrue(
1056+
"Should be top_hits aggregation fetch",
1057+
topHitsFetch1.getQueryName().startsWith("fetch_top_hits_aggregation")
1058+
);
1059+
assertTrue("Should contain aggregation name", topHitsFetch1.getQueryName().contains("top_hits_agg1"));
1060+
assertNotNull(topHitsFetch1.getTimeBreakdown());
1061+
assertEquals("Top hits fetch should have 1 child (FetchSourcePhase)", 1, topHitsFetch1.getProfiledChildren().size());
1062+
assertEquals("FetchSourcePhase", topHitsFetch1.getProfiledChildren().get(0).getQueryName());
1063+
1064+
assertNotNull("Should have top_hits_agg2 fetch operation", topHitsFetch2);
1065+
assertTrue(
1066+
"Should be top_hits aggregation fetch",
1067+
topHitsFetch2.getQueryName().startsWith("fetch_top_hits_aggregation")
1068+
);
1069+
assertTrue("Should contain aggregation name", topHitsFetch2.getQueryName().contains("top_hits_agg2"));
1070+
assertNotNull(topHitsFetch2.getTimeBreakdown());
1071+
assertEquals("Top hits fetch should have 1 child (FetchSourcePhase)", 1, topHitsFetch2.getProfiledChildren().size());
1072+
assertEquals("FetchSourcePhase", topHitsFetch2.getProfiledChildren().get(0).getQueryName());
1073+
1074+
for (ProfileResult fetchResult : fetchProfileResults) {
1075+
Map<String, Long> breakdown = fetchResult.getTimeBreakdown();
1076+
assertTrue(
1077+
"CREATE_STORED_FIELDS_VISITOR timing should be present",
1078+
breakdown.containsKey("create_stored_fields_visitor")
1079+
);
1080+
assertTrue(
1081+
"BUILD_SUB_PHASE_PROCESSORS timing should be present",
1082+
breakdown.containsKey("build_sub_phase_processors")
1083+
);
1084+
assertTrue("GET_NEXT_READER timing should be present", breakdown.containsKey("get_next_reader"));
1085+
assertTrue("LOAD_STORED_FIELDS timing should be present", breakdown.containsKey("load_stored_fields"));
1086+
assertTrue("LOAD_SOURCE timing should be present", breakdown.containsKey("load_source"));
1087+
}
1088+
1089+
shardsWithCorrectProfile++;
1090+
}
1091+
}
1092+
1093+
assertTrue("Should have at least one shard with documents", shardsWithDocuments > 0);
1094+
assertEquals(
1095+
"All shards with documents should have correct fetch profile structure",
1096+
shardsWithDocuments,
1097+
shardsWithCorrectProfile
1098+
);
1099+
} catch (Exception e) {
1100+
if (e.getCause() != null
1101+
&& e.getCause().getMessage() != null
1102+
&& e.getCause().getMessage().contains("Fetch phase")
1103+
&& e.getCause().getMessage().contains("does not exist")) {
1104+
1105+
boolean concurrentSearchEnabled = clusterService().getClusterSettings().get(CLUSTER_CONCURRENT_SEGMENT_SEARCH_SETTING);
1106+
1107+
if (concurrentSearchEnabled) {
1108+
assumeTrue("Skipping test due to known issue with concurrent search and top hits fetch profiling", false);
1109+
} else {
1110+
throw e;
1111+
}
1112+
} else {
1113+
throw e;
1114+
}
1115+
}
1116+
}
10031117
}

0 commit comments

Comments
 (0)