Move optimization out of BoolQueryBuilder into tests
This commit is contained in:
parent
387a55d5f9
commit
8d568ce3e1
|
@ -263,13 +263,6 @@ public class BoolQueryBuilder extends AbstractQueryBuilder<BoolQueryBuilder> {
|
|||
|
||||
@Override
|
||||
protected Query doToQuery(QueryShardContext context) throws IOException {
|
||||
final int numClauses = mustNotClauses.size() + filterClauses.size() + shouldClauses.size() + mustClauses.size();
|
||||
if (numClauses == 1 && must().size() == 1 && boost() == DEFAULT_BOOST) {
|
||||
// we really only optimize this for testing since we use this to rewrite
|
||||
// named queries TemplateQueryBuilder and WrapperQueryBuilder.
|
||||
// it's equivalent but will anyways happen later down the road in the BQ#rewrite method
|
||||
return mustClauses.get(0).toQuery(context);
|
||||
}
|
||||
BooleanQuery.Builder booleanQueryBuilder = new BooleanQuery.Builder();
|
||||
booleanQueryBuilder.setDisableCoord(disableCoord);
|
||||
addBooleanClauses(context, booleanQueryBuilder, mustClauses, BooleanClause.Occur.MUST);
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
package org.elasticsearch.index.query;
|
||||
|
||||
import org.apache.lucene.search.MatchAllDocsQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
|
|
|
@ -143,4 +143,6 @@ public class WrapperQueryBuilder extends AbstractQueryBuilder<WrapperQueryBuilde
|
|||
return queryBuilder;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import com.carrotsearch.randomizedtesting.generators.CodepointSetGenerator;
|
|||
import com.fasterxml.jackson.core.JsonParseException;
|
||||
import com.fasterxml.jackson.core.io.JsonStringEncoder;
|
||||
|
||||
import org.apache.lucene.index.memory.MemoryIndex;
|
||||
import org.apache.lucene.search.BoostQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.TermQuery;
|
||||
|
@ -538,7 +539,7 @@ public abstract class AbstractQueryTestCase<QB extends AbstractQueryBuilder<QB>>
|
|||
assertLuceneQuery(secondQuery, secondLuceneQuery, context);
|
||||
SearchContext.removeCurrent();
|
||||
|
||||
assertThat("two equivalent query builders lead to different lucene queries", secondLuceneQuery, equalTo(firstLuceneQuery));
|
||||
assertEquals("two equivalent query builders lead to different lucene queries", rewrite(secondLuceneQuery), rewrite(firstLuceneQuery));
|
||||
|
||||
// if the initial lucene query is null, changing its boost won't have any effect, we shouldn't test that
|
||||
if (firstLuceneQuery != null && supportsBoostAndQueryName()) {
|
||||
|
@ -546,8 +547,8 @@ public abstract class AbstractQueryTestCase<QB extends AbstractQueryBuilder<QB>>
|
|||
setSearchContext(randomTypes);
|
||||
Query thirdLuceneQuery = rewriteQuery(secondQuery, context).toQuery(context);
|
||||
SearchContext.removeCurrent();
|
||||
assertThat("modifying the boost doesn't affect the corresponding lucene query", firstLuceneQuery,
|
||||
not(equalTo(thirdLuceneQuery)));
|
||||
assertNotEquals("modifying the boost doesn't affect the corresponding lucene query", rewrite(firstLuceneQuery),
|
||||
rewrite(thirdLuceneQuery));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -988,4 +989,9 @@ public abstract class AbstractQueryTestCase<QB extends AbstractQueryBuilder<QB>>
|
|||
setSearchContext(randomTypes); // only set search context for toQuery to be more realistic
|
||||
queryBuilder.toQuery(context);
|
||||
}
|
||||
|
||||
protected Query rewrite(Query query) throws IOException {
|
||||
return query;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -195,14 +195,14 @@ public class BoolQueryBuilderTests extends AbstractQueryTestCase<BoolQueryBuilde
|
|||
|
||||
public void testDefaultMinShouldMatch() throws Exception {
|
||||
// Queries have a minShouldMatch of 0
|
||||
BooleanQuery bq = (BooleanQuery) parseQuery(boolQuery().filter(termQuery("foo", "bar")).buildAsBytes()).toQuery(createShardContext());
|
||||
BooleanQuery bq = (BooleanQuery) parseQuery(boolQuery().must(termQuery("foo", "bar")).buildAsBytes()).toQuery(createShardContext());
|
||||
assertEquals(0, bq.getMinimumNumberShouldMatch());
|
||||
|
||||
bq = (BooleanQuery) parseQuery(boolQuery().should(termQuery("foo", "bar")).buildAsBytes()).toQuery(createShardContext());
|
||||
assertEquals(0, bq.getMinimumNumberShouldMatch());
|
||||
|
||||
// Filters have a minShouldMatch of 0/1
|
||||
ConstantScoreQuery csq = (ConstantScoreQuery) parseQuery(constantScoreQuery(boolQuery().filter(termQuery("foo", "bar"))).buildAsBytes()).toQuery(createShardContext());
|
||||
ConstantScoreQuery csq = (ConstantScoreQuery) parseQuery(constantScoreQuery(boolQuery().must(termQuery("foo", "bar"))).buildAsBytes()).toQuery(createShardContext());
|
||||
bq = (BooleanQuery) csq.getQuery();
|
||||
assertEquals(0, bq.getMinimumNumberShouldMatch());
|
||||
|
||||
|
@ -213,7 +213,7 @@ public class BoolQueryBuilderTests extends AbstractQueryTestCase<BoolQueryBuilde
|
|||
|
||||
public void testMinShouldMatchFilterWithoutShouldClauses() throws Exception {
|
||||
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
|
||||
boolQueryBuilder.filter(new BoolQueryBuilder().filter(new MatchAllQueryBuilder()));
|
||||
boolQueryBuilder.filter(new BoolQueryBuilder().must(new MatchAllQueryBuilder()));
|
||||
Query query = boolQueryBuilder.toQuery(createShardContext());
|
||||
assertThat(query, instanceOf(BooleanQuery.class));
|
||||
BooleanQuery booleanQuery = (BooleanQuery) query;
|
||||
|
@ -227,7 +227,7 @@ public class BoolQueryBuilderTests extends AbstractQueryTestCase<BoolQueryBuilde
|
|||
assertThat(innerBooleanQuery.getMinimumNumberShouldMatch(), equalTo(0));
|
||||
assertThat(innerBooleanQuery.clauses().size(), equalTo(1));
|
||||
BooleanClause innerBooleanClause = innerBooleanQuery.clauses().get(0);
|
||||
assertThat(innerBooleanClause.getOccur(), equalTo(BooleanClause.Occur.FILTER));
|
||||
assertThat(innerBooleanClause.getOccur(), equalTo(BooleanClause.Occur.MUST));
|
||||
assertThat(innerBooleanClause.getQuery(), instanceOf(MatchAllDocsQuery.class));
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
package org.elasticsearch.index.query;
|
||||
|
||||
import org.apache.lucene.index.memory.MemoryIndex;
|
||||
import org.apache.lucene.search.MatchAllDocsQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
|
@ -58,7 +60,7 @@ public class TemplateQueryBuilderTests extends AbstractQueryTestCase<TemplateQue
|
|||
|
||||
@Override
|
||||
protected void doAssertLuceneQuery(TemplateQueryBuilder queryBuilder, Query query, QueryShardContext context) throws IOException {
|
||||
assertEquals(QueryBuilder.rewriteQuery(templateBase, context).toQuery(context), query);
|
||||
assertEquals(rewrite(QueryBuilder.rewriteQuery(templateBase, context).toQuery(context)), rewrite(query));
|
||||
}
|
||||
|
||||
public void testIllegalArgument() {
|
||||
|
@ -157,4 +159,16 @@ public class TemplateQueryBuilderTests extends AbstractQueryTestCase<TemplateQue
|
|||
XContentType.JSON, Collections.emptyMap())).boost(3);
|
||||
assertEquals(new BoolQueryBuilder().must(query).boost(3), builder.rewrite(queryShardContext()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Query rewrite(Query query) throws IOException {
|
||||
// TemplateQueryBuilder adds some optimization if the template and query builder have boosts / query names that wraps
|
||||
// the actual QueryBuilder that comes from the template into a BooleanQueryBuilder to give it an outer boost / name
|
||||
// this causes some queries to be not exactly equal but equivalent such that we need to rewrite them before comparing.
|
||||
if (query != null) {
|
||||
MemoryIndex idx = new MemoryIndex();
|
||||
return idx.createSearcher().rewrite(query);
|
||||
}
|
||||
return new MatchAllDocsQuery(); // null == *:*
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,19 +19,17 @@
|
|||
|
||||
package org.elasticsearch.index.query;
|
||||
|
||||
import org.apache.lucene.index.memory.MemoryIndex;
|
||||
import org.apache.lucene.search.MatchAllDocsQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.elasticsearch.action.support.ToXContentToBytes;
|
||||
import org.elasticsearch.common.ParsingException;
|
||||
import org.elasticsearch.common.bytes.BytesArray;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class WrapperQueryBuilderTests extends AbstractQueryTestCase<WrapperQueryBuilder> {
|
||||
|
||||
@Override
|
||||
|
@ -56,13 +54,9 @@ public class WrapperQueryBuilderTests extends AbstractQueryTestCase<WrapperQuery
|
|||
|
||||
@Override
|
||||
protected void doAssertLuceneQuery(WrapperQueryBuilder queryBuilder, Query query, QueryShardContext context) throws IOException {
|
||||
try (XContentParser qSourceParser = XContentFactory.xContent(queryBuilder.source()).createParser(queryBuilder.source())) {
|
||||
final QueryShardContext contextCopy = new QueryShardContext(context);
|
||||
contextCopy.reset(qSourceParser);
|
||||
QueryBuilder<?> innerQuery = contextCopy.parseContext().parseInnerQueryBuilder();
|
||||
Query expected = innerQuery.toQuery(context);
|
||||
assertThat(query, equalTo(expected));
|
||||
}
|
||||
QueryBuilder<?> innerQuery = queryBuilder.rewrite(queryShardContext());
|
||||
Query expected = rewrite(innerQuery.toQuery(context));
|
||||
assertEquals(rewrite(query), expected);
|
||||
}
|
||||
|
||||
public void testIllegalArgument() {
|
||||
|
@ -164,4 +158,16 @@ public class WrapperQueryBuilderTests extends AbstractQueryTestCase<WrapperQuery
|
|||
assertEquals(new BoolQueryBuilder().must(query).boost(3), builder.rewrite(queryShardContext()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Query rewrite(Query query) throws IOException {
|
||||
// WrapperQueryBuilder adds some optimization if the wrapper and query builder have boosts / query names that wraps
|
||||
// the actual QueryBuilder that comes from the binary blob into a BooleanQueryBuilder to give it an outer boost / name
|
||||
// this causes some queries to be not exactly equal but equivalent such that we need to rewrite them before comparing.
|
||||
if (query != null) {
|
||||
MemoryIndex idx = new MemoryIndex();
|
||||
return idx.createSearcher().rewrite(query);
|
||||
}
|
||||
return new MatchAllDocsQuery(); // null == *:*
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ import org.elasticsearch.index.query.QueryBuilders;
|
|||
import org.elasticsearch.index.query.QueryShardContext;
|
||||
import org.elasticsearch.index.query.RandomQueryBuilder;
|
||||
import org.elasticsearch.index.query.TermQueryBuilder;
|
||||
import org.elasticsearch.index.query.WrapperQueryBuilder;
|
||||
import org.elasticsearch.index.query.functionscore.exp.ExponentialDecayFunctionBuilder;
|
||||
import org.elasticsearch.index.query.functionscore.fieldvaluefactor.FieldValueFactorFunctionBuilder;
|
||||
import org.elasticsearch.index.query.functionscore.gauss.GaussDecayFunctionBuilder;
|
||||
|
@ -630,4 +631,33 @@ public class FunctionScoreQueryBuilderTests extends AbstractQueryTestCase<Functi
|
|||
assertEquals(json, 100, parsed.maxBoost(), 0.00001);
|
||||
assertEquals(json, 1, parsed.getMinScore(), 0.0001);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testMustRewrite() throws IOException {
|
||||
assumeTrue("test runs only when at least a type is registered", getCurrentTypes().length > 0);
|
||||
super.testMustRewrite();
|
||||
}
|
||||
|
||||
public void testRewrite() throws IOException {
|
||||
FunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(new WrapperQueryBuilder(new TermQueryBuilder("foo", "bar").toString()));
|
||||
FunctionScoreQueryBuilder rewrite = (FunctionScoreQueryBuilder) functionScoreQueryBuilder.rewrite(queryShardContext());
|
||||
assertNotSame(functionScoreQueryBuilder, rewrite);
|
||||
assertEquals(rewrite.query(), new TermQueryBuilder("foo", "bar"));
|
||||
}
|
||||
|
||||
public void testRewriteWithFunction() throws IOException {
|
||||
TermQueryBuilder secondFunction = new TermQueryBuilder("tq", "2");
|
||||
QueryBuilder queryBuilder = randomBoolean() ? new WrapperQueryBuilder(new TermQueryBuilder("foo", "bar").toString()) : new TermQueryBuilder("foo", "bar");
|
||||
FunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(queryBuilder,
|
||||
new FunctionScoreQueryBuilder.FilterFunctionBuilder[]{
|
||||
new FunctionScoreQueryBuilder.FilterFunctionBuilder(new WrapperQueryBuilder(new TermQueryBuilder("tq", "1").toString()), new RandomScoreFunctionBuilder()),
|
||||
new FunctionScoreQueryBuilder.FilterFunctionBuilder(secondFunction, new RandomScoreFunctionBuilder())
|
||||
|
||||
});
|
||||
FunctionScoreQueryBuilder rewrite = (FunctionScoreQueryBuilder) functionScoreQueryBuilder.rewrite(queryShardContext());
|
||||
assertNotSame(functionScoreQueryBuilder, rewrite);
|
||||
assertEquals(rewrite.query(), new TermQueryBuilder("foo", "bar"));
|
||||
assertEquals(rewrite.filterFunctionBuilders()[0].getFilter(), new TermQueryBuilder("tq", "1"));
|
||||
assertSame(rewrite.filterFunctionBuilders()[1].getFilter(), secondFunction);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue