Skip to content

Commit cb4d238

Browse files
committed
Query shape for agg & sort
1 parent 29a3e2c commit cb4d238

File tree

2 files changed

+96
-2
lines changed

2 files changed

+96
-2
lines changed

server/src/main/java/org/opensearch/action/search/SearchQueryCategorizer.java

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,13 @@
1515
import org.opensearch.index.query.QueryShapeVisitor;
1616
import org.opensearch.search.aggregations.AggregatorFactories;
1717
import org.opensearch.search.builder.SearchSourceBuilder;
18+
import org.opensearch.search.sort.FieldSortBuilder;
1819
import org.opensearch.search.sort.SortBuilder;
1920
import org.opensearch.telemetry.metrics.MetricsRegistry;
2021
import org.opensearch.telemetry.metrics.tags.Tags;
2122

23+
import java.util.ArrayList;
24+
import java.util.Collections;
2225
import java.util.List;
2326
import java.util.ListIterator;
2427

@@ -28,7 +31,8 @@
2831
*/
2932
final class SearchQueryCategorizer {
3033

31-
private static final Logger log = LogManager.getLogger(SearchQueryCategorizer.class);
34+
private static final Logger logger = LogManager.getLogger(SearchQueryCategorizer.class);
35+
public static final String TWO_SPACE_INDENT = " ";
3236

3337
final SearchQueryCounters searchQueryCounters;
3438

@@ -43,8 +47,12 @@ public void categorize(SearchSourceBuilder source) {
4347
QueryBuilder topLevelQueryBuilder = source.query();
4448
logQueryShape(topLevelQueryBuilder);
4549
incrementQueryTypeCounters(topLevelQueryBuilder);
50+
4651
incrementQueryAggregationCounters(source.aggregations());
52+
logAggregationsShape(source.aggregations());
53+
4754
incrementQuerySortCounters(source.sorts());
55+
logSortShape(source.sorts(), true);
4856
}
4957

5058
private void incrementQuerySortCounters(List<SortBuilder<?>> sorts) {
@@ -79,7 +87,45 @@ private void logQueryShape(QueryBuilder topLevelQueryBuilder) {
7987
}
8088
QueryShapeVisitor shapeVisitor = new QueryShapeVisitor();
8189
topLevelQueryBuilder.visit(shapeVisitor);
82-
log.trace("Query shape : {}", shapeVisitor.prettyPrintTree(" "));
90+
logger.trace(shapeVisitor.prettyPrintTree(TWO_SPACE_INDENT));
91+
System.out.println(shapeVisitor.prettyPrintTree(TWO_SPACE_INDENT));
8392
}
8493

94+
private void logAggregationsShape(AggregatorFactories.Builder aggregationsBuilder) {
95+
if (aggregationsBuilder == null) {
96+
return;
97+
}
98+
StringBuilder aggregationShape = aggregationsBuilder.visit(new StringBuilder(), 0, true);
99+
logger.trace(aggregationShape.toString());
100+
System.out.println(aggregationShape);
101+
}
102+
103+
private void logSortShape(List<SortBuilder<?>> sortBuilderList, Boolean showFields) {
104+
if (sortBuilderList.isEmpty()) {
105+
return;
106+
}
107+
StringBuilder sortShape = new StringBuilder();
108+
sortShape.append("sort:\n");
109+
110+
List<String> shapeStrings = new ArrayList<>();
111+
for (SortBuilder sortBuilder : sortBuilderList) {
112+
StringBuilder stringBuilder = new StringBuilder();
113+
stringBuilder.append(TWO_SPACE_INDENT + sortBuilder.order() + ":");
114+
if (showFields) {
115+
if (sortBuilder instanceof FieldSortBuilder) {
116+
stringBuilder.append(" [" + ((FieldSortBuilder) sortBuilder).getFieldName() + "]");
117+
} else {
118+
stringBuilder.append(" []");
119+
}
120+
}
121+
shapeStrings.add(stringBuilder.toString());
122+
}
123+
124+
Collections.sort(shapeStrings);
125+
for (String line : shapeStrings) {
126+
sortShape.append(line).append("\n");
127+
}
128+
logger.trace(sortShape.toString());
129+
System.out.println(sortShape);
130+
}
85131
}

server/src/main/java/org/opensearch/search/aggregations/AggregatorFactories.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545
import org.opensearch.core.xcontent.XContentBuilder;
4646
import org.opensearch.core.xcontent.XContentLocation;
4747
import org.opensearch.core.xcontent.XContentParser;
48+
import org.opensearch.index.query.QueryBuilder;
49+
import org.opensearch.index.query.QueryBuilderVisitor;
4850
import org.opensearch.index.query.QueryRewriteContext;
4951
import org.opensearch.index.query.QueryShardContext;
5052
import org.opensearch.index.query.Rewriteable;
@@ -55,6 +57,7 @@
5557
import org.opensearch.search.aggregations.pipeline.PipelineAggregator.PipelineTree;
5658
import org.opensearch.search.aggregations.support.AggregationPath;
5759
import org.opensearch.search.aggregations.support.AggregationPath.PathElement;
60+
import org.opensearch.search.aggregations.support.ValuesSourceAggregationBuilder;
5861
import org.opensearch.search.internal.SearchContext;
5962
import org.opensearch.search.profile.Profilers;
6063
import org.opensearch.search.profile.aggregation.ProfilingAggregator;
@@ -88,6 +91,7 @@
8891
@PublicApi(since = "1.0.0")
8992
public class AggregatorFactories {
9093
public static final Pattern VALID_AGG_NAME = Pattern.compile("[^\\[\\]>]+");
94+
static final String TWO_SPACE_INDENT = " ";
9195

9296
/**
9397
* Parses the aggregation request recursively generating aggregator
@@ -372,6 +376,50 @@ public Builder(StreamInput in) throws IOException {
372376
}
373377
}
374378

379+
public StringBuilder visit(StringBuilder outputBuilder, int indentCount, Boolean showFields) {
380+
String indent = TWO_SPACE_INDENT.repeat(indentCount);
381+
382+
//// Normal Aggregations ////
383+
if (aggregationBuilders.isEmpty() == false) {
384+
outputBuilder.append(indent + "aggregation:").append("\n");
385+
}
386+
List<String> aggShapeStrings = new ArrayList<>();
387+
for (AggregationBuilder agg : aggregationBuilders) {
388+
StringBuilder stringBuilder = new StringBuilder();
389+
stringBuilder.append(indent + TWO_SPACE_INDENT + agg.getType());
390+
if (showFields) {
391+
if (agg instanceof ValuesSourceAggregationBuilder) {
392+
stringBuilder.append(" [" + ((ValuesSourceAggregationBuilder) agg).field() + "]");
393+
} else {
394+
stringBuilder.append(" []");
395+
}
396+
}
397+
stringBuilder.append("\n");
398+
399+
if (agg.factoriesBuilder.names.isEmpty() == false) {
400+
// Recursive call on sub-aggregations
401+
stringBuilder = agg.factoriesBuilder.visit(stringBuilder, indentCount + 2, showFields);
402+
}
403+
aggShapeStrings.add(stringBuilder.toString());
404+
}
405+
406+
// Sort aggregations
407+
Collections.sort(aggShapeStrings);
408+
for (String shapeString : aggShapeStrings) {
409+
outputBuilder.append(shapeString);
410+
}
411+
412+
//// Pipeline Aggregation (cannot have sub-aggregations) ////
413+
if (pipelineAggregatorBuilders.isEmpty() == false) {
414+
outputBuilder.append(indent + "pipeline aggregation:").append("\n");
415+
}
416+
for (PipelineAggregationBuilder agg : pipelineAggregatorBuilders) {
417+
outputBuilder.append(indent + " " + agg.name).append("\n");
418+
}
419+
420+
return outputBuilder;
421+
}
422+
375423
@Override
376424
public void writeTo(StreamOutput out) throws IOException {
377425
out.writeVInt(this.aggregationBuilders.size());

0 commit comments

Comments
 (0)