Delegate wildcard query creation to MappedFieldType. (#34062)

* Delegate wildcard query creation to MappedFieldType.
* Disallow wildcard queries on collation fields.
* Disallow wildcard queries on non-string fields.
This commit is contained in:
Julie Tibshirani 2018-09-26 09:36:41 -07:00 committed by GitHub
parent 4fbe84edf6
commit de8bfb908f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 53 additions and 17 deletions

View File

@ -23,7 +23,6 @@ import com.ibm.icu.text.Collator;
import com.ibm.icu.text.RawCollationKey; import com.ibm.icu.text.RawCollationKey;
import com.ibm.icu.text.RuleBasedCollator; import com.ibm.icu.text.RuleBasedCollator;
import com.ibm.icu.util.ULocale; import com.ibm.icu.util.ULocale;
import org.apache.lucene.document.Field; import org.apache.lucene.document.Field;
import org.apache.lucene.document.SortedSetDocValuesField; import org.apache.lucene.document.SortedSetDocValuesField;
import org.apache.lucene.index.IndexOptions; import org.apache.lucene.index.IndexOptions;
@ -159,18 +158,23 @@ public class ICUCollationKeywordFieldMapper extends FieldMapper {
@Override @Override
public Query fuzzyQuery(Object value, Fuzziness fuzziness, int prefixLength, int maxExpansions, public Query fuzzyQuery(Object value, Fuzziness fuzziness, int prefixLength, int maxExpansions,
boolean transpositions) { boolean transpositions) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException("[fuzzy] queries are not supported on [" + CONTENT_TYPE + "] fields.");
} }
@Override @Override
public Query prefixQuery(String value, MultiTermQuery.RewriteMethod method, QueryShardContext context) { public Query prefixQuery(String value, MultiTermQuery.RewriteMethod method, QueryShardContext context) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException("[prefix] queries are not supported on [" + CONTENT_TYPE + "] fields.");
}
@Override
public Query wildcardQuery(String value, QueryShardContext context) {
throw new UnsupportedOperationException("[wildcard] queries are not supported on [" + CONTENT_TYPE + "] fields.");
} }
@Override @Override
public Query regexpQuery(String value, int flags, int maxDeterminizedStates, public Query regexpQuery(String value, int flags, int maxDeterminizedStates,
MultiTermQuery.RewriteMethod method, QueryShardContext context) { MultiTermQuery.RewriteMethod method, QueryShardContext context) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException("[regexp] queries are not supported on [" + CONTENT_TYPE + "] fields.");
} }
public static DocValueFormat COLLATE_FORMAT = new DocValueFormat() { public static DocValueFormat COLLATE_FORMAT = new DocValueFormat() {

View File

@ -121,6 +121,14 @@ public class CollationFieldTypeTests extends FieldTypeTestCase {
() -> ft.prefixQuery("prefix", null, null)); () -> ft.prefixQuery("prefix", null, null));
} }
public void testWildcardQuery() {
MappedFieldType ft = createDefaultFieldType();
ft.setName("field");
ft.setIndexOptions(IndexOptions.DOCS);
expectThrows(UnsupportedOperationException.class,
() -> ft.wildcardQuery("foo*", null));
}
public void testRangeQuery() { public void testRangeQuery() {
MappedFieldType ft = createDefaultFieldType(); MappedFieldType ft = createDefaultFieldType();
ft.setName("field"); ft.setName("field");

View File

@ -150,8 +150,17 @@ public class IndexFieldMapper extends MetadataFieldMapper {
+ " vs. " + values); + " vs. " + values);
} }
@Override
public Query wildcardQuery(String value, QueryShardContext context) {
if (isSameIndex(value, context.getFullyQualifiedIndex().getName())) {
return Queries.newMatchAllQuery();
} else {
return Queries.newMatchNoDocsQuery("Index didn't match. Index queried: " + context.index().getName() + " vs. " + value);
}
}
private boolean isSameIndex(Object value, String indexName) { private boolean isSameIndex(Object value, String indexName) {
String pattern = value instanceof BytesRef ? pattern = ((BytesRef) value).utf8ToString() : value.toString(); String pattern = value instanceof BytesRef ? ((BytesRef) value).utf8ToString() : value.toString();
return Regex.simpleMatch(pattern, indexName); return Regex.simpleMatch(pattern, indexName);
} }

View File

@ -345,6 +345,10 @@ public abstract class MappedFieldType extends FieldType {
throw new QueryShardException(context, "Can only use prefix queries on keyword and text fields - not on [" + name + "] which is of type [" + typeName() + "]"); throw new QueryShardException(context, "Can only use prefix queries on keyword and text fields - not on [" + name + "] which is of type [" + typeName() + "]");
} }
public Query wildcardQuery(String value, QueryShardContext context) {
throw new QueryShardException(context, "Can only use wildcard queries on keyword and text fields - not on [" + name + "] which is of type [" + typeName() + "]");
}
public Query regexpQuery(String value, int flags, int maxDeterminizedStates, @Nullable MultiTermQuery.RewriteMethod method, QueryShardContext context) { public Query regexpQuery(String value, int flags, int maxDeterminizedStates, @Nullable MultiTermQuery.RewriteMethod method, QueryShardContext context) {
throw new QueryShardException(context, "Can only use regexp queries on keyword and text fields - not on [" + name + "] which is of type [" + typeName() + "]"); throw new QueryShardException(context, "Can only use regexp queries on keyword and text fields - not on [" + name + "] which is of type [" + typeName() + "]");
} }

View File

@ -22,6 +22,8 @@ package org.elasticsearch.index.mapper;
import java.util.List; import java.util.List;
import org.apache.lucene.index.Term; import org.apache.lucene.index.Term;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.MatchNoDocsQuery;
import org.apache.lucene.search.TermInSetQuery; import org.apache.lucene.search.TermInSetQuery;
import org.apache.lucene.search.FuzzyQuery; import org.apache.lucene.search.FuzzyQuery;
import org.apache.lucene.search.MultiTermQuery; import org.apache.lucene.search.MultiTermQuery;
@ -29,6 +31,7 @@ import org.apache.lucene.search.PrefixQuery;
import org.apache.lucene.search.Query; import org.apache.lucene.search.Query;
import org.apache.lucene.search.RegexpQuery; import org.apache.lucene.search.RegexpQuery;
import org.apache.lucene.search.TermRangeQuery; import org.apache.lucene.search.TermRangeQuery;
import org.apache.lucene.search.WildcardQuery;
import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.BytesRef;
import org.elasticsearch.common.lucene.BytesRefs; import org.elasticsearch.common.lucene.BytesRefs;
import org.elasticsearch.common.unit.Fuzziness; import org.elasticsearch.common.unit.Fuzziness;
@ -74,6 +77,16 @@ public abstract class StringFieldType extends TermBasedFieldType {
return query; return query;
} }
@Override
public Query wildcardQuery(String value, QueryShardContext context) {
Query termQuery = termQuery(value, context);
if (termQuery instanceof MatchNoDocsQuery || termQuery instanceof MatchAllDocsQuery) {
return termQuery;
}
Term term = MappedFieldType.extractTerm(termQuery);
return new WildcardQuery(term);
}
@Override @Override
public Query regexpQuery(String value, int flags, int maxDeterminizedStates, public Query regexpQuery(String value, int flags, int maxDeterminizedStates,
MultiTermQuery.RewriteMethod method, QueryShardContext context) { MultiTermQuery.RewriteMethod method, QueryShardContext context) {

View File

@ -20,8 +20,6 @@
package org.elasticsearch.index.query; package org.elasticsearch.index.query;
import org.apache.lucene.index.Term; import org.apache.lucene.index.Term;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.MatchNoDocsQuery;
import org.apache.lucene.search.MultiTermQuery; import org.apache.lucene.search.MultiTermQuery;
import org.apache.lucene.search.Query; import org.apache.lucene.search.Query;
import org.apache.lucene.search.WildcardQuery; import org.apache.lucene.search.WildcardQuery;
@ -185,20 +183,20 @@ public class WildcardQueryBuilder extends AbstractQueryBuilder<WildcardQueryBuil
@Override @Override
protected Query doToQuery(QueryShardContext context) throws IOException { protected Query doToQuery(QueryShardContext context) throws IOException {
MappedFieldType fieldType = context.fieldMapper(fieldName); MappedFieldType fieldType = context.fieldMapper(fieldName);
Term term;
Query query;
if (fieldType == null) { if (fieldType == null) {
term = new Term(fieldName, BytesRefs.toBytesRef(value)); Term term = new Term(fieldName, BytesRefs.toBytesRef(value));
query = new WildcardQuery(term);
} else { } else {
Query termQuery = fieldType.termQuery(value, context); query = fieldType.wildcardQuery(value, context);
if (termQuery instanceof MatchNoDocsQuery || termQuery instanceof MatchAllDocsQuery) {
return termQuery;
}
term = MappedFieldType.extractTerm(termQuery);
} }
WildcardQuery query = new WildcardQuery(term); if (query instanceof MultiTermQuery) {
MultiTermQuery.RewriteMethod rewriteMethod = QueryParsers.parseRewriteMethod(rewrite, null, LoggingDeprecationHandler.INSTANCE); MultiTermQuery.RewriteMethod rewriteMethod = QueryParsers.parseRewriteMethod(
QueryParsers.setRewriteMethod(query, rewriteMethod); rewrite, null, LoggingDeprecationHandler.INSTANCE);
QueryParsers.setRewriteMethod((MultiTermQuery) query, rewriteMethod);
}
return query; return query;
} }