Skip to content

Commit 2872969

Browse files
committed
Make highlighters accessible
1 parent b923a2e commit 2872969

File tree

7 files changed

+67
-19
lines changed

7 files changed

+67
-19
lines changed

server/src/main/java/org/elasticsearch/search/SearchModule.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,8 @@
278278
* Sets up things that can be done at search time like queries, aggregations, and suggesters.
279279
*/
280280
public class SearchModule {
281+
private static volatile Map<String, Highlighter> staticHighlighters = Map.of();
282+
281283
public static final Setting<Integer> INDICES_MAX_CLAUSE_COUNT_SETTING = Setting.intSetting(
282284
"indices.query.bool.max_clause_count",
283285
4096,
@@ -920,6 +922,20 @@ private static Map<String, Highlighter> setupHighlighters(Settings settings, Lis
920922
return unmodifiableMap(highlighters.getRegistry());
921923
}
922924

925+
/**
926+
* Sets the static highlighters map for access by other plugins
927+
*/
928+
private static void setStaticHighlighters(Map<String, Highlighter> highlighters) {
929+
staticHighlighters = Map.copyOf(highlighters);
930+
}
931+
932+
/**
933+
* Gets the static highlighters map for other plugin access
934+
*/
935+
public static Map<String, Highlighter> getStaticHighlighters() {
936+
return staticHighlighters;
937+
}
938+
923939
private void registerScoreFunctions(List<SearchPlugin> plugins) {
924940
// ScriptScoreFunctionBuilder has it own named writable because of a new script_score query
925941
namedWriteables.add(
@@ -1059,6 +1075,8 @@ private void registerFetchSubPhases(List<SearchPlugin> plugins) {
10591075
registerFetchSubPhase(new HighlightPhase(highlighters));
10601076
registerFetchSubPhase(new FetchScorePhase());
10611077

1078+
setStaticHighlighters(highlighters);
1079+
10621080
FetchPhaseConstructionContext context = new FetchPhaseConstructionContext(highlighters);
10631081
registerFromPlugin(plugins, p -> p.getFetchSubPhases(context), this::registerFetchSubPhase);
10641082
}

server/src/main/java/org/elasticsearch/search/fetch/subphase/highlight/SearchHighlightContext.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ Builder boundaryScannerLocale(Locale boundaryScannerLocale) {
269269
return this;
270270
}
271271

272-
Builder highlightQuery(Query highlightQuery) {
272+
public Builder highlightQuery(Query highlightQuery) {
273273
fieldOptions.highlightQuery = highlightQuery;
274274
return this;
275275
}

x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/lucene/HighlighterExpressionEvaluator.java

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,20 +50,23 @@ public class HighlighterExpressionEvaluator extends LuceneQueryEvaluator<BytesRe
5050
private final Integer numFragments;
5151
private final Integer fragmentLength;
5252
private final SearchContext searchContext;
53+
private final Map<String, Highlighter> highlighters;
5354

5455
HighlighterExpressionEvaluator(
5556
BlockFactory blockFactory,
5657
ShardConfig[] shardConfigs,
5758
String fieldName,
5859
Integer numFragments,
5960
Integer fragmentLength,
60-
SearchContext searchContext
61+
SearchContext searchContext,
62+
Map<String, Highlighter> highlighters
6163
) {
6264
super(blockFactory, shardConfigs);
6365
this.fieldName = fieldName;
6466
this.numFragments = numFragments;
6567
this.fragmentLength = fragmentLength;
6668
this.searchContext = searchContext;
69+
this.highlighters = highlighters;
6770
}
6871

6972
@Override
@@ -93,14 +96,7 @@ protected void appendMatch(BytesRefBlock.Builder builder, Scorable scorer, int d
9396
MappedFieldType fieldType = searchContext.getSearchExecutionContext().getFieldType(fieldName);
9497
SearchHit searchHit = new SearchHit(docId);
9598
Source source = Source.lazy(lazyStoredSourceLoader(leafReaderContext, docId));
96-
String defaultHighlighter = fieldType.getDefaultHighlighter();
97-
98-
Highlighter highlighter;
99-
// if (SemanticTextHighlighter.NAME.equals(defaultHighlighter)) {
100-
// highlighter = new SemanticTextHighlighter();
101-
// } else {
102-
highlighter = new DefaultHighlighter();
103-
// }
99+
Highlighter highlighter = highlighters.getOrDefault(fieldType.getDefaultHighlighter(), new DefaultHighlighter());
104100

105101
SearchHighlightContext.FieldOptions.Builder optionsBuilder = new SearchHighlightContext.FieldOptions.Builder();
106102
optionsBuilder.numberOfFragments(numFragments != null ? numFragments : HighlightBuilder.DEFAULT_NUMBER_OF_FRAGMENTS);
@@ -109,6 +105,7 @@ protected void appendMatch(BytesRefBlock.Builder builder, Scorable scorer, int d
109105
optionsBuilder.postTags(new String[] { "" });
110106
optionsBuilder.requireFieldMatch(false);
111107
optionsBuilder.scoreOrdered(true);
108+
optionsBuilder.highlightQuery(query);
112109
SearchHighlightContext.Field field = new SearchHighlightContext.Field(fieldName, optionsBuilder.build());
113110

114111
FetchSubPhase.HitContext hitContext = new FetchSubPhase.HitContext(searchHit, leafReaderContext, docId, Map.of(), source, null);
@@ -165,7 +162,8 @@ public record Factory(
165162
String fieldName,
166163
Integer numFragments,
167164
Integer fragmentSize,
168-
SearchContext searchContext
165+
SearchContext searchContext,
166+
Map<String, Highlighter> highlighters
169167
) implements EvalOperator.ExpressionEvaluator.Factory {
170168
@Override
171169
public EvalOperator.ExpressionEvaluator get(DriverContext context) {
@@ -175,7 +173,8 @@ public EvalOperator.ExpressionEvaluator get(DriverContext context) {
175173
fieldName,
176174
numFragments,
177175
fragmentSize,
178-
searchContext
176+
searchContext,
177+
highlighters
179178
);
180179
}
181180
}

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/evaluator/EvalMapper.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,16 @@
2929
import org.elasticsearch.xpack.esql.expression.predicate.logical.BinaryLogic;
3030
import org.elasticsearch.xpack.esql.expression.predicate.operator.comparison.InsensitiveEqualsMapper;
3131
import org.elasticsearch.xpack.esql.planner.EsPhysicalOperationProviders.ShardContext;
32+
import org.elasticsearch.search.SearchModule;
33+
import org.elasticsearch.search.fetch.subphase.highlight.DefaultHighlighter;
34+
import org.elasticsearch.search.fetch.subphase.highlight.Highlighter;
35+
import org.elasticsearch.search.fetch.subphase.highlight.PlainHighlighter;
36+
import org.elasticsearch.search.internal.SearchContext;
3237
import org.elasticsearch.xpack.esql.planner.Layout;
3338

39+
import java.util.HashMap;
3440
import java.util.List;
41+
import java.util.Map;
3542

3643
public final class EvalMapper {
3744

@@ -79,6 +86,11 @@ public FoldContext foldCtx() {
7986
public List<ShardContext> shardContexts() {
8087
return shardContexts;
8188
}
89+
90+
@Override
91+
public Map<String, Highlighter> highlighters() {
92+
return SearchModule.getStaticHighlighters();
93+
}
8294
});
8395
}
8496
for (ExpressionMapper em : MAPPERS) {

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/evaluator/mapper/EvaluatorMapper.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import org.elasticsearch.indices.breaker.AllCircuitBreakerStats;
1818
import org.elasticsearch.indices.breaker.CircuitBreakerService;
1919
import org.elasticsearch.indices.breaker.CircuitBreakerStats;
20+
import org.elasticsearch.search.fetch.subphase.highlight.Highlighter;
2021
import org.elasticsearch.xpack.esql.core.expression.Expression;
2122
import org.elasticsearch.xpack.esql.core.expression.FoldContext;
2223
import org.elasticsearch.xpack.esql.core.tree.Source;
@@ -25,6 +26,7 @@
2526
import org.elasticsearch.xpack.esql.planner.Layout;
2627

2728
import java.util.List;
29+
import java.util.Map;
2830

2931
import static org.elasticsearch.compute.data.BlockUtils.fromArrayRow;
3032
import static org.elasticsearch.compute.data.BlockUtils.toJavaObject;
@@ -41,6 +43,10 @@ interface ToEvaluator {
4143
default List<EsPhysicalOperationProviders.ShardContext> shardContexts() {
4244
throw new UnsupportedOperationException("Shard contexts should only be needed for evaluation operations");
4345
}
46+
47+
default Map<String, Highlighter> highlighters() {
48+
throw new UnsupportedOperationException("Highlighters should only be needed for highlight operations");
49+
}
4450
}
4551

4652
/**

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/ExtractSnippets.java

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -217,11 +217,6 @@ public ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvaluator) {
217217
try {
218218
// TODO: Reduce duplication between this method and TextSimilarityRerankingRankFeaturePhaseRankShardContext#prepareForFetch
219219
HighlightBuilder highlightBuilder = new HighlightBuilder();
220-
if (queryBuilder != null) {
221-
// TODO validate this works and determine why this is not working in query builder resolver
222-
QueryBuilder rewritten = Rewriteable.rewrite(queryBuilder, searchExecutionContext);
223-
highlightBuilder.highlightQuery(rewritten);
224-
}
225220
// Stripping pre/post tags as they're not useful for snippet creation
226221
highlightBuilder.field(field.sourceText()).preTags("").postTags("");
227222
// Return highest scoring fragments
@@ -231,6 +226,12 @@ public ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvaluator) {
231226
highlightBuilder.fragmentSize(snippedSize);
232227
highlightBuilder.noMatchSize(snippedSize);
233228

229+
if (queryBuilder != null) {
230+
// TODO validate this works and determine why this is not working in query builder resolver
231+
QueryBuilder rewritten = Rewriteable.rewrite(queryBuilder, searchExecutionContext);
232+
highlightBuilder.highlightQuery(rewritten);
233+
}
234+
234235
SearchHighlightContext highlightContext = highlightBuilder.build(searchExecutionContext);
235236
searchContext.highlight(highlightContext);
236237

@@ -254,7 +255,14 @@ public ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvaluator) {
254255
// Get field name and search context from the first shard context
255256
String fieldNameStr = field.sourceText();
256257
SearchContext firstSearchContext = shardContexts.isEmpty() ? null : shardContexts.get(0).searchContext();
257-
return new HighlighterExpressionEvaluator.Factory(shardConfigs, fieldNameStr, numSnippets, snippedSize, firstSearchContext);
258+
return new HighlighterExpressionEvaluator.Factory(
259+
shardConfigs,
260+
fieldNameStr,
261+
numSnippets,
262+
snippedSize,
263+
firstSearchContext,
264+
toEvaluator.highlighters()
265+
);
258266
}
259267

260268
@Override

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/EsqlPlugin.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@
4242
import org.elasticsearch.plugins.ActionPlugin;
4343
import org.elasticsearch.plugins.ExtensiblePlugin;
4444
import org.elasticsearch.plugins.Plugin;
45+
import org.elasticsearch.plugins.SearchPlugin;
46+
import org.elasticsearch.search.fetch.subphase.highlight.DefaultHighlighter;
47+
import org.elasticsearch.search.fetch.subphase.highlight.Highlighter;
4548
import org.elasticsearch.rest.RestController;
4649
import org.elasticsearch.rest.RestHandler;
4750
import org.elasticsearch.threadpool.ExecutorBuilder;
@@ -82,12 +85,14 @@
8285
import java.lang.invoke.MethodHandles;
8386
import java.util.ArrayList;
8487
import java.util.Collection;
88+
import java.util.HashMap;
8589
import java.util.List;
90+
import java.util.Map;
8691
import java.util.Objects;
8792
import java.util.function.Predicate;
8893
import java.util.function.Supplier;
8994

90-
public class EsqlPlugin extends Plugin implements ActionPlugin, ExtensiblePlugin {
95+
public class EsqlPlugin extends Plugin implements ActionPlugin, ExtensiblePlugin, SearchPlugin {
9196
public static final boolean INLINESTATS_FEATURE_FLAG = new FeatureFlag("esql_inlinestats").isEnabled();
9297

9398
public static final String ESQL_WORKER_THREAD_POOL_NAME = "esql_worker";

0 commit comments

Comments
 (0)