Prechádzať zdrojové kódy

Allow different decay values depending on the score function (#91195)

closes #78887

Currently, when setting a decay value on a score function, you can only set a value between 0 and 1 **exclusively**, independently of the score function you're using.

This makes sense with gauss and exp score functions, since they use ln(decay) in their formula, and ln(0) does not exist.
But when using linear functions the decay should be allowed to be 0, since the formula would not result in a division by 0.
Matias Salles 3 rokov pred
rodič
commit
f2f9a1f2d9

+ 6 - 0
docs/changelog/91195.yaml

@@ -0,0 +1,6 @@
+pr: 91195
+summary: Allow different decay values depending on the score function
+area: Search
+type: bug
+issues:
+  - 78887

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

@@ -79,9 +79,7 @@ public abstract class DecayFunctionBuilder<DFB extends DecayFunctionBuilder<DFB>
         if (scale == null) {
             throw new IllegalArgumentException("decay function: scale must not be null");
         }
-        if (decay <= 0 || decay >= 1.0) {
-            throw new IllegalStateException("decay function: decay must be in range 0..1!");
-        }
+        validateDecay(decay);
         this.fieldName = fieldName;
         try {
             XContentBuilder builder = XContentFactory.jsonBuilder();
@@ -112,6 +110,15 @@ public abstract class DecayFunctionBuilder<DFB extends DecayFunctionBuilder<DFB>
         this.functionBytes = functionBytes;
     }
 
+    /**
+    * Override this function if you have different validation rules per score function
+    */
+    protected void validateDecay(double decay) {
+        if (decay <= 0 || decay >= 1.0) {
+            throw new IllegalStateException("decay function: decay must be in range (0..1)!");
+        }
+    }
+
     /**
      * Read from a stream.
      */

+ 7 - 0
server/src/main/java/org/elasticsearch/index/query/functionscore/LinearDecayFunctionBuilder.java

@@ -39,6 +39,13 @@ public class LinearDecayFunctionBuilder extends DecayFunctionBuilder<LinearDecay
         super(in);
     }
 
+    @Override
+    protected void validateDecay(double decay) {
+        if (decay < 0 || decay >= 1.0) {
+            throw new IllegalStateException("decay function: decay must be in range [0..1)!");
+        }
+    }
+
     @Override
     public String getName() {
         return NAME;

+ 11 - 0
server/src/test/java/org/elasticsearch/index/query/functionscore/ScoreFunctionBuilderTests.java

@@ -40,6 +40,17 @@ public class ScoreFunctionBuilderTests extends ESTestCase {
         expectThrows(IllegalArgumentException.class, () -> new ExponentialDecayFunctionBuilder("", "", null, "", randomDouble()));
     }
 
+    public void testDecayValues() {
+        expectThrows(IllegalStateException.class, () -> new ExponentialDecayFunctionBuilder("", "", "", "", 0.0));
+        expectThrows(IllegalStateException.class, () -> new ExponentialDecayFunctionBuilder("", "", "", "", 1.0));
+        expectThrows(IllegalStateException.class, () -> new GaussDecayFunctionBuilder("", "", "", "", 0.0));
+        expectThrows(IllegalStateException.class, () -> new GaussDecayFunctionBuilder("", "", "", "", 1.0));
+        expectThrows(IllegalStateException.class, () -> new LinearDecayFunctionBuilder("", "", "", "", 1.0));
+        expectThrows(IllegalStateException.class, () -> new LinearDecayFunctionBuilder("", "", "", "", -1.0));
+        // should not throw since the score formula allows it
+        new LinearDecayFunctionBuilder("", "", "", "", 0.0);
+    }
+
     public void testRandomScoreFunctionWithSeedNoField() throws Exception {
         RandomScoreFunctionBuilder builder = new RandomScoreFunctionBuilder();
         builder.seed(42);