Browse Source

allow origin not set, defaults to "now" for date fields, exception for all other types

Britta Weber 12 years ago
parent
commit
4938f09d8d

+ 3 - 1
src/main/java/org/elasticsearch/index/query/functionscore/DecayFunctionBuilder.java

@@ -60,7 +60,9 @@ public abstract class DecayFunctionBuilder implements ScoreFunctionBuilder {
     public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
         builder.startObject(getName());
         builder.startObject(fieldName);
-        builder.field(ORIGIN, origin);
+        if (origin != null) {
+            builder.field(ORIGIN, origin);
+        }
         builder.field(SCALE, scale);
         if (decay > 0) {
             builder.field(DECAY, decay);

+ 1 - 1
src/main/java/org/elasticsearch/index/query/functionscore/DecayFunctionParser.java

@@ -254,7 +254,7 @@ public abstract class DecayFunctionParser implements ScoreFunctionParser {
         }
 
         if (scaleString == null) {
-            throw new ElasticSearchParseException(DecayFunctionBuilder.SCALE + "must be set for geo fields.");
+            throw new ElasticSearchParseException(DecayFunctionBuilder.SCALE + "must be set for date fields.");
         }
         TimeValue val = TimeValue.parseTimeValue(scaleString, TimeValue.timeValueHours(24));
         double scale = val.getMillis();

+ 12 - 28
src/main/java/org/elasticsearch/index/query/functionscore/ScoreFunctionBuilders.java

@@ -29,45 +29,29 @@ import org.elasticsearch.index.query.functionscore.script.ScriptScoreFunctionBui
 import java.util.Map;
 
 public class ScoreFunctionBuilders {
-    /**
-     * A query that match on all documents.
-     */
+   
     public static ExponentialDecayFunctionBuilder exponentialDecayFunction(String fieldName, Object origin, Object scale) {
         return new ExponentialDecayFunctionBuilder(fieldName, origin, scale);
     }
-
-    public static ExponentialDecayFunctionBuilder exponentialDecayFunction(String fieldName, Object origin, Object scale, double decay) {
-        return (ExponentialDecayFunctionBuilder) (new ExponentialDecayFunctionBuilder(fieldName, origin, scale)).setDecay(decay);
-    }
-
-    public static ExponentialDecayFunctionBuilder exponentialDecayFunction(String fieldName, Object origin, Object scale, double decay,
-            double offset) {
-        return (ExponentialDecayFunctionBuilder) (new ExponentialDecayFunctionBuilder(fieldName, origin, scale)).setDecay(decay).setOffset(
-                offset);
+    
+    public static ExponentialDecayFunctionBuilder exponentialDecayFunction(String fieldName, Object scale) {
+        return new ExponentialDecayFunctionBuilder(fieldName, null, scale);
     }
-
+    
     public static GaussDecayFunctionBuilder gaussDecayFunction(String fieldName, Object origin, Object scale) {
         return new GaussDecayFunctionBuilder(fieldName, origin, scale);
     }
-
-    public static GaussDecayFunctionBuilder gaussDecayFunction(String fieldName, Object origin, Object scale, double decay) {
-        return (GaussDecayFunctionBuilder) (new GaussDecayFunctionBuilder(fieldName, origin, scale)).setDecay(decay);
+    
+    public static GaussDecayFunctionBuilder gaussDecayFunction(String fieldName, Object scale) {
+        return new GaussDecayFunctionBuilder(fieldName, null, scale);
     }
-
-    public static GaussDecayFunctionBuilder gaussDecayFunction(String fieldName, Object origin, Object scale, double decay, double offset) {
-        return (GaussDecayFunctionBuilder) (new GaussDecayFunctionBuilder(fieldName, origin, scale)).setDecay(decay).setOffset(offset);
-    }
-
+    
     public static LinearDecayFunctionBuilder linearDecayFunction(String fieldName, Object origin, Object scale) {
         return new LinearDecayFunctionBuilder(fieldName, origin, scale);
     }
-
-    public static LinearDecayFunctionBuilder linearDecayFunction(String fieldName, Object origin, Object scale, double decay) {
-        return (LinearDecayFunctionBuilder) (new LinearDecayFunctionBuilder(fieldName, origin, scale)).setDecay(decay);
-    }
-
-    public static LinearDecayFunctionBuilder linearDecayFunction(String fieldName, Object origin, Object scale, double decay, double offset) {
-        return (LinearDecayFunctionBuilder) (new LinearDecayFunctionBuilder(fieldName, origin, scale)).setDecay(decay).setOffset(offset);
+    
+    public static LinearDecayFunctionBuilder linearDecayFunction(String fieldName, Object scale) {
+        return new LinearDecayFunctionBuilder(fieldName, null, scale);
     }
 
     public static ScriptScoreFunctionBuilder scriptFunction(String script) {

+ 105 - 70
src/test/java/org/elasticsearch/search/functionscore/DecayFunctionScoreTests.java

@@ -29,10 +29,12 @@ import org.elasticsearch.action.search.SearchType;
 import org.elasticsearch.common.geo.GeoPoint;
 import org.elasticsearch.common.lucene.search.function.CombineFunction;
 import org.elasticsearch.index.query.MatchAllFilterBuilder;
+import org.elasticsearch.index.query.QueryBuilders;
 import org.elasticsearch.index.query.functionscore.DecayFunctionBuilder;
 import org.elasticsearch.index.query.functionscore.gauss.GaussDecayFunctionBuilder;
 import org.elasticsearch.search.SearchHits;
 import org.elasticsearch.test.hamcrest.ElasticsearchAssertions;
+import org.joda.time.DateTime;
 import org.junit.Test;
 
 import java.util.ArrayList;
@@ -52,11 +54,10 @@ public class DecayFunctionScoreTests extends AbstractSharedClusterTest {
 
     @Test
     public void testDistanceScoreGeoLinGaussExp() throws Exception {
-        assertAcked(prepareCreate("test").addMapping("type1", 
-                jsonBuilder().startObject().startObject("type1").startObject("properties")
-                    .startObject("test").field("type", "string").endObject()
-                    .startObject("loc").field("type", "geo_point").endObject()
-                    .endObject().endObject().endObject()));
+        assertAcked(prepareCreate("test").addMapping(
+                "type1",
+                jsonBuilder().startObject().startObject("type1").startObject("properties").startObject("test").field("type", "string")
+                        .endObject().startObject("loc").field("type", "geo_point").endObject().endObject().endObject().endObject()));
         ensureYellow();
 
         List<IndexRequestBuilder> indexBuilders = new ArrayList<IndexRequestBuilder>();
@@ -154,11 +155,10 @@ public class DecayFunctionScoreTests extends AbstractSharedClusterTest {
 
     @Test
     public void testDistanceScoreGeoLinGaussExpWithOffset() throws Exception {
-        assertAcked(prepareCreate("test").addMapping("type1", 
-                jsonBuilder().startObject().startObject("type1").startObject("properties")
-                    .startObject("test").field("type", "string").endObject()
-                    .startObject("num").field("type", "double").endObject()
-                    .endObject().endObject().endObject()));
+        assertAcked(prepareCreate("test").addMapping(
+                "type1",
+                jsonBuilder().startObject().startObject("type1").startObject("properties").startObject("test").field("type", "string")
+                        .endObject().startObject("num").field("type", "double").endObject().endObject().endObject().endObject()));
         ensureYellow();
 
         // add tw docs within offset
@@ -235,11 +235,10 @@ public class DecayFunctionScoreTests extends AbstractSharedClusterTest {
 
     @Test
     public void testBoostModeSettingWorks() throws Exception {
-        assertAcked(prepareCreate("test").addMapping("type1", 
-                jsonBuilder().startObject().startObject("type1").startObject("properties")
-                    .startObject("test").field("type", "string").endObject()
-                    .startObject("loc").field("type", "geo_point").endObject()
-                    .endObject().endObject().endObject()));
+        assertAcked(prepareCreate("test").addMapping(
+                "type1",
+                jsonBuilder().startObject().startObject("type1").startObject("properties").startObject("test").field("type", "string")
+                        .endObject().startObject("loc").field("type", "geo_point").endObject().endObject().endObject().endObject()));
         ensureYellow();
 
         List<IndexRequestBuilder> indexBuilders = new ArrayList<IndexRequestBuilder>();
@@ -294,11 +293,10 @@ public class DecayFunctionScoreTests extends AbstractSharedClusterTest {
 
     @Test
     public void testParseGeoPoint() throws Exception {
-        assertAcked(prepareCreate("test").addMapping("type1", 
-                jsonBuilder().startObject().startObject("type1").startObject("properties")
-                    .startObject("test").field("type", "string").endObject()
-                    .startObject("loc").field("type", "geo_point").endObject()
-                    .endObject().endObject().endObject()));
+        assertAcked(prepareCreate("test").addMapping(
+                "type1",
+                jsonBuilder().startObject().startObject("type1").startObject("properties").startObject("test").field("type", "string")
+                        .endObject().startObject("loc").field("type", "geo_point").endObject().endObject().endObject().endObject()));
         ensureYellow();
 
         List<IndexRequestBuilder> indexBuilders = new ArrayList<IndexRequestBuilder>();
@@ -341,11 +339,10 @@ public class DecayFunctionScoreTests extends AbstractSharedClusterTest {
     @Test
     public void testCombineModes() throws Exception {
 
-        assertAcked(prepareCreate("test").addMapping("type1", 
-                jsonBuilder().startObject().startObject("type1").startObject("properties")
-                    .startObject("test").field("type", "string").endObject()
-                    .startObject("num").field("type", "double").endObject()
-                    .endObject().endObject().endObject()));
+        assertAcked(prepareCreate("test").addMapping(
+                "type1",
+                jsonBuilder().startObject().startObject("type1").startObject("properties").startObject("test").field("type", "string")
+                        .endObject().startObject("num").field("type", "double").endObject().endObject().endObject().endObject()));
         ensureYellow();
 
         List<IndexRequestBuilder> indexBuilders = new ArrayList<IndexRequestBuilder>();
@@ -434,11 +431,10 @@ public class DecayFunctionScoreTests extends AbstractSharedClusterTest {
 
     @Test(expected = SearchPhaseExecutionException.class)
     public void testExceptionThrownIfScaleLE0() throws Exception {
-        assertAcked(prepareCreate("test").addMapping("type1", 
-                jsonBuilder().startObject().startObject("type1").startObject("properties")
-                    .startObject("test").field("type", "string").endObject()
-                    .startObject("num1").field("type", "date").endObject()
-                    .endObject().endObject().endObject()));
+        assertAcked(prepareCreate("test").addMapping(
+                "type1",
+                jsonBuilder().startObject().startObject("type1").startObject("properties").startObject("test").field("type", "string")
+                        .endObject().startObject("num1").field("type", "date").endObject().endObject().endObject().endObject()));
         ensureYellow();
         client().index(
                 indexRequest("test").type("type1").id("1")
@@ -471,12 +467,11 @@ public class DecayFunctionScoreTests extends AbstractSharedClusterTest {
     @Test
     public void testValueMissingLin() throws Exception {
 
-        assertAcked(prepareCreate("test").addMapping("type1", 
-                jsonBuilder().startObject().startObject("type1").startObject("properties")
-                    .startObject("test").field("type", "string").endObject()
-                    .startObject("num1").field("type", "date").endObject()
-                    .startObject("num2").field("type", "double").endObject()
-                    .endObject().endObject().endObject()));
+        assertAcked(prepareCreate("test").addMapping(
+                "type1",
+                jsonBuilder().startObject().startObject("type1").startObject("properties").startObject("test").field("type", "string")
+                        .endObject().startObject("num1").field("type", "date").endObject().startObject("num2").field("type", "double")
+                        .endObject().endObject().endObject().endObject()));
         ensureYellow();
         client().index(
                 indexRequest("test")
@@ -502,8 +497,7 @@ public class DecayFunctionScoreTests extends AbstractSharedClusterTest {
         ActionFuture<SearchResponse> response = client().search(
                 searchRequest().searchType(SearchType.QUERY_THEN_FETCH).source(
                         searchSource().explain(false).query(
-                                functionScoreQuery(termQuery("test", "value"))
-                                        .add(linearDecayFunction("num1", "2013-05-28", "+3d"))
+                                functionScoreQuery(termQuery("test", "value")).add(linearDecayFunction("num1", "2013-05-28", "+3d"))
                                         .add(linearDecayFunction("num2", "0.0", "1")).scoreMode("multiply"))));
 
         SearchResponse sr = response.actionGet();
@@ -519,15 +513,61 @@ public class DecayFunctionScoreTests extends AbstractSharedClusterTest {
 
     }
 
+    @Test
+    public void testDateWithoutOrigin() throws Exception {
+        DateTime dt = new DateTime();
+
+        assertAcked(prepareCreate("test").addMapping(
+                "type1",
+                jsonBuilder().startObject().startObject("type1").startObject("properties").startObject("test").field("type", "string")
+                        .endObject().startObject("num1").field("type", "date").endObject().endObject().endObject().endObject()));
+        ensureYellow();
+
+        DateTime docDate = dt.minusDays(1);
+        String docDateString = docDate.getYear() + "-" + docDate.getMonthOfYear() + "-" + docDate.getDayOfMonth();
+        client().index(
+                indexRequest("test").type("type1").id("1")
+                        .source(jsonBuilder().startObject().field("test", "value").field("num1", docDateString).endObject())).actionGet();
+        docDate = dt.minusDays(2);
+        docDateString = docDate.getYear() + "-" + docDate.getMonthOfYear() + "-" + docDate.getDayOfMonth();
+        client().index(
+                indexRequest("test").type("type1").id("2")
+                        .source(jsonBuilder().startObject().field("test", "value").field("num1", docDateString).endObject())).actionGet();
+        docDate = dt.minusDays(3);
+        docDateString = docDate.getYear() + "-" + docDate.getMonthOfYear() + "-" + docDate.getDayOfMonth();
+        client().index(
+                indexRequest("test").type("type1").id("3")
+                        .source(jsonBuilder().startObject().field("test", "value").field("num1", docDateString).endObject())).actionGet();
+
+        refresh();
+
+        ActionFuture<SearchResponse> response = client().search(
+                searchRequest().searchType(SearchType.QUERY_THEN_FETCH).source(
+                        searchSource().explain(false).query(
+                                functionScoreQuery(QueryBuilders.matchAllQuery()).add(linearDecayFunction("num1", "1000w"))
+                                        .add(gaussDecayFunction("num1", "1d")).add(exponentialDecayFunction("num1", "1000w"))
+                                        .scoreMode("multiply"))));
+
+        SearchResponse sr = response.actionGet();
+        ElasticsearchAssertions.assertNoFailures(sr);
+        SearchHits sh = sr.getHits();
+        assertThat(sh.hits().length, equalTo(3));
+        double[] scores = new double[4];
+        for (int i = 0; i < sh.hits().length; i++) {
+            scores[Integer.parseInt(sh.getAt(i).getId()) - 1] = sh.getAt(i).getScore();
+        }
+        assertThat(scores[1], lessThan(scores[0]));
+        assertThat(scores[2], lessThan(scores[1]));
+
+    }
+
     @Test
     public void testManyDocsLin() throws Exception {
-        assertAcked(prepareCreate("test").addMapping("type", 
-                jsonBuilder().startObject().startObject("type").startObject("properties")
-                    .startObject("test").field("type", "string").endObject()
-                    .startObject("date").field("type", "date").endObject()
-                    .startObject("num").field("type", "double").endObject()
-                    .startObject("geo").field("type", "geo_point").endObject()
-                    .endObject().endObject().endObject()));
+        assertAcked(prepareCreate("test").addMapping(
+                "type",
+                jsonBuilder().startObject().startObject("type").startObject("properties").startObject("test").field("type", "string")
+                        .endObject().startObject("date").field("type", "date").endObject().startObject("num").field("type", "double")
+                        .endObject().startObject("geo").field("type", "geo_point").endObject().endObject().endObject().endObject()));
         ensureYellow();
         int numDocs = 200;
         List<IndexRequestBuilder> indexBuilders = new ArrayList<IndexRequestBuilder>();
@@ -554,13 +594,11 @@ public class DecayFunctionScoreTests extends AbstractSharedClusterTest {
         lonlat.add(new Float(110));
         ActionFuture<SearchResponse> response = client().search(
                 searchRequest().searchType(SearchType.QUERY_THEN_FETCH).source(
-                        searchSource()
-                                .size(numDocs)
-                                .query(functionScoreQuery(termQuery("test", "value"))
+                        searchSource().size(numDocs).query(
+                                functionScoreQuery(termQuery("test", "value"))
                                         .add(new MatchAllFilterBuilder(), linearDecayFunction("date", "2013-05-30", "+15d"))
                                         .add(new MatchAllFilterBuilder(), linearDecayFunction("geo", lonlat, "1000km"))
-                                        .add(new MatchAllFilterBuilder(),
-                                                linearDecayFunction("num", numDocs, numDocs / 2.0))
+                                        .add(new MatchAllFilterBuilder(), linearDecayFunction("num", numDocs, numDocs / 2.0))
                                         .scoreMode("multiply").boostMode(CombineFunction.REPLACE.getName()))));
 
         SearchResponse sr = response.actionGet();
@@ -580,11 +618,10 @@ public class DecayFunctionScoreTests extends AbstractSharedClusterTest {
 
     @Test(expected = SearchPhaseExecutionException.class)
     public void testParsingExceptionIfFieldDoesNotExist() throws Exception {
-        assertAcked(prepareCreate("test").addMapping("type", 
-                jsonBuilder().startObject().startObject("type").startObject("properties")
-                    .startObject("test").field("type", "string").endObject()
-                    .startObject("geo").field("type", "geo_point").endObject()
-                    .endObject().endObject().endObject()));
+        assertAcked(prepareCreate("test").addMapping(
+                "type",
+                jsonBuilder().startObject().startObject("type").startObject("properties").startObject("test").field("type", "string")
+                        .endObject().startObject("geo").field("type", "geo_point").endObject().endObject().endObject().endObject()));
         ensureYellow();
         int numDocs = 2;
         client().index(
@@ -608,11 +645,10 @@ public class DecayFunctionScoreTests extends AbstractSharedClusterTest {
 
     @Test(expected = SearchPhaseExecutionException.class)
     public void testParsingExceptionIfFieldTypeDoesNotMatch() throws Exception {
-        assertAcked(prepareCreate("test").addMapping("type", 
-                jsonBuilder().startObject().startObject("type").startObject("properties")
-                    .startObject("test").field("type", "string").endObject()
-                    .startObject("num").field("type", "string").endObject()
-                    .endObject().endObject().endObject()));
+        assertAcked(prepareCreate("test").addMapping(
+                "type",
+                jsonBuilder().startObject().startObject("type").startObject("properties").startObject("test").field("type", "string")
+                        .endObject().startObject("num").field("type", "string").endObject().endObject().endObject().endObject()));
         ensureYellow();
         client().index(
                 indexRequest("test").type("type").source(
@@ -626,26 +662,25 @@ public class DecayFunctionScoreTests extends AbstractSharedClusterTest {
                                         linearDecayFunction("num", 1.0, 0.5)).scoreMode("multiply"))));
         response.actionGet();
     }
+
     @Test
     public void testNoQueryGiven() throws Exception {
-        assertAcked(prepareCreate("test").addMapping("type", 
-                jsonBuilder().startObject().startObject("type").startObject("properties")
-                    .startObject("test").field("type", "string").endObject()
-                    .startObject("num").field("type", "double").endObject()
-                    .endObject().endObject().endObject()));
+        assertAcked(prepareCreate("test").addMapping(
+                "type",
+                jsonBuilder().startObject().startObject("type").startObject("properties").startObject("test").field("type", "string")
+                        .endObject().startObject("num").field("type", "double").endObject().endObject().endObject().endObject()));
         ensureYellow();
         client().index(
-                indexRequest("test").type("type").source(
-                        jsonBuilder().startObject().field("test", "value").field("num", 1.0).endObject())).actionGet();
+                indexRequest("test").type("type").source(jsonBuilder().startObject().field("test", "value").field("num", 1.0).endObject()))
+                .actionGet();
         refresh();
         // so, we indexed a string field, but now we try to score a num field
         ActionFuture<SearchResponse> response = client().search(
                 searchRequest().searchType(SearchType.QUERY_THEN_FETCH).source(
                         searchSource().explain(true).query(
-                                functionScoreQuery().add(new MatchAllFilterBuilder(),
-                                        linearDecayFunction("num", 1, 0.5)).scoreMode("multiply"))));
+                                functionScoreQuery().add(new MatchAllFilterBuilder(), linearDecayFunction("num", 1, 0.5)).scoreMode(
+                                        "multiply"))));
         response.actionGet();
     }
 
-
 }