diff --git a/core/src/main/java/org/elasticsearch/index/query/WildcardQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/WildcardQueryBuilder.java
index d142e3520801e..1320fe9c1a0f3 100644
--- a/core/src/main/java/org/elasticsearch/index/query/WildcardQueryBuilder.java
+++ b/core/src/main/java/org/elasticsearch/index/query/WildcardQueryBuilder.java
@@ -19,9 +19,20 @@
package org.elasticsearch.index.query;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.search.MultiTermQuery;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.WildcardQuery;
+import org.apache.lucene.util.BytesRef;
+import org.elasticsearch.common.Strings;
+import org.elasticsearch.common.io.stream.StreamInput;
+import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.index.mapper.MappedFieldType;
+import org.elasticsearch.index.query.support.QueryParsers;
import java.io.IOException;
+import java.util.Objects;
/**
* Implements the wildcard search query. Supported wildcards are *, which
@@ -35,9 +46,9 @@ public class WildcardQueryBuilder extends AbstractQueryBuilder* or
* ?.
*
- * @param name The field name
- * @param wildcard The wildcard query string
+ * @param fieldName The field name
+ * @param value The wildcard query string
*/
- public WildcardQueryBuilder(String name, String wildcard) {
- this.name = name;
- this.wildcard = wildcard;
+ public WildcardQueryBuilder(String fieldName, String value) {
+ this.fieldName = fieldName;
+ this.value = value;
+ }
+
+ public String fieldName() {
+ return fieldName;
+ }
+
+ public String value() {
+ return value;
}
public WildcardQueryBuilder rewrite(String rewrite) {
@@ -64,11 +83,20 @@ public WildcardQueryBuilder rewrite(String rewrite) {
return this;
}
+ public String rewrite() {
+ return this.rewrite;
+ }
+
+ @Override
+ public String getName() {
+ return NAME;
+ }
+
@Override
public void doXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject(NAME);
- builder.startObject(name);
- builder.field("wildcard", wildcard);
+ builder.startObject(fieldName);
+ builder.field("wildcard", value);
if (rewrite != null) {
builder.field("rewrite", rewrite);
}
@@ -78,7 +106,60 @@ public void doXContent(XContentBuilder builder, Params params) throws IOExceptio
}
@Override
- public String getName() {
- return NAME;
+ protected Query doToQuery(QueryParseContext parseContext) throws IOException {
+ String indexFieldName;
+ BytesRef valueBytes;
+
+ MappedFieldType fieldType = parseContext.fieldMapper(fieldName);
+ if (fieldType != null) {
+ indexFieldName = fieldType.names().indexName();
+ valueBytes = fieldType.indexedValueForSearch(value);
+ } else {
+ indexFieldName = fieldName;
+ valueBytes = new BytesRef(value);
+ }
+
+ WildcardQuery query = new WildcardQuery(new Term(indexFieldName, valueBytes));
+ MultiTermQuery.RewriteMethod rewriteMethod = QueryParsers.parseRewriteMethod(parseContext.parseFieldMatcher(), rewrite, null);
+ QueryParsers.setRewriteMethod(query, rewriteMethod);
+ return query;
+ }
+
+ @Override
+ public QueryValidationException validate() {
+ QueryValidationException validationException = null;
+ if (Strings.isEmpty(this.fieldName)) {
+ validationException = addValidationError("field name cannot be null or empty.", validationException);
+ }
+ if (this.value == null) {
+ validationException = addValidationError("wildcard cannot be null", validationException);
+ }
+ return validationException;
+ }
+
+ @Override
+ protected WildcardQueryBuilder doReadFrom(StreamInput in) throws IOException {
+ WildcardQueryBuilder wildcardQueryBuilder = new WildcardQueryBuilder(in.readString(), in.readString());
+ wildcardQueryBuilder.rewrite = in.readOptionalString();
+ return wildcardQueryBuilder;
+ }
+
+ @Override
+ protected void doWriteTo(StreamOutput out) throws IOException {
+ out.writeString(fieldName);
+ out.writeString(value);
+ out.writeOptionalString(rewrite);
+ }
+
+ @Override
+ protected int doHashCode() {
+ return Objects.hash(fieldName, value, rewrite);
+ }
+
+ @Override
+ protected boolean doEquals(WildcardQueryBuilder other) {
+ return Objects.equals(fieldName, other.fieldName) &&
+ Objects.equals(value, other.value) &&
+ Objects.equals(rewrite, other.rewrite);
}
}
diff --git a/core/src/main/java/org/elasticsearch/index/query/WildcardQueryParser.java b/core/src/main/java/org/elasticsearch/index/query/WildcardQueryParser.java
index 2ac10b80be38d..72330abb882b2 100644
--- a/core/src/main/java/org/elasticsearch/index/query/WildcardQueryParser.java
+++ b/core/src/main/java/org/elasticsearch/index/query/WildcardQueryParser.java
@@ -19,21 +19,15 @@
package org.elasticsearch.index.query;
-import org.apache.lucene.index.Term;
-import org.apache.lucene.search.Query;
-import org.apache.lucene.search.WildcardQuery;
-import org.apache.lucene.util.BytesRef;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.xcontent.XContentParser;
-import org.elasticsearch.index.mapper.MappedFieldType;
-import org.elasticsearch.index.query.support.QueryParsers;
import java.io.IOException;
/**
*
*/
-public class WildcardQueryParser extends BaseQueryParserTemp {
+public class WildcardQueryParser extends BaseQueryParser {
@Inject
public WildcardQueryParser() {
@@ -45,7 +39,7 @@ public String[] names() {
}
@Override
- public Query parse(QueryParseContext parseContext) throws IOException, QueryParsingException {
+ public QueryBuilder fromXContent(QueryParseContext parseContext) throws IOException, QueryParsingException {
XContentParser parser = parseContext.parser();
XContentParser.Token token = parser.nextToken();
@@ -53,7 +47,7 @@ public Query parse(QueryParseContext parseContext) throws IOException, QueryPars
throw new QueryParsingException(parseContext, "[wildcard] query malformed, no field");
}
String fieldName = parser.currentName();
- String rewriteMethod = null;
+ String rewrite = null;
String value = null;
float boost = AbstractQueryBuilder.DEFAULT_BOOST;
@@ -72,7 +66,7 @@ public Query parse(QueryParseContext parseContext) throws IOException, QueryPars
} else if ("boost".equals(currentFieldName)) {
boost = parser.floatValue();
} else if ("rewrite".equals(currentFieldName)) {
- rewriteMethod = parser.textOrNull();
+ rewrite = parser.textOrNull();
} else if ("_name".equals(currentFieldName)) {
queryName = parser.text();
} else {
@@ -89,23 +83,10 @@ public Query parse(QueryParseContext parseContext) throws IOException, QueryPars
if (value == null) {
throw new QueryParsingException(parseContext, "No value specified for prefix query");
}
-
- BytesRef valueBytes;
- MappedFieldType fieldType = parseContext.fieldMapper(fieldName);
- if (fieldType != null) {
- fieldName = fieldType.names().indexName();
- valueBytes = fieldType.indexedValueForSearch(value);
- } else {
- valueBytes = new BytesRef(value);
- }
-
- WildcardQuery wildcardQuery = new WildcardQuery(new Term(fieldName, valueBytes));
- QueryParsers.setRewriteMethod(wildcardQuery, parseContext.parseFieldMatcher(), rewriteMethod);
- wildcardQuery.setBoost(boost);
- if (queryName != null) {
- parseContext.addNamedQuery(queryName, wildcardQuery);
- }
- return wildcardQuery;
+ return new WildcardQueryBuilder(fieldName, value)
+ .rewrite(rewrite)
+ .boost(boost)
+ .queryName(queryName);
}
@Override
diff --git a/core/src/test/java/org/elasticsearch/index/query/WildcardQueryBuilderTest.java b/core/src/test/java/org/elasticsearch/index/query/WildcardQueryBuilderTest.java
new file mode 100644
index 0000000000000..dc3c6789f5ff4
--- /dev/null
+++ b/core/src/test/java/org/elasticsearch/index/query/WildcardQueryBuilderTest.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.index.query;
+
+import org.apache.lucene.index.Term;
+import org.apache.lucene.search.MultiTermQuery;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.WildcardQuery;
+import org.apache.lucene.util.BytesRef;
+import org.elasticsearch.common.ParseFieldMatcher;
+import org.elasticsearch.index.mapper.MappedFieldType;
+import org.elasticsearch.index.query.support.QueryParsers;
+import org.junit.Test;
+
+import java.io.IOException;
+
+import static org.hamcrest.Matchers.is;
+
+public class WildcardQueryBuilderTest extends BaseQueryTestCase {
+
+ @Override
+ protected WildcardQueryBuilder doCreateTestQueryBuilder() {
+ WildcardQueryBuilder query;
+
+ // mapped or unmapped field
+ String text = randomAsciiOfLengthBetween(1, 10);
+ if (randomBoolean()) {
+ query = new WildcardQueryBuilder(STRING_FIELD_NAME, text);
+ } else {
+ query = new WildcardQueryBuilder(randomAsciiOfLengthBetween(1, 10), text);
+ }
+ if (randomBoolean()) {
+ query.rewrite(randomFrom(getRandomRewriteMethod()));
+ }
+ return query;
+ }
+
+ @Override
+ protected Query doCreateExpectedQuery(WildcardQueryBuilder queryBuilder, QueryParseContext context) throws IOException {
+ String indexFieldName;
+ BytesRef valueBytes;
+
+ MappedFieldType fieldType = context.fieldMapper(queryBuilder.fieldName());
+ if (fieldType != null) {
+ indexFieldName = fieldType.names().indexName();
+ valueBytes = fieldType.indexedValueForSearch(queryBuilder.value());
+ } else {
+ indexFieldName = queryBuilder.fieldName();
+ valueBytes = new BytesRef(queryBuilder.value());
+ }
+
+ WildcardQuery expectedQuery = new WildcardQuery(new Term(indexFieldName, valueBytes));
+
+ //norelease fix to be removed to avoid NPE on unmapped fields
+ context.parseFieldMatcher(randomBoolean() ? ParseFieldMatcher.EMPTY : ParseFieldMatcher.STRICT);
+ MultiTermQuery.RewriteMethod rewriteMethod = QueryParsers.parseRewriteMethod(context.parseFieldMatcher(), queryBuilder.rewrite(), null);
+ QueryParsers.setRewriteMethod(expectedQuery, rewriteMethod);
+ return expectedQuery;
+ }
+
+ @Test
+ public void testValidate() {
+ WildcardQueryBuilder wildcardQueryBuilder = new WildcardQueryBuilder("", "text");
+ assertThat(wildcardQueryBuilder.validate().validationErrors().size(), is(1));
+
+ wildcardQueryBuilder = new WildcardQueryBuilder("field", null);
+ assertThat(wildcardQueryBuilder.validate().validationErrors().size(), is(1));
+
+ wildcardQueryBuilder = new WildcardQueryBuilder(null, null);
+ assertThat(wildcardQueryBuilder.validate().validationErrors().size(), is(2));
+
+ wildcardQueryBuilder = new WildcardQueryBuilder("field", "text");
+ assertNull(wildcardQueryBuilder.validate());
+ }
+
+ @Test
+ public void testEmptyValue() throws IOException {
+ QueryParseContext context = createContext();
+ context.setAllowUnmappedFields(true);
+
+ WildcardQueryBuilder wildcardQueryBuilder = new WildcardQueryBuilder(getRandomType(), "");
+ assertEquals(wildcardQueryBuilder.toQuery(context).getClass(), WildcardQuery.class);
+ }
+}