parent
dc0d81b8aa
commit
a2de34eead
|
@ -26,14 +26,14 @@ import java.io.IOException;
|
|||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A query that uses a script to compute the score.
|
||||
*
|
||||
*
|
||||
* A query that uses a script to compute or influence the score of documents that match with the inner query or filter.
|
||||
*/
|
||||
public class CustomScoreQueryBuilder extends BaseQueryBuilder implements BoostableQueryBuilder<CustomScoreQueryBuilder> {
|
||||
|
||||
private final QueryBuilder queryBuilder;
|
||||
|
||||
private final FilterBuilder filterBuilder;
|
||||
|
||||
private String script;
|
||||
|
||||
private String lang;
|
||||
|
@ -43,12 +43,24 @@ public class CustomScoreQueryBuilder extends BaseQueryBuilder implements Boostab
|
|||
private Map<String, Object> params = null;
|
||||
|
||||
/**
|
||||
* A query that simply applies the boost factor to another query (multiply it).
|
||||
* Constructs a query that defines how the scores are computed or influenced for documents that match with the
|
||||
* specified query by a custom defined script.
|
||||
*
|
||||
* @param queryBuilder The query to apply the boost factor to.
|
||||
* @param queryBuilder The query that defines what documents are custom scored by this query
|
||||
*/
|
||||
public CustomScoreQueryBuilder(QueryBuilder queryBuilder) {
|
||||
this.queryBuilder = queryBuilder;
|
||||
this.filterBuilder = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a query that defines how documents are scored that match with the specified filter.
|
||||
*
|
||||
* @param filterBuilder The filter that decides with documents are scored by this query.
|
||||
*/
|
||||
public CustomScoreQueryBuilder(FilterBuilder filterBuilder) {
|
||||
this.filterBuilder = filterBuilder;
|
||||
this.queryBuilder = null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -102,8 +114,13 @@ public class CustomScoreQueryBuilder extends BaseQueryBuilder implements Boostab
|
|||
@Override
|
||||
protected void doXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject(CustomScoreQueryParser.NAME);
|
||||
builder.field("query");
|
||||
queryBuilder.toXContent(builder, params);
|
||||
if (queryBuilder != null) {
|
||||
builder.field("query");
|
||||
queryBuilder.toXContent(builder, params);
|
||||
} else if (filterBuilder != null) {
|
||||
builder.field("filter");
|
||||
filterBuilder.toXContent(builder, params);
|
||||
}
|
||||
builder.field("script", script);
|
||||
if (lang != null) {
|
||||
builder.field("lang", lang);
|
||||
|
|
|
@ -20,8 +20,9 @@
|
|||
package org.elasticsearch.index.query;
|
||||
|
||||
import org.apache.lucene.index.AtomicReaderContext;
|
||||
import org.apache.lucene.index.IndexReader;
|
||||
import org.apache.lucene.search.ConstantScoreQuery;
|
||||
import org.apache.lucene.search.Explanation;
|
||||
import org.apache.lucene.search.Filter;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
|
@ -55,7 +56,8 @@ public class CustomScoreQueryParser implements QueryParser {
|
|||
XContentParser parser = parseContext.parser();
|
||||
|
||||
Query query = null;
|
||||
boolean queryFound = false;
|
||||
Filter filter = null;
|
||||
boolean queryOrFilterFound = false;
|
||||
float boost = 1.0f;
|
||||
String script = null;
|
||||
String scriptLang = null;
|
||||
|
@ -69,7 +71,10 @@ public class CustomScoreQueryParser implements QueryParser {
|
|||
} else if (token == XContentParser.Token.START_OBJECT) {
|
||||
if ("query".equals(currentFieldName)) {
|
||||
query = parseContext.parseInnerQuery();
|
||||
queryFound = true;
|
||||
queryOrFilterFound = true;
|
||||
} else if ("filter".equals(currentFieldName)) {
|
||||
filter = parseContext.parseInnerFilter();
|
||||
queryOrFilterFound = true;
|
||||
} else if ("params".equals(currentFieldName)) {
|
||||
vars = parser.map();
|
||||
} else {
|
||||
|
@ -87,14 +92,16 @@ public class CustomScoreQueryParser implements QueryParser {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (!queryFound) {
|
||||
throw new QueryParsingException(parseContext.index(), "[custom_score] requires 'query' field");
|
||||
if (!queryOrFilterFound) {
|
||||
throw new QueryParsingException(parseContext.index(), "[custom_score] requires 'query' or 'filter' field");
|
||||
}
|
||||
if (script == null) {
|
||||
throw new QueryParsingException(parseContext.index(), "[custom_score] requires 'script' field");
|
||||
}
|
||||
if (query == null) {
|
||||
if (query == null && filter == null) {
|
||||
return null;
|
||||
} else if (filter != null) {
|
||||
query = new ConstantScoreQuery(filter);
|
||||
}
|
||||
|
||||
SearchScript searchScript;
|
||||
|
|
|
@ -520,6 +520,16 @@ public abstract class QueryBuilders {
|
|||
return new CustomScoreQueryBuilder(queryBuilder);
|
||||
}
|
||||
|
||||
/**
|
||||
* A query that allows to define a custom scoring script, that defines the score for each document that match
|
||||
* with the specified filter.
|
||||
*
|
||||
* @param filterBuilder The filter that defines which documents are scored by a script.
|
||||
*/
|
||||
public static CustomScoreQueryBuilder customScoreQuery(FilterBuilder filterBuilder) {
|
||||
return new CustomScoreQueryBuilder(filterBuilder);
|
||||
}
|
||||
|
||||
public static CustomFiltersScoreQueryBuilder customFiltersScoreQuery(QueryBuilder queryBuilder) {
|
||||
return new CustomFiltersScoreQueryBuilder(queryBuilder);
|
||||
}
|
||||
|
|
|
@ -309,6 +309,19 @@ public class CustomScoreSearchTests extends AbstractSharedClusterTest {
|
|||
logger.info("Hit[1] {} Explanation {}", response.getHits().getAt(1).id(), response.getHits().getAt(1).explanation());
|
||||
assertThat(response.getHits().getAt(0).id(), equalTo("1"));
|
||||
assertThat(response.getHits().getAt(1).id(), equalTo("2"));
|
||||
|
||||
logger.info("running param1 * param2 * _score with filter instead of query");
|
||||
response = client().search(searchRequest()
|
||||
.searchType(SearchType.QUERY_THEN_FETCH)
|
||||
.source(searchSource().explain(true).query(customScoreQuery(termFilter("test", "value")).script("param1 * param2 * _score").param("param1", 2).param("param2", 2)))
|
||||
).actionGet();
|
||||
|
||||
assertThat(response.getHits().totalHits(), equalTo(2l));
|
||||
logger.info("Hit[0] {} Explanation {}", response.getHits().getAt(0).id(), response.getHits().getAt(0).explanation());
|
||||
logger.info("Hit[1] {} Explanation {}", response.getHits().getAt(1).id(), response.getHits().getAt(1).explanation());
|
||||
assertThat(response.getHits().getAt(0).id(), equalTo("1"));
|
||||
assertThat(response.getHits().getAt(0).score(), equalTo(4f)); // _score is always 1
|
||||
assertThat(response.getHits().getAt(1).score(), equalTo(4f)); // _score is always 1
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
Loading…
Reference in New Issue