Apply QueryParser boost to top leve query if applicable.

Set the query boost of a parsed query string query to the product of
the parsed query boost and the boost value specified in the "boost"
query string parameter. This only applies if the top level query returned
from the query parser has a boost assigned to it. In such a case we must
multiply the boost with the top level query boost otherwise the boost
will be overwritten ie. 'foo^2' has a top-level boost of 2 while
'foo^2 OR bar^3' has a top level boost of 1.0 (default) since the
boolean query is the top level query.

Closes #3024
This commit is contained in:
Matt Weber 2013-05-20 19:34:30 -07:00 committed by Simon Willnauer
parent af4205fd30
commit 927fda8a61
4 changed files with 48 additions and 8 deletions

View File

@ -34,10 +34,11 @@ public class QueryParserSettings {
public static final boolean DEFAULT_ALLOW_LEADING_WILDCARD = true; public static final boolean DEFAULT_ALLOW_LEADING_WILDCARD = true;
public static final boolean DEFAULT_ANALYZE_WILDCARD = false; public static final boolean DEFAULT_ANALYZE_WILDCARD = false;
public static final float DEFAULT_BOOST = 1.f;
private String queryString; private String queryString;
private String defaultField; private String defaultField;
private float boost = 1.0f; private float boost = DEFAULT_BOOST;
private MapperQueryParser.Operator defaultOperator = QueryParser.Operator.OR; private MapperQueryParser.Operator defaultOperator = QueryParser.Operator.OR;
private boolean autoGeneratePhraseQueries = false; private boolean autoGeneratePhraseQueries = false;
private boolean allowLeadingWildcard = DEFAULT_ALLOW_LEADING_WILDCARD; private boolean allowLeadingWildcard = DEFAULT_ALLOW_LEADING_WILDCARD;

View File

@ -214,7 +214,9 @@ public class QueryStringQueryParser implements QueryParser {
if (query == null) { if (query == null) {
return null; return null;
} }
query.setBoost(qpSettings.boost()); if (qpSettings.boost() != QueryParserSettings.DEFAULT_BOOST) {
query.setBoost(query.getBoost() * qpSettings.boost());
}
query = optimizeQuery(fixNegativeQueryIfNeeded(query)); query = optimizeQuery(fixNegativeQueryIfNeeded(query));
if (query instanceof BooleanQuery) { if (query instanceof BooleanQuery) {
Queries.applyMinimumShouldMatch((BooleanQuery) query, qpSettings.minimumShouldMatch()); Queries.applyMinimumShouldMatch((BooleanQuery) query, qpSettings.minimumShouldMatch());

View File

@ -23,6 +23,8 @@ import static org.hamcrest.Matchers.*;
import java.util.Arrays; import java.util.Arrays;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.Query;
import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.suggest.Suggest; import org.elasticsearch.search.suggest.Suggest;
@ -108,4 +110,12 @@ public class ElasticsearchAssertions {
return new ElasticsearchMatchers.SearchHitHasIndexMatcher(index); return new ElasticsearchMatchers.SearchHitHasIndexMatcher(index);
} }
public static <T extends Query> T assertBooleanSubQuery(Query query, Class<T> subqueryType, int i) {
assertThat(query, instanceOf(BooleanQuery.class));
BooleanQuery q = (BooleanQuery) query;
assertThat(q.getClauses().length, greaterThan(i));
assertThat(q.getClauses()[i].getQuery(), instanceOf(subqueryType));
return (T)q.getClauses()[i].getQuery();
}
} }

View File

@ -54,6 +54,7 @@ import org.elasticsearch.index.mapper.MapperServiceModule;
import org.elasticsearch.index.query.IndexQueryParserModule; import org.elasticsearch.index.query.IndexQueryParserModule;
import org.elasticsearch.index.query.IndexQueryParserService; import org.elasticsearch.index.query.IndexQueryParserService;
import org.elasticsearch.index.query.ParsedQuery; import org.elasticsearch.index.query.ParsedQuery;
import org.elasticsearch.index.query.QueryStringQueryBuilder;
import org.elasticsearch.index.search.NumericRangeFieldDataFilter; import org.elasticsearch.index.search.NumericRangeFieldDataFilter;
import org.elasticsearch.index.search.geo.GeoDistanceFilter; import org.elasticsearch.index.search.geo.GeoDistanceFilter;
import org.elasticsearch.index.search.geo.GeoPolygonFilter; import org.elasticsearch.index.search.geo.GeoPolygonFilter;
@ -80,6 +81,7 @@ import static org.elasticsearch.index.query.QueryBuilders.*;
import static org.elasticsearch.index.query.RegexpFlag.*; import static org.elasticsearch.index.query.RegexpFlag.*;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*; import static org.hamcrest.Matchers.*;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.*;
/** /**
* *
@ -160,6 +162,31 @@ public class SimpleIndexQueryParserTests {
assertThat(termQuery.getTerm(), equalTo(new Term("content", "test"))); assertThat(termQuery.getTerm(), equalTo(new Term("content", "test")));
} }
@Test
public void testQueryStringBoostsBuilder() throws Exception {
IndexQueryParserService queryParser = queryParser();
QueryStringQueryBuilder builder = queryString("field:boosted^2");
Query parsedQuery = queryParser.parse(builder).query();
assertThat(parsedQuery, instanceOf(TermQuery.class));
assertThat(((TermQuery) parsedQuery).getTerm(), equalTo(new Term("field", "boosted")));
assertThat(parsedQuery.getBoost(), equalTo(2.0f));
builder.boost(2.0f);
parsedQuery = queryParser.parse(builder).query();
assertThat(parsedQuery.getBoost(), equalTo(4.0f));
builder = queryString("((field:boosted^2) AND (field:foo^1.5))^3");
parsedQuery = queryParser.parse(builder).query();
assertThat(parsedQuery, instanceOf(BooleanQuery.class));
assertThat(assertBooleanSubQuery(parsedQuery, TermQuery.class, 0).getTerm(), equalTo(new Term("field", "boosted")));
assertThat(assertBooleanSubQuery(parsedQuery, TermQuery.class, 0).getBoost(), equalTo(2.0f));
assertThat(assertBooleanSubQuery(parsedQuery, TermQuery.class, 1).getTerm(), equalTo(new Term("field", "foo")));
assertThat(assertBooleanSubQuery(parsedQuery, TermQuery.class, 1).getBoost(), equalTo(1.5f));
assertThat(parsedQuery.getBoost(), equalTo(3.0f));
builder.boost(2.0f);
parsedQuery = queryParser.parse(builder).query();
assertThat(parsedQuery.getBoost(), equalTo(6.0f));
}
@Test @Test
public void testQueryStringFields1Builder() throws Exception { public void testQueryStringFields1Builder() throws Exception {
IndexQueryParserService queryParser = queryParser(); IndexQueryParserService queryParser = queryParser();
@ -167,8 +194,8 @@ public class SimpleIndexQueryParserTests {
assertThat(parsedQuery, instanceOf(BooleanQuery.class)); assertThat(parsedQuery, instanceOf(BooleanQuery.class));
BooleanQuery bQuery = (BooleanQuery) parsedQuery; BooleanQuery bQuery = (BooleanQuery) parsedQuery;
assertThat(bQuery.clauses().size(), equalTo(2)); assertThat(bQuery.clauses().size(), equalTo(2));
assertThat(((TermQuery) bQuery.clauses().get(0).getQuery()).getTerm(), equalTo(new Term("content", "test"))); assertThat(assertBooleanSubQuery(parsedQuery, TermQuery.class, 0).getTerm(), equalTo(new Term("content", "test")));
assertThat(((TermQuery) bQuery.clauses().get(1).getQuery()).getTerm(), equalTo(new Term("name", "test"))); assertThat(assertBooleanSubQuery(parsedQuery, TermQuery.class, 1).getTerm(), equalTo(new Term("name", "test")));
} }
@Test @Test
@ -179,8 +206,8 @@ public class SimpleIndexQueryParserTests {
assertThat(parsedQuery, instanceOf(BooleanQuery.class)); assertThat(parsedQuery, instanceOf(BooleanQuery.class));
BooleanQuery bQuery = (BooleanQuery) parsedQuery; BooleanQuery bQuery = (BooleanQuery) parsedQuery;
assertThat(bQuery.clauses().size(), equalTo(2)); assertThat(bQuery.clauses().size(), equalTo(2));
assertThat(((TermQuery) bQuery.clauses().get(0).getQuery()).getTerm(), equalTo(new Term("content", "test"))); assertThat(assertBooleanSubQuery(parsedQuery, TermQuery.class, 0).getTerm(), equalTo(new Term("content", "test")));
assertThat(((TermQuery) bQuery.clauses().get(1).getQuery()).getTerm(), equalTo(new Term("name", "test"))); assertThat(assertBooleanSubQuery(parsedQuery, TermQuery.class, 1).getTerm(), equalTo(new Term("name", "test")));
} }
@Test @Test
@ -191,8 +218,8 @@ public class SimpleIndexQueryParserTests {
assertThat(parsedQuery, instanceOf(BooleanQuery.class)); assertThat(parsedQuery, instanceOf(BooleanQuery.class));
BooleanQuery bQuery = (BooleanQuery) parsedQuery; BooleanQuery bQuery = (BooleanQuery) parsedQuery;
assertThat(bQuery.clauses().size(), equalTo(2)); assertThat(bQuery.clauses().size(), equalTo(2));
assertThat(((TermQuery) bQuery.clauses().get(0).getQuery()).getTerm(), equalTo(new Term("name.first", "test"))); assertThat(assertBooleanSubQuery(parsedQuery, TermQuery.class, 0).getTerm(), equalTo(new Term("name.first", "test")));
assertThat(((TermQuery) bQuery.clauses().get(1).getQuery()).getTerm(), equalTo(new Term("name.last", "test"))); assertThat(assertBooleanSubQuery(parsedQuery, TermQuery.class, 1).getTerm(), equalTo(new Term("name.last", "test")));
} }
@Test @Test