Wildcard field bug fix for prefix + term queries. Wildcard syntax should not be supported. (#62085) (#62154)

Wildcard field bug fix for term and prefix queries.
We now escape any * or ? characters in the search string before delegating to the main wildcardQuery() method.

Closes #62081
This commit is contained in:
markharwood 2020-09-09 10:46:52 +01:00 committed by GitHub
parent 6c1700c343
commit 5a48895065
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 60 additions and 3 deletions

View File

@ -250,7 +250,7 @@ setup:
query:
prefix:
my_wildcard:
value: "hell*"
value: "hell"
- match: {hits.total.value: 1}

View File

@ -844,12 +844,28 @@ public class WildcardFieldMapper extends FieldMapper {
@Override
public Query termQuery(Object value, QueryShardContext context) {
return wildcardQuery(BytesRefs.toString(value), MultiTermQuery.CONSTANT_SCORE_REWRITE, context);
String searchTerm = BytesRefs.toString(value);
return wildcardQuery(escapeWildcardSyntax(searchTerm), MultiTermQuery.CONSTANT_SCORE_REWRITE, context);
}
private String escapeWildcardSyntax(String term) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < term.length();) {
final int c = term.codePointAt(i);
int length = Character.charCount(c);
// Escape any reserved characters
if (c == WildcardQuery.WILDCARD_STRING || c == WildcardQuery.WILDCARD_CHAR || c == WildcardQuery.WILDCARD_ESCAPE) {
result.append("\\");
}
result.appendCodePoint(c);
i += length;
}
return result.toString();
}
@Override
public Query prefixQuery(String value, MultiTermQuery.RewriteMethod method, QueryShardContext context) {
return wildcardQuery(value + "*", method, context);
return wildcardQuery(escapeWildcardSyntax(value) + "*", method, context);
}
@Override

View File

@ -180,6 +180,47 @@ public class WildcardFieldMapperTests extends ESTestCase {
}
public void testTermAndPrefixQueryIgnoreWildcardSyntax() throws IOException {
Directory dir = newDirectory();
IndexWriterConfig iwc = newIndexWriterConfig(WildcardFieldMapper.WILDCARD_ANALYZER);
iwc.setMergePolicy(newTieredMergePolicy(random()));
RandomIndexWriter iw = new RandomIndexWriter(random(), dir, iwc);
Document doc = new Document();
ParseContext.Document parseDoc = new ParseContext.Document();
addFields(parseDoc, doc, "f*oo?");
indexDoc(parseDoc, doc, iw);
iw.forceMerge(1);
DirectoryReader reader = iw.getReader();
IndexSearcher searcher = newSearcher(reader);
iw.close();
expectTermMatch(searcher, "f*oo*", 0);
expectTermMatch(searcher, "f*oo?", 1);
expectTermMatch(searcher, "*oo?", 0);
expectPrefixMatch(searcher, "f*o", 1);
expectPrefixMatch(searcher, "f*oo?", 1);
expectPrefixMatch(searcher, "f??o", 0);
reader.close();
dir.close();
}
private void expectTermMatch(IndexSearcher searcher, String term,long count) throws IOException {
Query q = wildcardFieldType.fieldType().termQuery(term, MOCK_QSC);
TopDocs td = searcher.search(q, 10, Sort.RELEVANCE);
assertThat(td.totalHits.value, equalTo(count));
}
private void expectPrefixMatch(IndexSearcher searcher, String term,long count) throws IOException {
Query q = wildcardFieldType.fieldType().prefixQuery(term, null, MOCK_QSC);
TopDocs td = searcher.search(q, 10, Sort.RELEVANCE);
assertThat(td.totalHits.value, equalTo(count));
}
public void testSearchResultsVersusKeywordField() throws IOException {
Directory dir = newDirectory();
IndexWriterConfig iwc = newIndexWriterConfig(WildcardFieldMapper.WILDCARD_ANALYZER);