From e20b6b4d505268bc8a295deae7f41b9f9a71286a Mon Sep 17 00:00:00 2001 From: Isabel Drost-Fromm Date: Tue, 28 Apr 2015 09:30:09 +0200 Subject: [PATCH] Refactors SpanTermQueryBuilder. This attempts to do to SpanTermQueryBuilder what has already been changed for TermQueryBuilder. The commit tries to avoid code duplication where possible by pulling what is the same for both QueryBuilders and tests into separate classes. Relates to #10217 --- .../index/query/BaseTermQueryBuilder.java | 221 ++++++++++++++++++ .../index/query/SpanTermQueryBuilder.java | 94 ++++---- .../index/query/SpanTermQueryParser.java | 38 +-- .../index/query/TermQueryBuilder.java | 178 ++------------ .../index/query/BaseQueryTestCase.java | 19 +- .../index/query/BaseTermQueryTest.java | 77 ++++++ .../index/query/SpanTermQueryBuilderTest.java | 72 ++++++ .../index/query/TermQueryBuilderTest.java | 46 +--- 8 files changed, 464 insertions(+), 281 deletions(-) create mode 100644 src/main/java/org/elasticsearch/index/query/BaseTermQueryBuilder.java create mode 100644 src/test/java/org/elasticsearch/index/query/BaseTermQueryTest.java create mode 100644 src/test/java/org/elasticsearch/index/query/SpanTermQueryBuilderTest.java diff --git a/src/main/java/org/elasticsearch/index/query/BaseTermQueryBuilder.java b/src/main/java/org/elasticsearch/index/query/BaseTermQueryBuilder.java new file mode 100644 index 0000000000000..ecf083d0e294b --- /dev/null +++ b/src/main/java/org/elasticsearch/index/query/BaseTermQueryBuilder.java @@ -0,0 +1,221 @@ +/* + * 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.util.BytesRef; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.common.io.stream.Streamable; +import org.elasticsearch.common.lucene.BytesRefs; +import org.elasticsearch.common.xcontent.XContentBuilder; + +import java.io.IOException; +import java.util.Objects; + +public abstract class BaseTermQueryBuilder extends BaseQueryBuilder implements Streamable { + + /** Name of field to match against. */ + protected String fieldName; + + /** Value to find matches for. */ + protected Object value; + + /** Query boost. */ + protected float boost = 1.0f; + + /** Name of the query. */ + protected String queryName; + + /** + * Constructs a new base term query. + * + * @param fieldName The name of the field + * @param value The value of the term + */ + public BaseTermQueryBuilder(String fieldName, String value) { + this(fieldName, (Object) value); + } + + /** + * Constructs a new base term query. + * + * @param fieldName The name of the field + * @param value The value of the term + */ + public BaseTermQueryBuilder(String fieldName, int value) { + this(fieldName, (Object) value); + } + + /** + * Constructs a new base term query. + * + * @param fieldName The name of the field + * @param value The value of the term + */ + public BaseTermQueryBuilder(String fieldName, long value) { + this(fieldName, (Object) value); + } + + /** + * Constructs a new base term query. + * + * @param fieldName The name of the field + * @param value The value of the term + */ + public BaseTermQueryBuilder(String fieldName, float value) { + this(fieldName, (Object) value); + } + + /** + * Constructs a new base term query. + * + * @param fieldName The name of the field + * @param value The value of the term + */ + public BaseTermQueryBuilder(String fieldName, double value) { + this(fieldName, (Object) value); + } + + /** + * Constructs a new base term query. + * + * @param fieldName The name of the field + * @param value The value of the term + */ + public BaseTermQueryBuilder(String fieldName, boolean value) { + this(fieldName, (Object) value); + } + + /** + * Constructs a new base term query. + * + * @param fieldName The name of the field + * @param value The value of the term + */ + public BaseTermQueryBuilder(String fieldName, Object value) { + this.fieldName = fieldName; + if (value instanceof String) { + this.value = BytesRefs.toBytesRef(value); + } else { + this.value = value; + } + } + + BaseTermQueryBuilder() { + // for serialization only + } + + /** Returns the field name used in this query @see org.apache.lucene.search.spans.SpanTermQuery#getField() */ + public String fieldName() { + return this.fieldName; + } + + /** Returns the value used in this query @see org.apache.lucene.index.Term#text() */ + public Object value() { + return this.value; + } + + /** Returns the query name for the query. */ + public String queryName() { + return this.queryName; + } + /** Returns the boost for this query. @see org.apache.lucene.search.Query#setBoost() */ + public float boost() { + return this.boost; + } + + @Override + protected void doXContent(XContentBuilder builder, Params params) throws IOException { + Object valueToWrite = value; + if (value instanceof BytesRef) { + valueToWrite = ((BytesRef) value).utf8ToString(); + } + + if (boost == 1.0f && queryName == null) { + builder.field(fieldName, valueToWrite); + } else { + builder.startObject(fieldName); + builder.field("value", valueToWrite); + if (boost != 1.0f) { + builder.field("boost", boost); + } + if (queryName != null) { + builder.field("_name", queryName); + } + builder.endObject(); + } + builder.endObject(); + } + + /** Returns a {@link QueryValidationException} if fieldName is null or empty, or if value is null. */ + @Override + public QueryValidationException validate() { + QueryValidationException validationException = null; + if (fieldName == null || fieldName.isEmpty()) { + validationException = QueryValidationException.addValidationError("field name cannot be null or empty.", validationException); + } + if (value == null) { + validationException = QueryValidationException.addValidationError("value cannot be null.", validationException); + } + return validationException; + } + + + @Override + public int hashCode() { + /* + * Added class name to the hashcode so a {@link SpanTermQueryBuilder} and a {@link TermQueryBuilder} aren't considered the same + * if they have the same parameters set. + */ + return Objects.hash(getClass(), fieldName, value, boost, queryName); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + BaseTermQueryBuilder other = (BaseTermQueryBuilder) obj; + return Objects.equals(fieldName, other.fieldName) && + Objects.equals(value, other.value) && + Objects.equals(boost, other.boost) && + Objects.equals(queryName, other.queryName); + } + + /** Read the given parameters. */ + @Override + public void readFrom(StreamInput in) throws IOException { + fieldName = in.readString(); + value = in.readGenericValue(); + boost = in.readFloat(); + queryName = in.readOptionalString(); + } + + /** Writes the given parameters. */ + public void writeTo(StreamOutput out) throws IOException { + out.writeString(fieldName); + out.writeGenericValue(value); + out.writeFloat(boost); + out.writeOptionalString(queryName); + } +} diff --git a/src/main/java/org/elasticsearch/index/query/SpanTermQueryBuilder.java b/src/main/java/org/elasticsearch/index/query/SpanTermQueryBuilder.java index 8d9e619855e13..3cc00a4626991 100644 --- a/src/main/java/org/elasticsearch/index/query/SpanTermQueryBuilder.java +++ b/src/main/java/org/elasticsearch/index/query/SpanTermQueryBuilder.java @@ -19,83 +19,95 @@ package org.elasticsearch.index.query; +import org.apache.lucene.index.Term; +import org.apache.lucene.search.Query; +import org.apache.lucene.search.spans.SpanTermQuery; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.lucene.BytesRefs; import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.index.mapper.MapperService; import java.io.IOException; /** - * + * A Span Query that matches documents containing a term. + * @see SpanTermQuery */ -public class SpanTermQueryBuilder extends BaseQueryBuilder implements SpanQueryBuilder, BoostableQueryBuilder { - - private final String name; - - private final Object value; - - private float boost = -1; - - private String queryName; - +public class SpanTermQueryBuilder extends BaseTermQueryBuilder implements SpanQueryBuilder, BoostableQueryBuilder { + /** {@inheritDoc} */ public SpanTermQueryBuilder(String name, String value) { - this(name, (Object) value); + super(name, (Object) value); } - + /** {@inheritDoc} */ public SpanTermQueryBuilder(String name, int value) { - this(name, (Object) value); + super(name, (Object) value); } - + /** {@inheritDoc} */ public SpanTermQueryBuilder(String name, long value) { - this(name, (Object) value); + super(name, (Object) value); } - + /** {@inheritDoc} */ public SpanTermQueryBuilder(String name, float value) { - this(name, (Object) value); + super(name, (Object) value); } - + /** {@inheritDoc} */ public SpanTermQueryBuilder(String name, double value) { - this(name, (Object) value); + super(name, (Object) value); + } + /** {@inheritDoc} */ + public SpanTermQueryBuilder(String name, Object value) { + super(name, value); } - private SpanTermQueryBuilder(String name, Object value) { - this.name = name; - this.value = value; + SpanTermQueryBuilder() { + super(); + // for testing and serialisation only } + /** @see org.apache.lucene.search.Query#getBoost() */ @Override public SpanTermQueryBuilder boost(float boost) { this.boost = boost; return this; } - - /** - * Sets the query name for the filter that can be used when searching for matched_filters per hit. - */ + + /** Sets the query name for the filter that can be used when searching for matched_filters per hit. */ public SpanTermQueryBuilder queryName(String queryName) { this.queryName = queryName; return this; } + /** {@inheritDoc} */ @Override public void doXContent(XContentBuilder builder, Params params) throws IOException { builder.startObject(SpanTermQueryParser.NAME); - if (boost == -1 && queryName != null) { - builder.field(name, value); - } else { - builder.startObject(name); - builder.field("value", value); - if (boost != -1) { - builder.field("boost", boost); - } - if (queryName != null) { - builder.field("_name", queryName); - } - builder.endObject(); - } - builder.endObject(); + super.doXContent(builder, params); } @Override protected String parserName() { return SpanTermQueryParser.NAME; } + + @Override + public Query toQuery(QueryParseContext context) { + BytesRef valueBytes = null; + MapperService.SmartNameFieldMappers smartNameFieldMappers = context.smartFieldMappers(fieldName); + if (smartNameFieldMappers != null) { + if (smartNameFieldMappers.hasMapper()) { + fieldName = smartNameFieldMappers.mapper().names().indexName(); + valueBytes = smartNameFieldMappers.mapper().indexedValueForSearch(value); + } + } + if (valueBytes == null) { + valueBytes = BytesRefs.toBytesRef(this.value); + } + + SpanTermQuery query = new SpanTermQuery(new Term(fieldName, valueBytes)); + query.setBoost(boost); + if (queryName != null) { + context.addNamedQuery(queryName, query); + } + return query; + } } diff --git a/src/main/java/org/elasticsearch/index/query/SpanTermQueryParser.java b/src/main/java/org/elasticsearch/index/query/SpanTermQueryParser.java index 01e7546b1de73..6637d1fe4eab5 100644 --- a/src/main/java/org/elasticsearch/index/query/SpanTermQueryParser.java +++ b/src/main/java/org/elasticsearch/index/query/SpanTermQueryParser.java @@ -19,21 +19,16 @@ package org.elasticsearch.index.query; -import org.apache.lucene.index.Term; -import org.apache.lucene.search.Query; -import org.apache.lucene.search.spans.SpanTermQuery; -import org.apache.lucene.util.BytesRef; import org.elasticsearch.common.Strings; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.xcontent.XContentParser; -import org.elasticsearch.index.mapper.MapperService; import java.io.IOException; /** * */ -public class SpanTermQueryParser extends BaseQueryParserTemp { +public class SpanTermQueryParser extends BaseQueryParser { public static final String NAME = "span_term"; @@ -47,18 +42,19 @@ 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.currentToken(); if (token == XContentParser.Token.START_OBJECT) { token = parser.nextToken(); } + assert token == XContentParser.Token.FIELD_NAME; String fieldName = parser.currentName(); - String value = null; + Object value = null; float boost = 1.0f; String queryName = null; token = parser.nextToken(); @@ -69,9 +65,9 @@ public Query parse(QueryParseContext parseContext) throws IOException, QueryPars currentFieldName = parser.currentName(); } else { if ("term".equals(currentFieldName)) { - value = parser.text(); + value = parser.objectText(); } else if ("value".equals(currentFieldName)) { - value = parser.text(); + value = parser.objectText(); } else if ("boost".equals(currentFieldName)) { boost = parser.floatValue(); } else if ("_name".equals(currentFieldName)) { @@ -92,23 +88,9 @@ public Query parse(QueryParseContext parseContext) throws IOException, QueryPars throw new QueryParsingException(parseContext, "No value specified for term query"); } - BytesRef valueBytes = null; - MapperService.SmartNameFieldMappers smartNameFieldMappers = parseContext.smartFieldMappers(fieldName); - if (smartNameFieldMappers != null) { - if (smartNameFieldMappers.hasMapper()) { - fieldName = smartNameFieldMappers.mapper().names().indexName(); - valueBytes = smartNameFieldMappers.mapper().indexedValueForSearch(value); - } - } - if (valueBytes == null) { - valueBytes = new BytesRef(value); - } - - SpanTermQuery query = new SpanTermQuery(new Term(fieldName, valueBytes)); - query.setBoost(boost); - if (queryName != null) { - parseContext.addNamedQuery(queryName, query); - } - return query; + SpanTermQueryBuilder result = new SpanTermQueryBuilder(fieldName, value); + result.boost(boost).queryName(queryName); + result.validate(); + return result; } } diff --git a/src/main/java/org/elasticsearch/index/query/TermQueryBuilder.java b/src/main/java/org/elasticsearch/index/query/TermQueryBuilder.java index 79034a8bdabc2..8ac4bde3f40fc 100644 --- a/src/main/java/org/elasticsearch/index/query/TermQueryBuilder.java +++ b/src/main/java/org/elasticsearch/index/query/TermQueryBuilder.java @@ -22,123 +22,56 @@ import org.apache.lucene.index.Term; import org.apache.lucene.search.Query; import org.apache.lucene.search.TermQuery; -import org.apache.lucene.util.BytesRef; -import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.common.io.stream.StreamOutput; -import org.elasticsearch.common.io.stream.Streamable; import org.elasticsearch.common.lucene.BytesRefs; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.index.mapper.MapperService; import java.io.IOException; -import java.util.Objects; /** * A Query that matches documents containing a term. */ -public class TermQueryBuilder extends BaseQueryBuilder implements Streamable, BoostableQueryBuilder { - - private String fieldName; - - private Object value; - - private float boost = 1.0f; - - private String queryName; - - /** - * Constructs a new term query. - * - * @param fieldName The name of the field - * @param value The value of the term - */ +public class TermQueryBuilder extends BaseTermQueryBuilder implements BoostableQueryBuilder { + /** {@inheritDoc} */ public TermQueryBuilder(String fieldName, String value) { - this(fieldName, (Object) value); + super(fieldName, (Object) value); } - /** - * Constructs a new term query. - * - * @param fieldName The name of the field - * @param value The value of the term - */ + /** {@inheritDoc} */ public TermQueryBuilder(String fieldName, int value) { - this(fieldName, (Object) value); + super(fieldName, (Object) value); } - /** - * Constructs a new term query. - * - * @param fieldName The name of the field - * @param value The value of the term - */ + /** {@inheritDoc} */ public TermQueryBuilder(String fieldName, long value) { - this(fieldName, (Object) value); + super(fieldName, (Object) value); } - /** - * Constructs a new term query. - * - * @param fieldName The name of the field - * @param value The value of the term - */ + /** {@inheritDoc} */ public TermQueryBuilder(String fieldName, float value) { - this(fieldName, (Object) value); + super(fieldName, (Object) value); } - /** - * Constructs a new term query. - * - * @param fieldName The name of the field - * @param value The value of the term - */ + /** {@inheritDoc} */ public TermQueryBuilder(String fieldName, double value) { - this(fieldName, (Object) value); + super(fieldName, (Object) value); } - /** - * Constructs a new term query. - * - * @param fieldName The name of the field - * @param value The value of the term - */ + /** {@inheritDoc} */ public TermQueryBuilder(String fieldName, boolean value) { - this(fieldName, (Object) value); + super(fieldName, (Object) value); } - /** - * Constructs a new term query. - * - * @param fieldName The name of the field - * @param value The value of the term - */ + /** {@inheritDoc} */ public TermQueryBuilder(String fieldName, Object value) { - this.fieldName = fieldName; - if (value instanceof String) { - this.value = BytesRefs.toBytesRef(value); - } else { - this.value = value; - } + super(fieldName, value); } TermQueryBuilder() { + super(); // for serialization only } - /** - * @return the field name used in this query - */ - public String fieldName() { - return this.fieldName; - } - - /** - * @return the value used in this query - */ - public Object value() { - return this.value; - } - /** * Sets the boost for this query. Documents matching this query will (in addition to the normal * weightings) have their score multiplied by the boost provided. @@ -149,13 +82,6 @@ public TermQueryBuilder boost(float boost) { return this; } - /** - * Gets the boost for this query. - */ - public float boost() { - return this.boost; - } - /** * Sets the query name for the query. */ @@ -164,34 +90,11 @@ public TermQueryBuilder queryName(String queryName) { return this; } - /** - * Gets the query name for the query. - */ - public String queryName() { - return this.queryName; - } @Override public void doXContent(XContentBuilder builder, Params params) throws IOException { builder.startObject(TermQueryParser.NAME); - Object valueToWrite = this.value; - if (valueToWrite instanceof BytesRef) { - valueToWrite = ((BytesRef) valueToWrite).utf8ToString(); - } - if (boost == 1.0f && queryName == null) { - builder.field(fieldName, valueToWrite); - } else { - builder.startObject(fieldName); - builder.field("value", valueToWrite); - if (boost != 1.0f) { - builder.field("boost", boost); - } - if (queryName != null) { - builder.field("_name", queryName); - } - builder.endObject(); - } - builder.endObject(); + super.doXContent(builder, params); } @Override @@ -211,55 +114,8 @@ public Query toQuery(QueryParseContext parseContext) { return query; } - @Override - public QueryValidationException validate() { - QueryValidationException validationException = null; - if (this.fieldName == null || this.fieldName.isEmpty()) { - validationException = QueryValidationException.addValidationError("field name cannot be null or empty.", validationException); - } - if (this.value == null) { - validationException = QueryValidationException.addValidationError("value cannot be null.", validationException); - } - return validationException; - } - @Override protected String parserName() { return TermQueryParser.NAME; } - - public void readFrom(StreamInput in) throws IOException { - fieldName = in.readString(); - value = in.readGenericValue(); - boost = in.readFloat(); - queryName = in.readOptionalString(); - } - - @Override - public void writeTo(StreamOutput out) throws IOException { - out.writeString(fieldName); - out.writeGenericValue(value); - out.writeFloat(boost); - out.writeOptionalString(queryName); - } - - @Override - public int hashCode() { - return Objects.hash(fieldName, value, boost, queryName); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null || getClass() != obj.getClass()) { - return false; - } - TermQueryBuilder other = (TermQueryBuilder) obj; - return Objects.equals(fieldName, other.fieldName) && - Objects.equals(value, other.value) && - Objects.equals(boost, other.boost) && - Objects.equals(queryName, other.queryName); - } } diff --git a/src/test/java/org/elasticsearch/index/query/BaseQueryTestCase.java b/src/test/java/org/elasticsearch/index/query/BaseQueryTestCase.java index 8a607d1f37fc1..dd67070f8ef7e 100644 --- a/src/test/java/org/elasticsearch/index/query/BaseQueryTestCase.java +++ b/src/test/java/org/elasticsearch/index/query/BaseQueryTestCase.java @@ -64,8 +64,8 @@ public abstract class BaseQueryTestCase extends ElasticsearchTestCase { private static Injector injector; - private static IndexQueryParserService queryParserService; - private static Index index; + protected static IndexQueryParserService queryParserService; + protected static Index index; protected QB testQuery = createTestQueryBuilder(); @@ -147,7 +147,14 @@ public void testFromXContent() throws IOException { assertNotSame(newQuery, testQuery); assertEquals(newQuery, testQuery); } - + + private static void assertQueryHeader(XContentParser parser, String expectedParserName) throws IOException { + assertThat(parser.nextToken(), is(XContentParser.Token.START_OBJECT)); + assertThat(parser.nextToken(), is(XContentParser.Token.FIELD_NAME)); + assertThat(parser.currentName(), is(expectedParserName)); + assertThat(parser.nextToken(), is(XContentParser.Token.START_OBJECT)); + } + /** * Test creates the {@link Query} from the {@link QueryBuilder} under test and delegates the * assertions being made on the result to the implementing subclass. @@ -182,10 +189,4 @@ protected static QueryParseContext createContext() { return new QueryParseContext(index, queryParserService); } - private static void assertQueryHeader(XContentParser parser, String expectedParserName) throws IOException { - assertThat(parser.nextToken(), is(XContentParser.Token.START_OBJECT)); - assertThat(parser.nextToken(), is(XContentParser.Token.FIELD_NAME)); - assertThat(parser.currentName(), is(expectedParserName)); - assertThat(parser.nextToken(), is(XContentParser.Token.START_OBJECT)); - } } \ No newline at end of file diff --git a/src/test/java/org/elasticsearch/index/query/BaseTermQueryTest.java b/src/test/java/org/elasticsearch/index/query/BaseTermQueryTest.java new file mode 100644 index 0000000000000..30ed185fa86f7 --- /dev/null +++ b/src/test/java/org/elasticsearch/index/query/BaseTermQueryTest.java @@ -0,0 +1,77 @@ +/* + * 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.search.Query; +import org.apache.lucene.search.spans.SpanTermQuery; +import org.elasticsearch.common.io.stream.Streamable; +import org.elasticsearch.common.lucene.BytesRefs; +import org.junit.Ignore; +import org.junit.Test; + +import java.io.IOException; + +import static org.hamcrest.Matchers.is; + +@Ignore +public abstract class BaseTermQueryTest extends BaseQueryTestCase { + + public Object createRandomValueObject() { + Object value = null; + switch (randomIntBetween(0, 3)) { + case 0: + value = randomBoolean(); + break; + case 1: + if (randomInt(10) > 0) { + value = randomAsciiOfLength(8); + } else { + // generate unicode string in 10% of cases + value = randomUnicodeOfLength(10); + } + break; + case 2: + value = randomInt(10000); + break; + case 3: + value = randomDouble(); + break; + } + return value; + } + + @Test + public void testValidate() throws QueryParsingException, IOException { + TermQueryBuilder queryBuilder = new TermQueryBuilder("all", "good"); + assertNull(queryBuilder.validate()); + + queryBuilder = new TermQueryBuilder(null, "Term"); + assertNotNull(queryBuilder.validate()); + assertThat(queryBuilder.validate().validationErrors().size(), is(1)); + + queryBuilder = new TermQueryBuilder("", "Term"); + assertNotNull(queryBuilder.validate()); + assertThat(queryBuilder.validate().validationErrors().size(), is(1)); + + queryBuilder = new TermQueryBuilder("", null); + assertNotNull(queryBuilder.validate()); + assertThat(queryBuilder.validate().validationErrors().size(), is(2)); + } +} diff --git a/src/test/java/org/elasticsearch/index/query/SpanTermQueryBuilderTest.java b/src/test/java/org/elasticsearch/index/query/SpanTermQueryBuilderTest.java new file mode 100644 index 0000000000000..507f09aa91528 --- /dev/null +++ b/src/test/java/org/elasticsearch/index/query/SpanTermQueryBuilderTest.java @@ -0,0 +1,72 @@ +/* + * 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.search.Filter; +import org.apache.lucene.search.Query; +import org.apache.lucene.search.QueryWrapperFilter; +import org.apache.lucene.search.spans.SpanTermQuery; +import org.elasticsearch.common.lucene.BytesRefs; + +import java.io.IOException; + +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.is; + +public class SpanTermQueryBuilderTest extends BaseTermQueryTest { + + @Override + protected SpanTermQueryBuilder createEmptyQueryBuilder() { + return new SpanTermQueryBuilder(); + } + + /** Returns a {@link SpanTermQueryBuilder} with random field name and value, optional random boost and queryname */ + protected SpanTermQueryBuilder createTestQueryBuilder() { + Object value = createRandomValueObject(); + SpanTermQueryBuilder query = new SpanTermQueryBuilder(randomAsciiOfLength(8), value); + if (randomBoolean()) { + query.boost(2.0f / randomIntBetween(1, 20)); + } + if (randomBoolean()) { + query.queryName(randomAsciiOfLength(8)); + } + return query; + } + + /** Checks the generated Lucene query against the {@link SpanTermQueryBuilder} it was created from. */ + @Override + protected void assertLuceneQuery(SpanTermQueryBuilder queryBuilder, Query query, QueryParseContext context) throws IOException { + assertThat(query, instanceOf(SpanTermQuery.class)); + assertThat(query.getBoost(), is(queryBuilder.boost())); + SpanTermQuery termQuery = (SpanTermQuery) query; + assertThat(termQuery.getTerm().field(), is(queryBuilder.fieldName())); + assertThat(termQuery.getTerm().bytes(), is(BytesRefs.toBytesRef(queryBuilder.value()))); + if (queryBuilder.queryName() != null) { + Filter namedQuery = context.copyNamedFilters().get(queryBuilder.queryName()); + assertNotNull(namedQuery); + if (namedQuery instanceof QueryWrapperFilter) { + assertThat(query, is(((QueryWrapperFilter) namedQuery).getQuery())); + } else { + fail("Expected a QueryWrapperFilter to be registered under " + queryBuilder.queryName() + + " in the query parse context"); + } + } + } +} diff --git a/src/test/java/org/elasticsearch/index/query/TermQueryBuilderTest.java b/src/test/java/org/elasticsearch/index/query/TermQueryBuilderTest.java index 164f7f6af48e1..5d6f1058da402 100644 --- a/src/test/java/org/elasticsearch/index/query/TermQueryBuilderTest.java +++ b/src/test/java/org/elasticsearch/index/query/TermQueryBuilderTest.java @@ -24,44 +24,22 @@ import org.apache.lucene.search.QueryWrapperFilter; import org.apache.lucene.search.TermQuery; import org.elasticsearch.common.lucene.BytesRefs; -import org.junit.Test; import java.io.IOException; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; -public class TermQueryBuilderTest extends BaseQueryTestCase { +public class TermQueryBuilderTest extends BaseTermQueryTest { @Override protected TermQueryBuilder createEmptyQueryBuilder() { return new TermQueryBuilder(); } - /** - * @return a TermQuery with random field name and value, optional random boost and queryname - */ + /** Returns a TermQuery with random field name and value, optional random boost and queryname. */ protected TermQueryBuilder createTestQueryBuilder() { - Object value = null; - switch (randomIntBetween(0, 3)) { - case 0: - value = randomBoolean(); - break; - case 1: - if (randomInt(10) > 0) { - value = randomAsciiOfLength(8); - } else { - // generate unicode string in 10% of cases - value = randomUnicodeOfLength(10); - } - break; - case 2: - value = randomInt(10000); - break; - case 3: - value = randomDouble(); - break; - } + Object value = createRandomValueObject(); TermQueryBuilder query = new TermQueryBuilder(randomAsciiOfLength(8), value); if (randomBoolean()) { query.boost(2.0f / randomIntBetween(1, 20)); @@ -72,6 +50,7 @@ protected TermQueryBuilder createTestQueryBuilder() { return query; } + /** Validates the Lucene query that was generated from a given {@link TermQueryBuilder}*/ @Override protected void assertLuceneQuery(TermQueryBuilder queryBuilder, Query query, QueryParseContext context) throws IOException { assertThat(query, instanceOf(TermQuery.class)); @@ -91,21 +70,4 @@ protected void assertLuceneQuery(TermQueryBuilder queryBuilder, Query query, Que } } - @Test - public void testValidate() throws QueryParsingException, IOException { - TermQueryBuilder queryBuilder = new TermQueryBuilder("all", "good"); - assertNull(queryBuilder.validate()); - - queryBuilder = new TermQueryBuilder(null, "Term"); - assertNotNull(queryBuilder.validate()); - assertThat(queryBuilder.validate().validationErrors().size(), is(1)); - - queryBuilder = new TermQueryBuilder("", "Term"); - assertNotNull(queryBuilder.validate()); - assertThat(queryBuilder.validate().validationErrors().size(), is(1)); - - queryBuilder = new TermQueryBuilder("", null); - assertNotNull(queryBuilder.validate()); - assertThat(queryBuilder.validate().validationErrors().size(), is(2)); - } }