diff --git a/docs/changelog/91195.yaml b/docs/changelog/91195.yaml new file mode 100644 index 0000000000000..f42ed122a3f0b --- /dev/null +++ b/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 diff --git a/server/src/main/java/org/elasticsearch/index/query/functionscore/DecayFunctionBuilder.java b/server/src/main/java/org/elasticsearch/index/query/functionscore/DecayFunctionBuilder.java index e358314bade8d..f92116a483866 100644 --- a/server/src/main/java/org/elasticsearch/index/query/functionscore/DecayFunctionBuilder.java +++ b/server/src/main/java/org/elasticsearch/index/query/functionscore/DecayFunctionBuilder.java @@ -79,9 +79,7 @@ protected DecayFunctionBuilder(String fieldName, Object origin, Object scale, Ob 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 @@ protected DecayFunctionBuilder(String fieldName, BytesReference functionBytes) { 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. */ diff --git a/server/src/main/java/org/elasticsearch/index/query/functionscore/LinearDecayFunctionBuilder.java b/server/src/main/java/org/elasticsearch/index/query/functionscore/LinearDecayFunctionBuilder.java index 4d7f8dffc67e3..f4729a59cef30 100644 --- a/server/src/main/java/org/elasticsearch/index/query/functionscore/LinearDecayFunctionBuilder.java +++ b/server/src/main/java/org/elasticsearch/index/query/functionscore/LinearDecayFunctionBuilder.java @@ -39,6 +39,13 @@ public LinearDecayFunctionBuilder(StreamInput in) throws IOException { 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; diff --git a/server/src/test/java/org/elasticsearch/index/query/functionscore/ScoreFunctionBuilderTests.java b/server/src/test/java/org/elasticsearch/index/query/functionscore/ScoreFunctionBuilderTests.java index d57db8e251ba5..c3ce1757a8dde 100644 --- a/server/src/test/java/org/elasticsearch/index/query/functionscore/ScoreFunctionBuilderTests.java +++ b/server/src/test/java/org/elasticsearch/index/query/functionscore/ScoreFunctionBuilderTests.java @@ -40,6 +40,17 @@ public void testIllegalArguments() { 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);