Skip to content

Commit 68deda6

Browse files
authored
FastVectorHighlighter should not cache the field query globally (#25197)
This commit removes the global caching of the field query and replaces it with a caching per field. Each field can use a different `highlight_query` and the rewriting of some queries (prefix, automaton, ...) depends on the targeted field so the query used for highlighting must be unique per field. There might be a small performance penalty when highlighting multiple fields since the query needs to be rewritten once per highlighted field with this change. Fixes #25171
1 parent 4a30e23 commit 68deda6

File tree

2 files changed

+72
-25
lines changed

2 files changed

+72
-25
lines changed

core/src/main/java/org/elasticsearch/search/fetch/subphase/highlight/FastVectorHighlighter.java

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -87,29 +87,6 @@ public HighlightField highlight(HighlighterContext highlighterContext) {
8787
HighlighterEntry cache = (HighlighterEntry) hitContext.cache().get(CACHE_KEY);
8888

8989
try {
90-
FieldQuery fieldQuery;
91-
if (field.fieldOptions().requireFieldMatch()) {
92-
if (cache.fieldMatchFieldQuery == null) {
93-
/*
94-
* we use top level reader to rewrite the query against all readers,
95-
* with use caching it across hits (and across readers...)
96-
*/
97-
cache.fieldMatchFieldQuery = new CustomFieldQuery(highlighterContext.query,
98-
hitContext.topLevelReader(), true, field.fieldOptions().requireFieldMatch());
99-
}
100-
fieldQuery = cache.fieldMatchFieldQuery;
101-
} else {
102-
if (cache.noFieldMatchFieldQuery == null) {
103-
/*
104-
* we use top level reader to rewrite the query against all readers,
105-
* with use caching it across hits (and across readers...)
106-
*/
107-
cache.noFieldMatchFieldQuery = new CustomFieldQuery(highlighterContext.query,
108-
hitContext.topLevelReader(), true, field.fieldOptions().requireFieldMatch());
109-
}
110-
fieldQuery = cache.noFieldMatchFieldQuery;
111-
}
112-
11390
MapperHighlightEntry entry = cache.mappers.get(mapper);
11491
if (entry == null) {
11592
FragListBuilder fragListBuilder;
@@ -151,6 +128,21 @@ public HighlightField highlight(HighlighterContext highlighterContext) {
151128
}
152129
fragmentsBuilder.setDiscreteMultiValueHighlighting(termVectorMultiValue);
153130
entry = new MapperHighlightEntry();
131+
if (field.fieldOptions().requireFieldMatch()) {
132+
/**
133+
* we use top level reader to rewrite the query against all readers,
134+
* with use caching it across hits (and across readers...)
135+
*/
136+
entry.fieldMatchFieldQuery = new CustomFieldQuery(highlighterContext.query,
137+
hitContext.topLevelReader(), true, field.fieldOptions().requireFieldMatch());
138+
} else {
139+
/**
140+
* we use top level reader to rewrite the query against all readers,
141+
* with use caching it across hits (and across readers...)
142+
*/
143+
entry.noFieldMatchFieldQuery = new CustomFieldQuery(highlighterContext.query,
144+
hitContext.topLevelReader(), true, field.fieldOptions().requireFieldMatch());
145+
}
154146
entry.fragListBuilder = fragListBuilder;
155147
entry.fragmentsBuilder = fragmentsBuilder;
156148
if (cache.fvh == null) {
@@ -162,6 +154,12 @@ public HighlightField highlight(HighlighterContext highlighterContext) {
162154
CustomFieldQuery.highlightFilters.set(field.fieldOptions().highlightFilter());
163155
cache.mappers.put(mapper, entry);
164156
}
157+
final FieldQuery fieldQuery;
158+
if (field.fieldOptions().requireFieldMatch()) {
159+
fieldQuery = entry.fieldMatchFieldQuery;
160+
} else {
161+
fieldQuery = entry.noFieldMatchFieldQuery;
162+
}
165163
cache.fvh.setPhraseLimit(field.fieldOptions().phraseLimit());
166164

167165
String[] fragments;
@@ -249,12 +247,12 @@ private static BoundaryScanner getBoundaryScanner(Field field) {
249247
private class MapperHighlightEntry {
250248
public FragListBuilder fragListBuilder;
251249
public FragmentsBuilder fragmentsBuilder;
250+
public FieldQuery noFieldMatchFieldQuery;
251+
public FieldQuery fieldMatchFieldQuery;
252252
}
253253

254254
private class HighlighterEntry {
255255
public org.apache.lucene.search.vectorhighlight.FastVectorHighlighter fvh;
256-
public FieldQuery noFieldMatchFieldQuery;
257-
public FieldQuery fieldMatchFieldQuery;
258256
public Map<FieldMapper, MapperHighlightEntry> mappers = new HashMap<>();
259257
}
260258
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
setup:
2+
- do:
3+
indices.create:
4+
index: test
5+
body:
6+
mappings:
7+
doc:
8+
"properties":
9+
"title":
10+
"type": "text"
11+
"term_vector": "with_positions_offsets"
12+
"description":
13+
"type": "text"
14+
"term_vector": "with_positions_offsets"
15+
- do:
16+
index:
17+
index: test
18+
type: doc
19+
id: 1
20+
body:
21+
"title" : "The quick brown fox is brown"
22+
"description" : "The quick pink panther is pink"
23+
- do:
24+
indices.refresh: {}
25+
26+
---
27+
"Highlight query":
28+
- skip:
29+
version: " - 5.5.99"
30+
reason: bug fixed in 5.6
31+
- do:
32+
search:
33+
body:
34+
highlight:
35+
type: fvh
36+
fields:
37+
description:
38+
type: fvh
39+
highlight_query:
40+
prefix:
41+
description: br
42+
title:
43+
type: fvh
44+
highlight_query:
45+
prefix:
46+
title: br
47+
48+
- match: {hits.hits.0.highlight.title.0: "The quick <em>brown</em> fox is <em>brown</em>"}
49+
- is_false: hits.hits.0.highlight.description

0 commit comments

Comments
 (0)