Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
2faea54
Add ability to set "max_analyzed_offet" implicitly to "index.highlight
svilen-mihaylov-elastic Dec 17, 2024
f26f2c7
Add test
svilen-mihaylov-elastic Jan 2, 2025
b18a696
Tweak tests
svilen-mihaylov-elastic Jan 2, 2025
a6a4623
Merge branch 'main' into svilen-mihaylov/112822
svilen-mihaylov-elastic Jan 2, 2025
f139e85
Fix test and update docs
svilen-mihaylov-elastic Jan 2, 2025
1285b01
Remove logger info
svilen-mihaylov-elastic Jan 2, 2025
eb6725e
Added test for zero
svilen-mihaylov-elastic Jan 2, 2025
4ae0be1
Add a capability
svilen-mihaylov-elastic Jan 3, 2025
c0c2127
Add test for -1
svilen-mihaylov-elastic Jan 3, 2025
c6d2920
Exclude test from REST compatibility
svilen-mihaylov-elastic Jan 3, 2025
703f438
Add Highlight_ to search capability name
svilen-mihaylov-elastic Jan 3, 2025
bf90d9a
Merge branch 'main' into svilen-mihaylov/112822
svilen-mihaylov-elastic Jan 6, 2025
9fc0fcb
Disallow 0
svilen-mihaylov-elastic Jan 6, 2025
6fd85f3
Fix test
svilen-mihaylov-elastic Jan 6, 2025
5abd2c4
Should SUCCEED -> Should FAIL
svilen-mihaylov-elastic Jan 6, 2025
0867480
Oops wrong test
svilen-mihaylov-elastic Jan 6, 2025
f889a61
Rename another test
svilen-mihaylov-elastic Jan 6, 2025
dc54b64
Remove test with =0 for now.
svilen-mihaylov-elastic Jan 6, 2025
909d90f
Restore test with zero
svilen-mihaylov-elastic Jan 6, 2025
7337f1d
Merge branch 'main' into svilen-mihaylov/112822
svilen-mihaylov-elastic Jan 6, 2025
13cda1e
Merge branch 'main' into svilen-mihaylov/112822
svilen-mihaylov-elastic Jan 7, 2025
15bc509
Fix merge
svilen-mihaylov-elastic Jan 7, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import org.elasticsearch.index.mapper.annotatedtext.AnnotatedTextFieldMapper.AnnotatedText;
import org.elasticsearch.index.query.SearchExecutionContext;
import org.elasticsearch.lucene.search.uhighlight.CustomUnifiedHighlighter;
import org.elasticsearch.lucene.search.uhighlight.QueryMaxAnalyzedOffset;
import org.elasticsearch.search.fetch.FetchSubPhase.HitContext;
import org.elasticsearch.search.fetch.subphase.highlight.DefaultHighlighter;
import org.elasticsearch.search.fetch.subphase.highlight.SearchHighlightContext;
Expand Down Expand Up @@ -52,7 +53,7 @@ protected List<Object> loadFieldValues(
}

@Override
protected Analyzer wrapAnalyzer(Analyzer analyzer, Integer maxAnalyzedOffset) {
protected Analyzer wrapAnalyzer(Analyzer analyzer, QueryMaxAnalyzedOffset maxAnalyzedOffset) {
return new AnnotatedHighlighterAnalyzer(super.wrapAnalyzer(analyzer, maxAnalyzedOffset));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import org.elasticsearch.index.mapper.annotatedtext.AnnotatedTextFieldMapper.AnnotatedText;
import org.elasticsearch.index.mapper.annotatedtext.AnnotatedTextFieldMapper.AnnotationAnalyzerWrapper;
import org.elasticsearch.lucene.search.uhighlight.CustomUnifiedHighlighter;
import org.elasticsearch.lucene.search.uhighlight.QueryMaxAnalyzedOffset;
import org.elasticsearch.lucene.search.uhighlight.Snippet;
import org.elasticsearch.search.fetch.subphase.highlight.LimitTokenOffsetAnalyzer;
import org.elasticsearch.test.ESTestCase;
Expand Down Expand Up @@ -85,7 +86,7 @@ private void assertHighlightOneDoc(
int noMatchSize,
String[] expectedPassages,
int maxAnalyzedOffset,
Integer queryMaxAnalyzedOffset
Integer queryMaxAnalyzedOffsetIn
) throws Exception {

try (Directory dir = newDirectory()) {
Expand Down Expand Up @@ -116,8 +117,9 @@ private void assertHighlightOneDoc(
for (int i = 0; i < markedUpInputs.length; i++) {
annotations[i] = AnnotatedText.parse(markedUpInputs[i]);
}
QueryMaxAnalyzedOffset queryMaxAnalyzedOffset = QueryMaxAnalyzedOffset.create(queryMaxAnalyzedOffsetIn, maxAnalyzedOffset);
if (queryMaxAnalyzedOffset != null) {
wrapperAnalyzer = new LimitTokenOffsetAnalyzer(wrapperAnalyzer, queryMaxAnalyzedOffset);
wrapperAnalyzer = new LimitTokenOffsetAnalyzer(wrapperAnalyzer, queryMaxAnalyzedOffset.getNotNull());
}
AnnotatedHighlighterAnalyzer hiliteAnalyzer = new AnnotatedHighlighterAnalyzer(wrapperAnalyzer);
hiliteAnalyzer.setAnnotations(annotations);
Expand Down Expand Up @@ -311,6 +313,19 @@ public void testExceedMaxAnalyzedOffset() throws Exception {
e.getMessage()
);

// Same as before, but force using index maxOffset (20) as queryMaxOffset by passing -1.
assertHighlightOneDoc(
"text",
new String[] { "[Long Text exceeds](Long+Text+exceeds) MAX analyzed offset)" },
query,
Locale.ROOT,
breakIterator,
0,
new String[] { "Long Text [exceeds](_hit_term=exceeds) MAX analyzed offset)" },
20,
-1
);

assertHighlightOneDoc(
"text",
new String[] { "[Long Text Exceeds](Long+Text+Exceeds) MAX analyzed offset [Long Text Exceeds](Long+Text+Exceeds)" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class CustomFieldHighlighter extends FieldHighlighter {
private final Locale breakIteratorLocale;
private final int noMatchSize;
private String fieldValue;
private final Integer queryMaxAnalyzedOffset;
private final QueryMaxAnalyzedOffset queryMaxAnalyzedOffset;

CustomFieldHighlighter(
String field,
Expand All @@ -47,7 +47,7 @@ class CustomFieldHighlighter extends FieldHighlighter {
PassageFormatter passageFormatter,
Comparator<Passage> passageSortComparator,
int noMatchSize,
Integer queryMaxAnalyzedOffset
QueryMaxAnalyzedOffset queryMaxAnalyzedOffset
) {
super(
field,
Expand Down Expand Up @@ -113,7 +113,7 @@ protected Passage[] getSummaryPassagesNoHighlight(int maxPassages) {
@Override
protected Passage[] highlightOffsetsEnums(OffsetsEnum off) throws IOException {
if (queryMaxAnalyzedOffset != null) {
off = new LimitedOffsetsEnum(off, queryMaxAnalyzedOffset);
off = new LimitedOffsetsEnum(off, queryMaxAnalyzedOffset.getNotNull());
}
return super.highlightOffsetsEnums(off);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public final class CustomUnifiedHighlighter extends UnifiedHighlighter {
private final int noMatchSize;
private final CustomFieldHighlighter fieldHighlighter;
private final int maxAnalyzedOffset;
private final Integer queryMaxAnalyzedOffset;
private final QueryMaxAnalyzedOffset queryMaxAnalyzedOffset;

/**
* Creates a new instance of {@link CustomUnifiedHighlighter}
Expand Down Expand Up @@ -94,7 +94,7 @@ public CustomUnifiedHighlighter(
int noMatchSize,
int maxPassages,
int maxAnalyzedOffset,
Integer queryMaxAnalyzedOffset,
QueryMaxAnalyzedOffset queryMaxAnalyzedOffset,
boolean requireFieldMatch,
boolean weightMatchesEnabled
) {
Expand Down Expand Up @@ -125,9 +125,9 @@ public Snippet[] highlightField(LeafReader reader, int docId, CheckedSupplier<St
return null;
}
int fieldValueLength = fieldValue.length();
if (((queryMaxAnalyzedOffset == null || queryMaxAnalyzedOffset > maxAnalyzedOffset)
if ((queryMaxAnalyzedOffset == null || queryMaxAnalyzedOffset.getNotNull() > maxAnalyzedOffset)
&& (getOffsetSource(field) == OffsetSource.ANALYSIS)
&& (fieldValueLength > maxAnalyzedOffset))) {
&& (fieldValueLength > maxAnalyzedOffset)) {
throw new IllegalArgumentException(
"The length ["
+ fieldValueLength
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

package org.elasticsearch.lucene.search.uhighlight;

public class QueryMaxAnalyzedOffset {
private final int queryMaxAnalyzedOffset;

private QueryMaxAnalyzedOffset(final int queryMaxAnalyzedOffset) {
// If we have a negative value, grab value for the actual maximum from the index.
this.queryMaxAnalyzedOffset = queryMaxAnalyzedOffset;
}

public static QueryMaxAnalyzedOffset create(final Integer queryMaxAnalyzedOffset, final int indexMaxAnalyzedOffset) {
if (queryMaxAnalyzedOffset == null) {
return null;
}
return new QueryMaxAnalyzedOffset(queryMaxAnalyzedOffset < 0 ? indexMaxAnalyzedOffset : queryMaxAnalyzedOffset);
}

public int getNotNull() {
return queryMaxAnalyzedOffset;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.elasticsearch.lucene.search.uhighlight.BoundedBreakIteratorScanner;
import org.elasticsearch.lucene.search.uhighlight.CustomPassageFormatter;
import org.elasticsearch.lucene.search.uhighlight.CustomUnifiedHighlighter;
import org.elasticsearch.lucene.search.uhighlight.QueryMaxAnalyzedOffset;
import org.elasticsearch.lucene.search.uhighlight.Snippet;
import org.elasticsearch.search.fetch.FetchContext;
import org.elasticsearch.search.fetch.FetchSubPhase;
Expand Down Expand Up @@ -121,7 +122,10 @@ CustomUnifiedHighlighter buildHighlighter(FieldHighlightContext fieldContext) {
int maxAnalyzedOffset = indexSettings.getHighlightMaxAnalyzedOffset();
boolean weightMatchesEnabled = indexSettings.isWeightMatchesEnabled();
int numberOfFragments = fieldContext.field.fieldOptions().numberOfFragments();
Integer queryMaxAnalyzedOffset = fieldContext.field.fieldOptions().maxAnalyzedOffset();
QueryMaxAnalyzedOffset queryMaxAnalyzedOffset = QueryMaxAnalyzedOffset.create(
fieldContext.field.fieldOptions().maxAnalyzedOffset(),
maxAnalyzedOffset
);
Analyzer analyzer = wrapAnalyzer(
fieldContext.context.getSearchExecutionContext().getIndexAnalyzer(f -> Lucene.KEYWORD_ANALYZER),
queryMaxAnalyzedOffset
Expand Down Expand Up @@ -171,7 +175,7 @@ CustomUnifiedHighlighter buildHighlighter(FieldHighlightContext fieldContext) {
fieldContext.field.fieldOptions().noMatchSize(),
highlighterNumberOfFragments,
maxAnalyzedOffset,
fieldContext.field.fieldOptions().maxAnalyzedOffset(),
queryMaxAnalyzedOffset,
fieldContext.field.fieldOptions().requireFieldMatch(),
weightMatchesEnabled
);
Expand All @@ -186,9 +190,9 @@ protected PassageFormatter getPassageFormatter(SearchHighlightContext.Field fiel
);
}

protected Analyzer wrapAnalyzer(Analyzer analyzer, Integer maxAnalyzedOffset) {
protected Analyzer wrapAnalyzer(Analyzer analyzer, QueryMaxAnalyzedOffset maxAnalyzedOffset) {
if (maxAnalyzedOffset != null) {
analyzer = new LimitTokenOffsetAnalyzer(analyzer, maxAnalyzedOffset);
analyzer = new LimitTokenOffsetAnalyzer(analyzer, maxAnalyzedOffset.getNotNull());
}
return analyzer;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.IndexSettings;
import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.lucene.search.uhighlight.QueryMaxAnalyzedOffset;
import org.elasticsearch.search.fetch.FetchContext;
import org.elasticsearch.search.fetch.FetchSubPhase;

Expand Down Expand Up @@ -107,7 +108,10 @@ public HighlightField highlight(FieldHighlightContext fieldContext) throws IOExc
ArrayList<OrderedTextFragment> fragsList = new ArrayList<>();
List<Object> textsToHighlight;
final int maxAnalyzedOffset = context.getSearchExecutionContext().getIndexSettings().getHighlightMaxAnalyzedOffset();
Integer queryMaxAnalyzedOffset = fieldContext.field.fieldOptions().maxAnalyzedOffset();
QueryMaxAnalyzedOffset queryMaxAnalyzedOffset = QueryMaxAnalyzedOffset.create(
fieldContext.field.fieldOptions().maxAnalyzedOffset(),
maxAnalyzedOffset
);
Analyzer analyzer = wrapAnalyzer(
context.getSearchExecutionContext().getIndexAnalyzer(f -> Lucene.KEYWORD_ANALYZER),
queryMaxAnalyzedOffset
Expand All @@ -119,7 +123,8 @@ public HighlightField highlight(FieldHighlightContext fieldContext) throws IOExc
for (Object textToHighlight : textsToHighlight) {
String text = convertFieldValue(fieldType, textToHighlight);
int textLength = text.length();
if ((queryMaxAnalyzedOffset == null || queryMaxAnalyzedOffset > maxAnalyzedOffset) && (textLength > maxAnalyzedOffset)) {
if ((queryMaxAnalyzedOffset == null || queryMaxAnalyzedOffset.getNotNull() > maxAnalyzedOffset)
&& (textLength > maxAnalyzedOffset)) {
throw new IllegalArgumentException(
"The length ["
+ textLength
Expand Down Expand Up @@ -241,9 +246,9 @@ private static int findGoodEndForNoHighlightExcerpt(int noMatchSize, Analyzer an
}
}

private static Analyzer wrapAnalyzer(Analyzer analyzer, Integer maxAnalyzedOffset) {
private static Analyzer wrapAnalyzer(Analyzer analyzer, QueryMaxAnalyzedOffset maxAnalyzedOffset) {
if (maxAnalyzedOffset != null) {
return new LimitTokenOffsetAnalyzer(analyzer, maxAnalyzedOffset);
return new LimitTokenOffsetAnalyzer(analyzer, maxAnalyzedOffset.getNotNull());
}
return analyzer;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ private void assertHighlightOneDoc(
noMatchSize,
expectedPassages.length,
maxAnalyzedOffset,
queryMaxAnalyzedOffset,
QueryMaxAnalyzedOffset.create(queryMaxAnalyzedOffset, maxAnalyzedOffset),
true,
true
);
Expand Down
Loading