Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions docs/changelog/129326.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pr: 129326
summary: Check positions on `MultiPhraseQueries` as well as phrase queries
area: Search
type: bug
issues:
- 123871
Original file line number Diff line number Diff line change
Expand Up @@ -200,3 +200,50 @@
query: quick brown
operator: and
- match: { hits.total: 2 }
---
# Tests that this returns 400, and not 500 (#123871)
"Test multi_match phrase with no positions":
- requires:
cluster_features: [ "search.multi.match.checks.positions" ]
reason: "This previously resulted in a 5xx error code"
- do:
indices.create:
index: test
body:
settings:
analysis:
filter:
syns:
type: synonym
synonyms: [ "quick,fast" ]
analyzer:
syns:
tokenizer: standard
filter: [ "syns" ]
mappings:
properties:
field1:
type: text
index_options: freqs
analyzer: syns

- do:
index:
index: test
id: "1"
body:
field1: the quick brown fox

- do:
catch: bad_request
search:
body:
query:
multi_match:
query: the fast brown
type: phrase
fields:
- field1
- match: { status: 400 }
- match: { error.root_cause.0.type: query_shard_exception }
- match: { error.root_cause.0.reason: "failed to create query: field:[field1] was indexed without position data; cannot run MultiPhraseQuery" }
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ public Query prefixQuery(

private void checkForPositions() {
if (getTextSearchInfo().hasPositions() == false) {
throw new IllegalStateException("field:[" + name() + "] was indexed without position data; cannot run PhraseQuery");
throw new IllegalArgumentException("field:[" + name() + "] was indexed without position data; cannot run PhraseQuery");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,9 @@ public void testPhraseQueryOnFieldWithNoPositions() throws Exception {
Exception.class,
prepareSearch("test").setQuery(queryStringQuery("f4:\"eggplant parmesan\"").lenient(false))
);
IllegalStateException ise = (IllegalStateException) ExceptionsHelper.unwrap(exc, IllegalStateException.class);
assertNotNull(ise);
assertThat(ise.getMessage(), containsString("field:[f4] was indexed without position data; cannot run PhraseQuery"));
IllegalArgumentException iae = (IllegalArgumentException) ExceptionsHelper.unwrap(exc, IllegalArgumentException.class);
assertNotNull(iae);
assertThat(iae.getMessage(), containsString("field:[f4] was indexed without position data; cannot run PhraseQuery"));
}

public void testBooleanStrictQuery() throws Exception {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -894,17 +894,19 @@ public IntervalsSource rangeIntervals(
return Intervals.range(lowerTerm, upperTerm, includeLower, includeUpper, IndexSearcher.getMaxClauseCount());
}

private void checkForPositions() {
private void checkForPositions(boolean multi) {
if (getTextSearchInfo().hasPositions() == false) {
throw new IllegalStateException("field:[" + name() + "] was indexed without position data; cannot run PhraseQuery");
throw new IllegalArgumentException(
"field:[" + name() + "] was indexed without position data; cannot run " + (multi ? "MultiPhraseQuery" : "PhraseQuery")
);
}
}

@Override
public Query phraseQuery(TokenStream stream, int slop, boolean enablePosIncrements, SearchExecutionContext context)
throws IOException {
String field = name();
checkForPositions();
checkForPositions(false);
// we can't use the index_phrases shortcut with slop, if there are gaps in the stream,
// or if the incoming token stream is the output of a token graph due to
// https://issues.apache.org/jira/browse/LUCENE-8916
Expand Down Expand Up @@ -939,6 +941,7 @@ public Query phraseQuery(TokenStream stream, int slop, boolean enablePosIncremen
public Query multiPhraseQuery(TokenStream stream, int slop, boolean enablePositionIncrements, SearchExecutionContext context)
throws IOException {
String field = name();
checkForPositions(true);
if (indexPhrases && slop == 0 && hasGaps(stream) == false) {
stream = new FixedShingleFilter(stream, 2);
field = field + FAST_PHRASE_SUFFIX;
Expand All @@ -959,7 +962,7 @@ private static int countTokens(TokenStream ts) throws IOException {
@Override
public Query phrasePrefixQuery(TokenStream stream, int slop, int maxExpansions, SearchExecutionContext context) throws IOException {
if (countTokens(stream) > 1) {
checkForPositions();
checkForPositions(false);
}
return analyzePhrasePrefix(stream, slop, maxExpansions);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,16 @@ public Set<NodeFeature> getFeatures() {
);
public static final NodeFeature RESCORER_MISSING_FIELD_BAD_REQUEST = new NodeFeature("search.rescorer.missing.field.bad.request");
public static final NodeFeature INT_SORT_FOR_INT_SHORT_BYTE_FIELDS = new NodeFeature("search.sort.int_sort_for_int_short_byte_fields");
static final NodeFeature MULTI_MATCH_CHECKS_POSITIONS = new NodeFeature("search.multi.match.checks.positions");

@Override
public Set<NodeFeature> getTestFeatures() {
return Set.of(
RETRIEVER_RESCORER_ENABLED,
COMPLETION_FIELD_SUPPORTS_DUPLICATE_SUGGESTIONS,
RESCORER_MISSING_FIELD_BAD_REQUEST,
INT_SORT_FOR_INT_SHORT_BYTE_FIELDS
INT_SORT_FOR_INT_SHORT_BYTE_FIELDS,
MULTI_MATCH_CHECKS_POSITIONS
);
}
}
Loading