From 634f1036a0a30569e3816578677c8bb8de264dda Mon Sep 17 00:00:00 2001 From: Britta Weber Date: Mon, 19 Aug 2013 16:07:38 +0200 Subject: [PATCH] add boost_mode to rest interface allow user to set combine functions explicitely via boost_mode variable. --- .../FunctionScoreQueryBuilder.java | 10 ++++ .../FunctionScoreQueryParser.java | 20 +++++++ .../DecayFunctionScoreTests.java | 55 +++++++++++++++++++ 3 files changed, 85 insertions(+) diff --git a/src/main/java/org/elasticsearch/index/query/functionscore/FunctionScoreQueryBuilder.java b/src/main/java/org/elasticsearch/index/query/functionscore/FunctionScoreQueryBuilder.java index ff2d96848ef..61601c6cb76 100644 --- a/src/main/java/org/elasticsearch/index/query/functionscore/FunctionScoreQueryBuilder.java +++ b/src/main/java/org/elasticsearch/index/query/functionscore/FunctionScoreQueryBuilder.java @@ -44,6 +44,8 @@ public class FunctionScoreQueryBuilder extends BaseQueryBuilder implements Boost private Float maxBoost; private String scoreMode; + + private String boostMode; private ArrayList filters = new ArrayList(); private ArrayList scoreFunctions = new ArrayList(); @@ -74,6 +76,11 @@ public class FunctionScoreQueryBuilder extends BaseQueryBuilder implements Boost this.scoreMode = scoreMode; return this; } + + public FunctionScoreQueryBuilder boostMode(String boostMode) { + this.boostMode = boostMode; + return this; + } public FunctionScoreQueryBuilder maxBoost(float maxBoost) { this.maxBoost = maxBoost; @@ -124,6 +131,9 @@ public class FunctionScoreQueryBuilder extends BaseQueryBuilder implements Boost if (scoreMode != null) { builder.field("score_mode", scoreMode); } + if (boostMode != null) { + builder.field("boost_mode", boostMode); + } if (maxBoost != null) { builder.field("max_boost", maxBoost); } diff --git a/src/main/java/org/elasticsearch/index/query/functionscore/FunctionScoreQueryParser.java b/src/main/java/org/elasticsearch/index/query/functionscore/FunctionScoreQueryParser.java index 44812cdb0c1..078b42cfeb4 100644 --- a/src/main/java/org/elasticsearch/index/query/functionscore/FunctionScoreQueryParser.java +++ b/src/main/java/org/elasticsearch/index/query/functionscore/FunctionScoreQueryParser.java @@ -25,6 +25,7 @@ import org.elasticsearch.common.Strings; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.lucene.search.MatchAllDocsFilter; import org.elasticsearch.common.lucene.search.XConstantScoreQuery; +import org.elasticsearch.common.lucene.search.function.CombineFunction; import org.elasticsearch.common.lucene.search.function.FiltersFunctionScoreQuery; import org.elasticsearch.common.lucene.search.function.FunctionScoreQuery; import org.elasticsearch.common.lucene.search.function.ScoreFunction; @@ -67,6 +68,7 @@ public class FunctionScoreQueryParser implements QueryParser { String currentFieldName = null; XContentParser.Token token; + CombineFunction combineFunction = null; while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { currentFieldName = parser.currentName(); @@ -76,6 +78,8 @@ public class FunctionScoreQueryParser implements QueryParser { query = new XConstantScoreQuery(parseContext.parseInnerFilter()); } else if ("score_mode".equals(currentFieldName) || "scoreMode".equals(currentFieldName)) { scoreMode = parseScoreMode(parseContext, parser); + } else if ("boost_mode".equals(currentFieldName) || "boostMode".equals(currentFieldName)) { + combineFunction = parseBoostMode(parseContext, parser); } else if ("max_boost".equals(currentFieldName) || "maxBoost".equals(currentFieldName)) { maxBoost = parser.floatValue(); } else if ("boost".equals(currentFieldName)) { @@ -101,6 +105,9 @@ public class FunctionScoreQueryParser implements QueryParser { // provided. In this case we create a FunctionScoreQuery. if (filterFunctions.size() == 1 && filterFunctions.get(0).filter == null) { FunctionScoreQuery theQuery = new FunctionScoreQuery(query, filterFunctions.get(0).function); + if (combineFunction != null) { + theQuery.setCombineFunction(combineFunction); + } theQuery.setBoost(boost); theQuery.setMaxBoost(maxBoost); return theQuery; @@ -108,6 +115,9 @@ public class FunctionScoreQueryParser implements QueryParser { } else { FiltersFunctionScoreQuery functionScoreQuery = new FiltersFunctionScoreQuery(query, scoreMode, filterFunctions.toArray(new FiltersFunctionScoreQuery.FilterFunction[filterFunctions.size()]), maxBoost); + if (combineFunction != null) { + functionScoreQuery.setCombineFunction(combineFunction); + } functionScoreQuery.setBoost(boost); return functionScoreQuery; } @@ -166,4 +176,14 @@ public class FunctionScoreQueryParser implements QueryParser { throw new QueryParsingException(parseContext.index(), NAME + " illegal score_mode [" + scoreMode + "]"); } } + + private CombineFunction parseBoostMode(QueryParseContext parseContext, XContentParser parser) throws IOException { + String boostMode = parser.text(); + for (CombineFunction cf : CombineFunction.values()) { + if (cf.getName().equals(boostMode)) { + return cf; + } + } + throw new QueryParsingException(parseContext.index(), NAME + " illegal boost_mode [" + boostMode + "]"); + } } \ No newline at end of file diff --git a/src/test/java/org/elasticsearch/test/integration/search/functionscore/DecayFunctionScoreTests.java b/src/test/java/org/elasticsearch/test/integration/search/functionscore/DecayFunctionScoreTests.java index d2bc201c244..2756753556e 100644 --- a/src/test/java/org/elasticsearch/test/integration/search/functionscore/DecayFunctionScoreTests.java +++ b/src/test/java/org/elasticsearch/test/integration/search/functionscore/DecayFunctionScoreTests.java @@ -25,6 +25,7 @@ import org.elasticsearch.action.index.IndexRequestBuilder; import org.elasticsearch.action.search.SearchPhaseExecutionException; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.search.SearchType; +import org.elasticsearch.common.lucene.search.function.CombineFunction; import org.elasticsearch.index.query.MatchAllFilterBuilder; import org.elasticsearch.index.query.functionscore.DecayFunctionBuilder; import org.elasticsearch.index.query.functionscore.exp.ExponentialDecayFunctionBuilder; @@ -147,6 +148,60 @@ public class DecayFunctionScoreTests extends AbstractSharedClusterTest { assertThat(sh.getAt(0).getId(), equalTo("1")); assertThat(sh.getAt(1).getId(), equalTo("2")); } + + + @Test + public void testBoostModeSettingWorks() throws Exception { + + createIndexMapped("test", "type1", "test", "string", "loc", "geo_point"); + ensureYellow(); + + List indexBuilders = new ArrayList(); + indexBuilders.add(new IndexRequestBuilder(client()) + .setType("type1") + .setId("1") + .setIndex("test") + .setSource( + jsonBuilder().startObject().field("test", "value").startObject("loc").field("lat", 11).field("lon", 21).endObject() + .endObject())); + indexBuilders.add(new IndexRequestBuilder(client()) + .setType("type1") + .setId("2") + .setIndex("test") + .setSource( + jsonBuilder().startObject().field("test", "value value").startObject("loc").field("lat", 11).field("lon", 20).endObject() + .endObject())); + IndexRequestBuilder[] builders = indexBuilders.toArray(new IndexRequestBuilder[indexBuilders.size()]); + + indexRandom("test", false, builders); + refresh(); + + // Test Gauss + List lonlat = new ArrayList(); + lonlat.add(new Float(20)); + lonlat.add(new Float(11)); + DecayFunctionBuilder fb = new GaussDecayFunctionBuilder("loc", lonlat, "1000km"); + + ActionFuture response = client().search( + searchRequest().searchType(SearchType.QUERY_THEN_FETCH).source( + searchSource().explain(true).query(functionScoreQuery(termQuery("test", "value")).add(fb).boostMode(CombineFunction.MULT.getName())))); + SearchResponse sr = response.actionGet(); + SearchHits sh = sr.getHits(); + assertThat(sh.getTotalHits(), equalTo((long) (2))); + assertThat(sh.getAt(0).getId(), equalTo("1")); + assertThat(sh.getAt(1).getId(), equalTo("2")); + + // Test Exp + response = client().search( + searchRequest().searchType(SearchType.QUERY_THEN_FETCH).source( + searchSource().explain(true).query(functionScoreQuery(termQuery("test", "value")).add(fb).boostMode(CombineFunction.PLAIN.getName())))); + sr = response.actionGet(); + sh = sr.getHits(); + assertThat(sh.getTotalHits(), equalTo((long) (2))); + assertThat(sh.getAt(0).getId(), equalTo("2")); + assertThat(sh.getAt(1).getId(), equalTo("1")); + + } @Test(expected = SearchPhaseExecutionException.class) public void testExceptionThrownIfScaleLE0() throws Exception {