Check positions on MultiPhraseQueries as well as phrase queries (#129326)
This commit is contained in:
parent
87ed699352
commit
3988ee1935
|
@ -0,0 +1,6 @@
|
|||
pr: 129326
|
||||
summary: Check positions on `MultiPhraseQueries` as well as phrase queries
|
||||
area: Search
|
||||
type: bug
|
||||
issues:
|
||||
- 123871
|
|
@ -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" }
|
||||
|
|
|
@ -362,7 +362,7 @@ public class SearchAsYouTypeFieldMapper extends FieldMapper {
|
|||
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -178,9 +178,9 @@ public class QueryStringIT extends ESIntegTestCase {
|
|||
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 {
|
||||
|
|
|
@ -894,9 +894,11 @@ public final class TextFieldMapper extends FieldMapper {
|
|||
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")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -904,7 +906,7 @@ public final class TextFieldMapper extends FieldMapper {
|
|||
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
|
||||
|
@ -939,6 +941,7 @@ public final class TextFieldMapper extends FieldMapper {
|
|||
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;
|
||||
|
@ -959,7 +962,7 @@ public final class TextFieldMapper extends FieldMapper {
|
|||
@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);
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ public final class SearchFeatures implements FeatureSpecification {
|
|||
);
|
||||
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() {
|
||||
|
@ -37,7 +38,8 @@ public final class SearchFeatures implements FeatureSpecification {
|
|||
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…
Reference in New Issue