Query DSL: Custom Boost Factory Query, closes #161.
This commit is contained in:
parent
b54f6b77de
commit
c05e2ad1f1
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Licensed to Elastic Search and Shay Banon under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. Elastic Search 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.xcontent;
|
||||
|
||||
import org.elasticsearch.util.xcontent.builder.XContentBuilder;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* A query that simply applies the boost factor to another query (multiply it).
|
||||
*
|
||||
* @author kimchy (shay.banon)
|
||||
*/
|
||||
public class CustomBoostFactorQueryBuilder extends BaseQueryBuilder {
|
||||
|
||||
private final XContentQueryBuilder queryBuilder;
|
||||
|
||||
private float boostFactor = -1;
|
||||
|
||||
/**
|
||||
* A query that simply applies the boost factor to another query (multiply it).
|
||||
*
|
||||
* @param queryBuilder The query to apply the boost factor to.
|
||||
*/
|
||||
public CustomBoostFactorQueryBuilder(XContentQueryBuilder queryBuilder) {
|
||||
this.queryBuilder = queryBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the boost factor for this query.
|
||||
*/
|
||||
public CustomBoostFactorQueryBuilder boostFactor(float boost) {
|
||||
this.boostFactor = boost;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override protected void doXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject(CustomBoostFactorQueryParser.NAME);
|
||||
builder.field("query");
|
||||
queryBuilder.toXContent(builder, params);
|
||||
if (boostFactor != -1) {
|
||||
builder.field("boost_factor", boostFactor);
|
||||
}
|
||||
builder.endObject();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Licensed to Elastic Search and Shay Banon under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. Elastic Search 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.xcontent;
|
||||
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.elasticsearch.index.AbstractIndexComponent;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.index.query.QueryParsingException;
|
||||
import org.elasticsearch.index.settings.IndexSettings;
|
||||
import org.elasticsearch.util.Strings;
|
||||
import org.elasticsearch.util.guice.inject.Inject;
|
||||
import org.elasticsearch.util.lucene.search.CustomBoostFactorQuery;
|
||||
import org.elasticsearch.util.settings.Settings;
|
||||
import org.elasticsearch.util.xcontent.XContentParser;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author kimchy (shay.banon)
|
||||
*/
|
||||
public class CustomBoostFactorQueryParser extends AbstractIndexComponent implements XContentQueryParser {
|
||||
|
||||
public static final String NAME = "custom_boost_factor";
|
||||
|
||||
@Inject public CustomBoostFactorQueryParser(Index index, @IndexSettings Settings settings) {
|
||||
super(index, settings);
|
||||
}
|
||||
|
||||
@Override public String[] names() {
|
||||
return new String[]{NAME, Strings.toCamelCase(NAME)};
|
||||
}
|
||||
|
||||
@Override public Query parse(QueryParseContext parseContext) throws IOException, QueryParsingException {
|
||||
XContentParser parser = parseContext.parser();
|
||||
|
||||
Query query = null;
|
||||
float boost = 1.0f;
|
||||
float boostFactor = 1.0f;
|
||||
|
||||
String currentFieldName = null;
|
||||
XContentParser.Token token;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else if (token == XContentParser.Token.START_OBJECT) {
|
||||
if ("query".equals(currentFieldName)) {
|
||||
query = parseContext.parseInnerQuery();
|
||||
}
|
||||
} else if (token.isValue()) {
|
||||
if ("boost_factor".equals(currentFieldName) || "boostFactor".equals(currentFieldName)) {
|
||||
boostFactor = parser.floatValue();
|
||||
} else if ("boost".equals(currentFieldName)) {
|
||||
boost = parser.floatValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (query == null) {
|
||||
throw new QueryParsingException(index, "[constant_factor_query] requires 'query' element");
|
||||
}
|
||||
CustomBoostFactorQuery customBoostFactorQuery = new CustomBoostFactorQuery(query, boostFactor);
|
||||
customBoostFactorQuery.setBoost(boost);
|
||||
return customBoostFactorQuery;
|
||||
}
|
||||
}
|
|
@ -261,6 +261,15 @@ public abstract class QueryBuilders {
|
|||
return new ConstantScoreQueryBuilder(filterBuilder);
|
||||
}
|
||||
|
||||
/**
|
||||
* A query that simply applies the boost fact to the wrapped query (multiplies it).
|
||||
*
|
||||
* @param queryBuilder The query to apply the boost factor to.
|
||||
*/
|
||||
public static CustomBoostFactorQueryBuilder customBoostFactorQuery(XContentQueryBuilder queryBuilder) {
|
||||
return new CustomBoostFactorQueryBuilder(queryBuilder);
|
||||
}
|
||||
|
||||
/**
|
||||
* A more like this query that finds documents that are "like" the provided {@link MoreLikeThisQueryBuilder#likeText(String)}
|
||||
* which is checked against the fields the query is constructed with.
|
||||
|
|
|
@ -59,6 +59,7 @@ public class XContentQueryParserRegistry {
|
|||
add(queryParsersMap, new WildcardQueryParser(index, indexSettings));
|
||||
add(queryParsersMap, new FilteredQueryParser(index, indexSettings));
|
||||
add(queryParsersMap, new ConstantScoreQueryParser(index, indexSettings));
|
||||
add(queryParsersMap, new CustomBoostFactorQueryParser(index, indexSettings));
|
||||
add(queryParsersMap, new SpanTermQueryParser(index, indexSettings));
|
||||
add(queryParsersMap, new SpanNotQueryParser(index, indexSettings));
|
||||
add(queryParsersMap, new SpanFirstQueryParser(index, indexSettings));
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.elasticsearch.index.analysis.AnalysisService;
|
|||
import org.elasticsearch.index.cache.IndexCache;
|
||||
import org.elasticsearch.index.mapper.MapperService;
|
||||
import org.elasticsearch.index.query.IndexQueryParser;
|
||||
import org.elasticsearch.util.lucene.search.CustomBoostFactorQuery;
|
||||
import org.elasticsearch.util.lucene.search.MoreLikeThisQuery;
|
||||
import org.elasticsearch.util.lucene.search.Queries;
|
||||
import org.elasticsearch.util.lucene.search.TermFilter;
|
||||
|
@ -600,6 +601,26 @@ public class SimpleIndexQueryParserTests {
|
|||
assertThat(((TermFilter) constantScoreQuery.getFilter()).getTerm(), equalTo(new Term("name.last", "banon")));
|
||||
}
|
||||
|
||||
@Test public void testCustomBoostFactorQueryBuilder() throws IOException {
|
||||
IndexQueryParser queryParser = newQueryParser();
|
||||
Query parsedQuery = queryParser.parse(customBoostFactorQuery(termQuery("name.last", "banon")).boostFactor(1.3f));
|
||||
assertThat(parsedQuery, instanceOf(CustomBoostFactorQuery.class));
|
||||
CustomBoostFactorQuery customBoostFactorQuery = (CustomBoostFactorQuery) parsedQuery;
|
||||
assertThat(((TermQuery) customBoostFactorQuery.getSubQuery()).getTerm(), equalTo(new Term("name.last", "banon")));
|
||||
assertThat((double) customBoostFactorQuery.getBoostFactor(), closeTo(1.3, 0.001));
|
||||
}
|
||||
|
||||
|
||||
@Test public void testCustomBoostFactorQuery() throws IOException {
|
||||
IndexQueryParser queryParser = newQueryParser();
|
||||
String query = copyToStringFromClasspath("/org/elasticsearch/index/query/xcontent/custom-boost-factor-query.json");
|
||||
Query parsedQuery = queryParser.parse(query);
|
||||
assertThat(parsedQuery, instanceOf(CustomBoostFactorQuery.class));
|
||||
CustomBoostFactorQuery customBoostFactorQuery = (CustomBoostFactorQuery) parsedQuery;
|
||||
assertThat(((TermQuery) customBoostFactorQuery.getSubQuery()).getTerm(), equalTo(new Term("name.last", "banon")));
|
||||
assertThat((double) customBoostFactorQuery.getBoostFactor(), closeTo(1.3, 0.001));
|
||||
}
|
||||
|
||||
@Test public void testSpanTermQueryBuilder() throws IOException {
|
||||
IndexQueryParser queryParser = newQueryParser();
|
||||
Query parsedQuery = queryParser.parse(spanTermQuery("age", 34));
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"custom_boost_factor" : {
|
||||
"query" : {
|
||||
"term" : { "name.last" : "banon"}
|
||||
},
|
||||
"boost_factor" : 1.3
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue