diff --git a/core/src/main/java/org/elasticsearch/index/query/QueryBuilders.java b/core/src/main/java/org/elasticsearch/index/query/QueryBuilders.java index 3825bebcde2..75bc64b0d21 100644 --- a/core/src/main/java/org/elasticsearch/index/query/QueryBuilders.java +++ b/core/src/main/java/org/elasticsearch/index/query/QueryBuilders.java @@ -324,9 +324,12 @@ public abstract class QueryBuilders { return new SpanOrQueryBuilder(); } - /** Creates a new {@code span_within} builder. */ - public static SpanWithinQueryBuilder spanWithinQuery() { - return new SpanWithinQueryBuilder(); + /** Creates a new {@code span_within} builder. + * @param big the big clause, it must enclose {@code little} for a match. + * @param little the little clause, it must be contained within {@code big} for a match. + */ + public static SpanWithinQueryBuilder spanWithinQuery(SpanQueryBuilder big, SpanQueryBuilder little) { + return new SpanWithinQueryBuilder(big, little); } /** diff --git a/core/src/main/java/org/elasticsearch/index/query/SpanWithinQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/SpanWithinQueryBuilder.java index ec955895549..89903a8bd8e 100644 --- a/core/src/main/java/org/elasticsearch/index/query/SpanWithinQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/SpanWithinQueryBuilder.java @@ -19,9 +19,15 @@ package org.elasticsearch.index.query; +import org.apache.lucene.search.Query; +import org.apache.lucene.search.spans.SpanQuery; +import org.apache.lucene.search.spans.SpanWithinQuery; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.xcontent.XContentBuilder; import java.io.IOException; +import java.util.Objects; /** * Builder for {@link org.apache.lucene.search.spans.SpanWithinQuery}. @@ -29,34 +35,44 @@ import java.io.IOException; public class SpanWithinQueryBuilder extends AbstractQueryBuilder implements SpanQueryBuilder { public static final String NAME = "span_within"; - private SpanQueryBuilder big; - private SpanQueryBuilder little; + private final SpanQueryBuilder big; + private final SpanQueryBuilder little; static final SpanWithinQueryBuilder PROTOTYPE = new SpanWithinQueryBuilder(); /** - * Sets the little clause, it must be contained within {@code big} for a match. + * Query that returns spans from little that are contained in a spans from big. + * @param big clause that must enclose {@code little} for a match. + * @param little the little clause, it must be contained within {@code big} for a match. */ - public SpanWithinQueryBuilder little(SpanQueryBuilder clause) { - this.little = clause; - return this; + public SpanWithinQueryBuilder(SpanQueryBuilder big, SpanQueryBuilder little) { + this.little = Objects.requireNonNull(little); + this.big = Objects.requireNonNull(big); } /** - * Sets the big clause, it must enclose {@code little} for a match. + * for prototype only */ - public SpanWithinQueryBuilder big(SpanQueryBuilder clause) { - this.big = clause; - return this; + private SpanWithinQueryBuilder() { + this.little = null; + this.big = null; + } + + /** + * @return the little clause, contained within {@code big} for a match. + */ + public SpanQueryBuilder little() { + return this.little; + } + + /** + * @return the big clause that must enclose {@code little} for a match. + */ + public SpanQueryBuilder big() { + return this.big; } @Override protected void doXContent(XContentBuilder builder, Params params) throws IOException { - if (big == null) { - throw new IllegalArgumentException("Must specify big clause when building a span_within query"); - } - if (little == null) { - throw new IllegalArgumentException("Must specify little clause when building a span_within query"); - } builder.startObject(NAME); builder.field("big"); @@ -70,6 +86,46 @@ public class SpanWithinQueryBuilder extends AbstractQueryBuilder { + + @Override + protected Query doCreateExpectedQuery(SpanWithinQueryBuilder testQueryBuilder, QueryParseContext context) throws IOException { + SpanQuery big = (SpanQuery) testQueryBuilder.big().toQuery(context); + SpanQuery little = (SpanQuery) testQueryBuilder.little().toQuery(context); + return new SpanWithinQuery(big, little); + } + + @Override + protected SpanWithinQueryBuilder doCreateTestQueryBuilder() { + SpanTermQueryBuilder bigQuery = new SpanTermQueryBuilderTest().createTestQueryBuilder(); + // we need same field name and value type as bigQuery for little query + String fieldName = bigQuery.fieldName(); + Object littleValue; + switch (fieldName) { + case BOOLEAN_FIELD_NAME: littleValue = randomBoolean(); break; + case INT_FIELD_NAME: littleValue = randomInt(); break; + case DOUBLE_FIELD_NAME: littleValue = randomDouble(); break; + case STRING_FIELD_NAME: littleValue = randomAsciiOfLengthBetween(1, 10); break; + default : littleValue = randomAsciiOfLengthBetween(1, 10); + } + SpanTermQueryBuilder littleQuery = new SpanTermQueryBuilder(fieldName, littleValue); + return new SpanWithinQueryBuilder(bigQuery, littleQuery); + } + + @Test + public void testValidate() { + int totalExpectedErrors = 0; + SpanQueryBuilder bigSpanQueryBuilder; + if (randomBoolean()) { + bigSpanQueryBuilder = new SpanTermQueryBuilder("", "test"); + totalExpectedErrors++; + } else { + bigSpanQueryBuilder = new SpanTermQueryBuilder("name", "value"); + } + SpanQueryBuilder littleSpanQueryBuilder; + if (randomBoolean()) { + littleSpanQueryBuilder = new SpanTermQueryBuilder("", "test"); + totalExpectedErrors++; + } else { + littleSpanQueryBuilder = new SpanTermQueryBuilder("name", "value"); + } + SpanWithinQueryBuilder queryBuilder = new SpanWithinQueryBuilder(bigSpanQueryBuilder, littleSpanQueryBuilder); + assertValidate(queryBuilder, totalExpectedErrors); + } + + @Test(expected=NullPointerException.class) + public void testNullBig() { + new SpanWithinQueryBuilder(null, new SpanTermQueryBuilder("name", "value")); + } + + @Test(expected=NullPointerException.class) + public void testNullLittle() { + new SpanWithinQueryBuilder(new SpanTermQueryBuilder("name", "value"), null); + } +} diff --git a/docs/reference/migration/migrate_query_refactoring.asciidoc b/docs/reference/migration/migrate_query_refactoring.asciidoc index 3fdc055d8e0..1f066db141e 100644 --- a/docs/reference/migration/migrate_query_refactoring.asciidoc +++ b/docs/reference/migration/migrate_query_refactoring.asciidoc @@ -27,6 +27,13 @@ Updated the static factory methods in QueryBuilders accordingly. Removed setter for mandatory include/exclude span query clause, needs to be set in constructor now. Updated the static factory methods in QueryBuilders and tests accordingly. +==== SpanWithinQueryBuilder + +Removed setters for mandatory big/little inner span queries. Both arguments now have +to be supplied at construction time already and have to be non-null. Updated +static factory methods in QueryBuilders accordingly. +>>>>>>> Query refactoring: SpanWithinQueryBuilder and Parser + ==== QueryFilterBuilder Removed the setter `queryName(String queryName)` since this field is not supported