Throw parsing error if prefix query contains multiple fields
Prefix Query, like many other queries, used to parse when the query refers to multiple fields and the last one would win. We rather throw an exception now instead. Also added tests for short prefix quer variant.
This commit is contained in:
parent
11e4b0168b
commit
69c2deedc7
|
@ -64,7 +64,7 @@ public class PrefixQueryBuilder extends AbstractQueryBuilder<PrefixQueryBuilder>
|
||||||
throw new IllegalArgumentException("field name is null or empty");
|
throw new IllegalArgumentException("field name is null or empty");
|
||||||
}
|
}
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
throw new IllegalArgumentException("value cannot be null.");
|
throw new IllegalArgumentException("value cannot be null");
|
||||||
}
|
}
|
||||||
this.fieldName = fieldName;
|
this.fieldName = fieldName;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
|
@ -120,7 +120,7 @@ public class PrefixQueryBuilder extends AbstractQueryBuilder<PrefixQueryBuilder>
|
||||||
public static Optional<PrefixQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException {
|
public static Optional<PrefixQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException {
|
||||||
XContentParser parser = parseContext.parser();
|
XContentParser parser = parseContext.parser();
|
||||||
|
|
||||||
String fieldName = parser.currentName();
|
String fieldName = null;
|
||||||
String value = null;
|
String value = null;
|
||||||
String rewrite = null;
|
String rewrite = null;
|
||||||
|
|
||||||
|
@ -134,6 +134,10 @@ public class PrefixQueryBuilder extends AbstractQueryBuilder<PrefixQueryBuilder>
|
||||||
} else if (parseContext.isDeprecatedSetting(currentFieldName)) {
|
} else if (parseContext.isDeprecatedSetting(currentFieldName)) {
|
||||||
// skip
|
// skip
|
||||||
} else if (token == XContentParser.Token.START_OBJECT) {
|
} else if (token == XContentParser.Token.START_OBJECT) {
|
||||||
|
if (fieldName != null) {
|
||||||
|
throw new ParsingException(parser.getTokenLocation(), "[prefix] query doesn't support multiple fields, found ["
|
||||||
|
+ fieldName + "] and [" + currentFieldName + "]");
|
||||||
|
}
|
||||||
fieldName = currentFieldName;
|
fieldName = currentFieldName;
|
||||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||||
if (token == XContentParser.Token.FIELD_NAME) {
|
if (token == XContentParser.Token.FIELD_NAME) {
|
||||||
|
@ -149,19 +153,16 @@ public class PrefixQueryBuilder extends AbstractQueryBuilder<PrefixQueryBuilder>
|
||||||
rewrite = parser.textOrNull();
|
rewrite = parser.textOrNull();
|
||||||
} else {
|
} else {
|
||||||
throw new ParsingException(parser.getTokenLocation(),
|
throw new ParsingException(parser.getTokenLocation(),
|
||||||
"[regexp] query does not support [" + currentFieldName + "]");
|
"[prefix] query does not support [" + currentFieldName + "]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fieldName = currentFieldName;
|
fieldName = currentFieldName;
|
||||||
value = parser.textOrNull();
|
value = parser.textOrNull();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value == null) {
|
|
||||||
throw new ParsingException(parser.getTokenLocation(), "No value specified for prefix query");
|
|
||||||
}
|
|
||||||
return Optional.of(new PrefixQueryBuilder(fieldName, value)
|
return Optional.of(new PrefixQueryBuilder(fieldName, value)
|
||||||
.rewrite(rewrite)
|
.rewrite(rewrite)
|
||||||
.boost(boost)
|
.boost(boost)
|
||||||
|
|
|
@ -23,9 +23,12 @@ import org.apache.lucene.index.Term;
|
||||||
import org.apache.lucene.search.MultiTermQuery;
|
import org.apache.lucene.search.MultiTermQuery;
|
||||||
import org.apache.lucene.search.PrefixQuery;
|
import org.apache.lucene.search.PrefixQuery;
|
||||||
import org.apache.lucene.search.Query;
|
import org.apache.lucene.search.Query;
|
||||||
|
import org.elasticsearch.common.ParsingException;
|
||||||
import org.elasticsearch.test.AbstractQueryTestCase;
|
import org.elasticsearch.test.AbstractQueryTestCase;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.elasticsearch.index.query.QueryBuilders.prefixQuery;
|
import static org.elasticsearch.index.query.QueryBuilders.prefixQuery;
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
@ -35,16 +38,32 @@ public class PrefixQueryBuilderTests extends AbstractQueryTestCase<PrefixQueryBu
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected PrefixQueryBuilder doCreateTestQueryBuilder() {
|
protected PrefixQueryBuilder doCreateTestQueryBuilder() {
|
||||||
String fieldName = randomBoolean() ? STRING_FIELD_NAME : randomAsciiOfLengthBetween(1, 10);
|
PrefixQueryBuilder query = randomPrefixQuery();
|
||||||
String value = randomAsciiOfLengthBetween(1, 10);
|
|
||||||
PrefixQueryBuilder query = new PrefixQueryBuilder(fieldName, value);
|
|
||||||
|
|
||||||
if (randomBoolean()) {
|
if (randomBoolean()) {
|
||||||
query.rewrite(getRandomRewriteMethod());
|
query.rewrite(getRandomRewriteMethod());
|
||||||
}
|
}
|
||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Map<String, PrefixQueryBuilder> getAlternateVersions() {
|
||||||
|
Map<String, PrefixQueryBuilder> alternateVersions = new HashMap<>();
|
||||||
|
PrefixQueryBuilder prefixQuery = randomPrefixQuery();
|
||||||
|
String contentString = "{\n" +
|
||||||
|
" \"prefix\" : {\n" +
|
||||||
|
" \"" + prefixQuery.fieldName() + "\" : \"" + prefixQuery.value() + "\"\n" +
|
||||||
|
" }\n" +
|
||||||
|
"}";
|
||||||
|
alternateVersions.put(contentString, prefixQuery);
|
||||||
|
return alternateVersions;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PrefixQueryBuilder randomPrefixQuery() {
|
||||||
|
String fieldName = randomBoolean() ? STRING_FIELD_NAME : randomAsciiOfLengthBetween(1, 10);
|
||||||
|
String value = randomAsciiOfLengthBetween(1, 10);
|
||||||
|
return new PrefixQueryBuilder(fieldName, value);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doAssertLuceneQuery(PrefixQueryBuilder queryBuilder, Query query, QueryShardContext context) throws IOException {
|
protected void doAssertLuceneQuery(PrefixQueryBuilder queryBuilder, Query query, QueryShardContext context) throws IOException {
|
||||||
assertThat(query, instanceOf(PrefixQuery.class));
|
assertThat(query, instanceOf(PrefixQuery.class));
|
||||||
|
@ -60,16 +79,16 @@ public class PrefixQueryBuilderTests extends AbstractQueryTestCase<PrefixQueryBu
|
||||||
} else {
|
} else {
|
||||||
new PrefixQueryBuilder("", "text");
|
new PrefixQueryBuilder("", "text");
|
||||||
}
|
}
|
||||||
fail("cannot be null or empty");
|
fail("field name is null or empty");
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
// expected
|
assertEquals("field name is null or empty", e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
new PrefixQueryBuilder("field", null);
|
new PrefixQueryBuilder("field", null);
|
||||||
fail("cannot be null or empty");
|
fail("value cannot be null");
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
// expected
|
assertEquals("value cannot be null", e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,4 +122,25 @@ public class PrefixQueryBuilderTests extends AbstractQueryTestCase<PrefixQueryBu
|
||||||
assertEquals("Can only use prefix queries on keyword and text fields - not on [mapped_int] which is of type [integer]",
|
assertEquals("Can only use prefix queries on keyword and text fields - not on [mapped_int] which is of type [integer]",
|
||||||
e.getMessage());
|
e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testParseFailsWithMultipleFields() throws IOException {
|
||||||
|
String json =
|
||||||
|
"{\n" +
|
||||||
|
" \"prefix\": {\n" +
|
||||||
|
" \"user1\": {\n" +
|
||||||
|
" \"value\": \"ki\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" \"user2\": {\n" +
|
||||||
|
" \"value\": \"ki\"\n" +
|
||||||
|
" }\n" +
|
||||||
|
" }\n" +
|
||||||
|
"}";
|
||||||
|
|
||||||
|
try {
|
||||||
|
parseQuery(json);
|
||||||
|
fail("parseQuery should have failed");
|
||||||
|
} catch(ParsingException e) {
|
||||||
|
assertEquals("[prefix] query doesn't support multiple fields, found [user1] and [user2]", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue