Skip to content

Commit d58a08b

Browse files
committed
added test and implemented feature
1 parent 79060e6 commit d58a08b

File tree

2 files changed

+140
-44
lines changed

2 files changed

+140
-44
lines changed

server/src/internalClusterTest/java/org/elasticsearch/search/fetch/subphase/highlight/HighlighterSearchIT.java

Lines changed: 116 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.elasticsearch.common.geo.GeoPoint;
2626
import org.elasticsearch.common.settings.Settings;
2727
import org.elasticsearch.common.settings.Settings.Builder;
28+
import org.elasticsearch.common.text.Text;
2829
import org.elasticsearch.common.time.DateFormatter;
2930
import org.elasticsearch.common.util.Maps;
3031
import org.elasticsearch.index.analysis.AbstractIndexAnalyzerProvider;
@@ -44,6 +45,7 @@
4445
import org.elasticsearch.plugins.Plugin;
4546
import org.elasticsearch.rest.RestStatus;
4647
import org.elasticsearch.search.SearchHit;
48+
import org.elasticsearch.search.SearchHits;
4749
import org.elasticsearch.search.builder.SearchSourceBuilder;
4850
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder.BoundaryScannerType;
4951
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder.Field;
@@ -75,7 +77,6 @@
7577
import static org.elasticsearch.index.query.QueryBuilders.constantScoreQuery;
7678
import static org.elasticsearch.index.query.QueryBuilders.existsQuery;
7779
import static org.elasticsearch.index.query.QueryBuilders.fuzzyQuery;
78-
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
7980
import static org.elasticsearch.index.query.QueryBuilders.matchPhrasePrefixQuery;
8081
import static org.elasticsearch.index.query.QueryBuilders.matchPhraseQuery;
8182
import static org.elasticsearch.index.query.QueryBuilders.matchQuery;
@@ -3502,6 +3503,120 @@ public void testDisableHighlightIdField() throws Exception {
35023503
}
35033504
}
35043505

3506+
public void testImplicitConstantKeywordFieldHighlighting() throws IOException {
3507+
//Constant field value is defined by the mapping
3508+
XContentBuilder mappings = prepareConstantKeywordMappings("level");
3509+
3510+
assertAcked(prepareCreate("test").setMapping(mappings));
3511+
3512+
client().prepareIndex("test")
3513+
.setId("1")
3514+
.setSource(
3515+
jsonBuilder().startObject()
3516+
.field("message", "some text")
3517+
.endObject()
3518+
)
3519+
.get();
3520+
refresh();
3521+
3522+
SearchResponse search = prepareConstantKeywordSearch(QueryBuilders.queryStringQuery("DEBUG"));
3523+
assertNoFailures(search);
3524+
assertThat(
3525+
getHighlighedStringFromSearch(search, "level"),
3526+
equalTo("<em>DEBUG</em>")
3527+
);
3528+
}
3529+
3530+
public void testConstantKeywordFieldHighlighting() throws IOException {
3531+
// check that constant_keyword highlighting works
3532+
XContentBuilder mappings = prepareConstantKeywordMappings("level");
3533+
3534+
assertAcked(prepareCreate("test").setMapping(mappings));
3535+
3536+
client().prepareIndex("test")
3537+
.setId("1")
3538+
.setSource(
3539+
jsonBuilder().startObject()
3540+
.field("message", "some text")
3541+
.field("level", "DEBUG")
3542+
.endObject()
3543+
)
3544+
.get();
3545+
refresh();
3546+
SearchResponse search = prepareConstantKeywordSearch(QueryBuilders.queryStringQuery("DEBUG"));
3547+
assertNoFailures(search);
3548+
assertThat(
3549+
getHighlighedStringFromSearch(search, "level"),
3550+
equalTo("<em>DEBUG</em>")
3551+
);
3552+
}
3553+
3554+
public void testConstantKeywordFieldPartialWithWildcardHighlighting() throws IOException {
3555+
// check that constant_keyword highlighting works
3556+
XContentBuilder mappings = prepareConstantKeywordMappings("level");
3557+
3558+
assertAcked(prepareCreate("test").setMapping(mappings));
3559+
3560+
client().prepareIndex("test")
3561+
.setId("1")
3562+
.setSource(
3563+
jsonBuilder()
3564+
.startObject()
3565+
.field("message", "some text")
3566+
.endObject()
3567+
)
3568+
.get();
3569+
refresh();
3570+
3571+
SearchResponse search = prepareConstantKeywordSearch(QueryBuilders.queryStringQuery("DEB*"));
3572+
3573+
assertNoFailures(search);
3574+
assertThat(
3575+
getHighlighedStringFromSearch(search, "level"),
3576+
equalTo("<em>DEBUG</em>")
3577+
);
3578+
}
3579+
3580+
private XContentBuilder prepareConstantKeywordMappings(String constantKeywordFieldName) throws IOException {
3581+
XContentBuilder mappings = jsonBuilder();
3582+
mappings.startObject();
3583+
mappings.startObject("_doc")
3584+
.startObject("properties")
3585+
.startObject(constantKeywordFieldName)
3586+
.field("type", "constant_keyword")
3587+
.field("value", "DEBUG")
3588+
.endObject()
3589+
.startObject("message")
3590+
.field("type", "text")
3591+
.endObject()
3592+
.endObject()
3593+
.endObject();
3594+
mappings.endObject();
3595+
return mappings;
3596+
}
3597+
3598+
private SearchResponse prepareConstantKeywordSearch(QueryBuilder query){
3599+
return client().prepareSearch()
3600+
.setSource(
3601+
new SearchSourceBuilder().query(query)
3602+
.highlighter(new HighlightBuilder().field("*"))
3603+
)
3604+
.get();
3605+
}
3606+
3607+
private String getHighlighedStringFromSearch(SearchResponse search, String fieldName){
3608+
SearchHits hits = search.getHits();
3609+
assertEquals("We expect this test search to find exactly one hit", 1, hits.getHits().length);
3610+
3611+
Map<String, HighlightField> highlightFields = hits.getAt(0).getHighlightFields();
3612+
assertTrue("We expect to find an highlighted field of name [ %s ]".formatted(fieldName), highlightFields.containsKey(fieldName));
3613+
3614+
Text[] fragments = highlightFields.get(fieldName).getFragments();
3615+
assertEquals("We expect to have exactly one fragment", 1, fragments.length);
3616+
3617+
return fragments[0].toString();
3618+
}
3619+
35053620
public static class MockAnalysisPlugin extends Plugin implements AnalysisPlugin {
35063621

35073622
public final class MockSnowBall extends TokenFilter {
@@ -3551,45 +3666,5 @@ public Analyzer get() {
35513666
}
35523667
}
35533668

3554-
public void testConstantKeywordFieldHighlighting() throws IOException {
3555-
// check that constant_keyword highlighting works
3556-
XContentBuilder mappings = jsonBuilder();
3557-
mappings.startObject();
3558-
mappings.startObject("_doc")
3559-
.startObject("properties")
3560-
.startObject("level")
3561-
.field("type", "constant_keyword")
3562-
.field("value", "DEBUG")
3563-
.endObject()
3564-
.startObject("message")
3565-
.field("type", "text")
3566-
.endObject()
3567-
.endObject()
3568-
.endObject();
3569-
mappings.endObject();
3570-
3571-
assertAcked(prepareCreate("test").setMapping(mappings));
3572-
3573-
client().prepareIndex("test")
3574-
.setId("1")
3575-
.setSource(
3576-
jsonBuilder().startObject()
3577-
.field("message", "some text")
3578-
.endObject()
3579-
)
3580-
.get();
3581-
refresh();
3582-
SearchResponse search = client().prepareSearch()
3583-
.setSource(
3584-
new SearchSourceBuilder().query(QueryBuilders.termQuery("level", "DEBUG"))
3585-
.highlighter(new HighlightBuilder().field("*"))
3586-
)
3587-
.get();
3588-
assertNoFailures(search);
3589-
assertThat(
3590-
search.getHits().getAt(0).getHighlightFields().get("level").getFragments()[0].toString(),
3591-
equalTo("<em>DEBUG</em>")
3592-
);
3593-
}
35943669

35953670
}

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

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@
99
package org.elasticsearch.search.fetch.subphase.highlight;
1010

1111
import org.apache.lucene.index.LeafReaderContext;
12+
import org.apache.lucene.index.Term;
1213
import org.apache.lucene.search.Query;
14+
import org.apache.lucene.search.TermQuery;
15+
import org.elasticsearch.index.mapper.ConstantFieldType;
1316
import org.elasticsearch.index.mapper.KeywordFieldMapper;
1417
import org.elasticsearch.index.mapper.MappedFieldType;
1518
import org.elasticsearch.index.mapper.TextFieldMapper;
@@ -23,6 +26,7 @@
2326
import java.util.HashMap;
2427
import java.util.HashSet;
2528
import java.util.LinkedHashMap;
29+
import java.util.List;
2630
import java.util.Map;
2731
import java.util.Set;
2832
import java.util.function.Function;
@@ -66,7 +70,7 @@ public void process(HitContext hitContext) throws IOException {
6670
for (String field : contextBuilders.keySet()) {
6771
FieldHighlightContext fieldContext = contextBuilders.get(field).apply(hitContext);
6872
Highlighter highlighter = getHighlighter(fieldContext.field);
69-
HighlightField highlightField = highlighter.highlight(fieldContext);
73+
HighlightField highlightField = highlighter.highlight(fieldContext); //field context query should have also original query
7074
if (highlightField != null) {
7175
// Note that we make sure to use the original field name in the response. This is because the
7276
// original field could be an alias, and highlighter implementations may instead reference the
@@ -124,6 +128,7 @@ private FieldContext contextBuilders(
124128
if (fieldNameContainsWildcards) {
125129
if (fieldType.typeName().equals(TextFieldMapper.CONTENT_TYPE) == false
126130
&& fieldType.typeName().equals(KeywordFieldMapper.CONTENT_TYPE) == false
131+
&& fieldType.typeName().equals("constant_keyword") == false
127132
&& fieldType.typeName().equals("match_only_text") == false) {
128133
continue;
129134
}
@@ -139,7 +144,15 @@ private FieldContext contextBuilders(
139144
}
140145

141146
Query highlightQuery = field.fieldOptions().highlightQuery();
142-
147+
if (fieldType instanceof ConstantFieldType){
148+
highlightQuery = new TermQuery(
149+
new Term(
150+
fieldType.name(),
151+
getValueForConstantFieldType(context, fieldType)
152+
)
153+
);
154+
}
155+
Query finalHighlightQuery = highlightQuery;
143156
builders.put(
144157
fieldName,
145158
hc -> new FieldHighlightContext(
@@ -148,7 +161,7 @@ private FieldContext contextBuilders(
148161
fieldType,
149162
context,
150163
hc,
151-
highlightQuery == null ? query : highlightQuery,
164+
finalHighlightQuery == null ? query : finalHighlightQuery,
152165
sharedCache
153166
)
154167
);
@@ -157,4 +170,12 @@ private FieldContext contextBuilders(
157170
}
158171
return new FieldContext(storedFieldsSpec, builders);
159172
}
173+
174+
private String getValueForConstantFieldType(FetchContext context, MappedFieldType fieldType){ //TODO Move this somewhere-else
175+
try {
176+
return (String) fieldType.valueFetcher(context.getSearchExecutionContext(), null).fetchValues(null,0, List.of()).get(0);
177+
} catch (IOException e) {
178+
throw new RuntimeException(e);
179+
}
180+
}
160181
}

0 commit comments

Comments
 (0)