The `top_hits` aggregation should compile scripts only once. (#20738)
Today it compiles when creating the aggregator, meaning that scripts will be compiled as many times as there are buckets. Instead it should compile when creating the factory so that scripts are compiled only once regardless of the number of buckets.
This commit is contained in:
parent
a2e82adc6f
commit
6174e21f47
|
@ -28,6 +28,8 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
import org.elasticsearch.common.xcontent.XContentParser;
|
import org.elasticsearch.common.xcontent.XContentParser;
|
||||||
import org.elasticsearch.index.query.QueryParseContext;
|
import org.elasticsearch.index.query.QueryParseContext;
|
||||||
import org.elasticsearch.script.Script;
|
import org.elasticsearch.script.Script;
|
||||||
|
import org.elasticsearch.script.ScriptContext;
|
||||||
|
import org.elasticsearch.script.SearchScript;
|
||||||
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
|
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
|
||||||
import org.elasticsearch.search.aggregations.AggregationInitializationException;
|
import org.elasticsearch.search.aggregations.AggregationInitializationException;
|
||||||
import org.elasticsearch.search.aggregations.AggregatorFactories.Builder;
|
import org.elasticsearch.search.aggregations.AggregatorFactories.Builder;
|
||||||
|
@ -39,6 +41,7 @@ import org.elasticsearch.search.builder.SearchSourceBuilder;
|
||||||
import org.elasticsearch.search.builder.SearchSourceBuilder.ScriptField;
|
import org.elasticsearch.search.builder.SearchSourceBuilder.ScriptField;
|
||||||
import org.elasticsearch.search.fetch.StoredFieldsContext;
|
import org.elasticsearch.search.fetch.StoredFieldsContext;
|
||||||
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
|
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
|
||||||
|
import org.elasticsearch.search.fetch.subphase.ScriptFieldsContext;
|
||||||
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
|
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
|
||||||
import org.elasticsearch.search.sort.ScoreSortBuilder;
|
import org.elasticsearch.search.sort.ScoreSortBuilder;
|
||||||
import org.elasticsearch.search.sort.SortBuilder;
|
import org.elasticsearch.search.sort.SortBuilder;
|
||||||
|
@ -527,6 +530,18 @@ public class TopHitsAggregationBuilder extends AbstractAggregationBuilder<TopHit
|
||||||
@Override
|
@Override
|
||||||
protected TopHitsAggregatorFactory doBuild(AggregationContext context, AggregatorFactory<?> parent, Builder subfactoriesBuilder)
|
protected TopHitsAggregatorFactory doBuild(AggregationContext context, AggregatorFactory<?> parent, Builder subfactoriesBuilder)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
List<ScriptFieldsContext.ScriptField> scriptFields = null;
|
||||||
|
if (this.scriptFields != null) {
|
||||||
|
scriptFields = new ArrayList<>();
|
||||||
|
for (ScriptField field : this.scriptFields) {
|
||||||
|
SearchScript searchScript = context.searchContext().scriptService().search(
|
||||||
|
context.searchContext().lookup(), field.script(), ScriptContext.Standard.SEARCH, Collections.emptyMap());
|
||||||
|
scriptFields.add(new ScriptFieldsContext.ScriptField(
|
||||||
|
field.fieldName(), searchScript, field.ignoreFailure()));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
scriptFields = Collections.emptyList();
|
||||||
|
}
|
||||||
return new TopHitsAggregatorFactory(name, type, from, size, explain, version, trackScores, sorts, highlightBuilder,
|
return new TopHitsAggregatorFactory(name, type, from, size, explain, version, trackScores, sorts, highlightBuilder,
|
||||||
storedFieldsContext, fieldDataFields, scriptFields, fetchSourceContext, context,
|
storedFieldsContext, fieldDataFields, scriptFields, fetchSourceContext, context,
|
||||||
parent, subfactoriesBuilder, metaData);
|
parent, subfactoriesBuilder, metaData);
|
||||||
|
|
|
@ -19,29 +19,25 @@
|
||||||
|
|
||||||
package org.elasticsearch.search.aggregations.metrics.tophits;
|
package org.elasticsearch.search.aggregations.metrics.tophits;
|
||||||
|
|
||||||
import org.elasticsearch.script.ScriptContext;
|
|
||||||
import org.elasticsearch.script.SearchScript;
|
|
||||||
import org.elasticsearch.search.aggregations.Aggregator;
|
import org.elasticsearch.search.aggregations.Aggregator;
|
||||||
import org.elasticsearch.search.aggregations.AggregatorFactories;
|
import org.elasticsearch.search.aggregations.AggregatorFactories;
|
||||||
import org.elasticsearch.search.aggregations.AggregatorFactory;
|
import org.elasticsearch.search.aggregations.AggregatorFactory;
|
||||||
import org.elasticsearch.search.aggregations.InternalAggregation.Type;
|
import org.elasticsearch.search.aggregations.InternalAggregation.Type;
|
||||||
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
|
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
|
||||||
import org.elasticsearch.search.aggregations.support.AggregationContext;
|
import org.elasticsearch.search.aggregations.support.AggregationContext;
|
||||||
import org.elasticsearch.search.builder.SearchSourceBuilder.ScriptField;
|
|
||||||
import org.elasticsearch.search.fetch.StoredFieldsContext;
|
import org.elasticsearch.search.fetch.StoredFieldsContext;
|
||||||
import org.elasticsearch.search.fetch.subphase.DocValueFieldsContext;
|
import org.elasticsearch.search.fetch.subphase.DocValueFieldsContext;
|
||||||
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
|
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
|
||||||
|
import org.elasticsearch.search.fetch.subphase.ScriptFieldsContext;
|
||||||
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
|
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
|
||||||
import org.elasticsearch.search.internal.SubSearchContext;
|
import org.elasticsearch.search.internal.SubSearchContext;
|
||||||
import org.elasticsearch.search.sort.SortAndFormats;
|
import org.elasticsearch.search.sort.SortAndFormats;
|
||||||
import org.elasticsearch.search.sort.SortBuilder;
|
import org.elasticsearch.search.sort.SortBuilder;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class TopHitsAggregatorFactory extends AggregatorFactory<TopHitsAggregatorFactory> {
|
public class TopHitsAggregatorFactory extends AggregatorFactory<TopHitsAggregatorFactory> {
|
||||||
|
|
||||||
|
@ -54,12 +50,12 @@ public class TopHitsAggregatorFactory extends AggregatorFactory<TopHitsAggregato
|
||||||
private final HighlightBuilder highlightBuilder;
|
private final HighlightBuilder highlightBuilder;
|
||||||
private final StoredFieldsContext storedFieldsContext;
|
private final StoredFieldsContext storedFieldsContext;
|
||||||
private final List<String> docValueFields;
|
private final List<String> docValueFields;
|
||||||
private final Set<ScriptField> scriptFields;
|
private final List<ScriptFieldsContext.ScriptField> scriptFields;
|
||||||
private final FetchSourceContext fetchSourceContext;
|
private final FetchSourceContext fetchSourceContext;
|
||||||
|
|
||||||
public TopHitsAggregatorFactory(String name, Type type, int from, int size, boolean explain, boolean version, boolean trackScores,
|
public TopHitsAggregatorFactory(String name, Type type, int from, int size, boolean explain, boolean version, boolean trackScores,
|
||||||
List<SortBuilder<?>> sorts, HighlightBuilder highlightBuilder, StoredFieldsContext storedFieldsContext,
|
List<SortBuilder<?>> sorts, HighlightBuilder highlightBuilder, StoredFieldsContext storedFieldsContext,
|
||||||
List<String> docValueFields, Set<ScriptField> scriptFields, FetchSourceContext fetchSourceContext,
|
List<String> docValueFields, List<ScriptFieldsContext.ScriptField> scriptFields, FetchSourceContext fetchSourceContext,
|
||||||
AggregationContext context, AggregatorFactory<?> parent, AggregatorFactories.Builder subFactories,
|
AggregationContext context, AggregatorFactory<?> parent, AggregatorFactories.Builder subFactories,
|
||||||
Map<String, Object> metaData) throws IOException {
|
Map<String, Object> metaData) throws IOException {
|
||||||
super(name, type, context, parent, subFactories, metaData);
|
super(name, type, context, parent, subFactories, metaData);
|
||||||
|
@ -98,13 +94,8 @@ public class TopHitsAggregatorFactory extends AggregatorFactory<TopHitsAggregato
|
||||||
if (docValueFields != null) {
|
if (docValueFields != null) {
|
||||||
subSearchContext.docValueFieldsContext(new DocValueFieldsContext(docValueFields));
|
subSearchContext.docValueFieldsContext(new DocValueFieldsContext(docValueFields));
|
||||||
}
|
}
|
||||||
if (scriptFields != null) {
|
for (ScriptFieldsContext.ScriptField field : scriptFields) {
|
||||||
for (ScriptField field : scriptFields) {
|
subSearchContext.scriptFields().add(field);
|
||||||
SearchScript searchScript = subSearchContext.scriptService().search(subSearchContext.lookup(), field.script(),
|
|
||||||
ScriptContext.Standard.SEARCH, Collections.emptyMap());
|
|
||||||
subSearchContext.scriptFields().add(new org.elasticsearch.search.fetch.subphase.ScriptFieldsContext.ScriptField(
|
|
||||||
field.fieldName(), searchScript, field.ignoreFailure()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (fetchSourceContext != null) {
|
if (fetchSourceContext != null) {
|
||||||
subSearchContext.fetchSourceContext(fetchSourceContext);
|
subSearchContext.fetchSourceContext(fetchSourceContext);
|
||||||
|
|
Loading…
Reference in New Issue