This is an automated email from the ASF dual-hosted git repository.

ishan pushed a commit to branch jira/solr-17927
in repository https://gitbox.apache.org/repos/asf/solr.git

commit c113bd6855e019d3620264263ba6dec268b60e50
Author: Elia <[email protected]>
AuthorDate: Wed Dec 10 17:33:26 2025 +0100

    Fix Exception handling
    Handled NaN value
    Added tests
---
 .../org/apache/solr/search/vector/KnnQParser.java  |  5 +-
 .../apache/solr/search/vector/KnnQParserTest.java  | 96 ++++++++++++++++++++++
 2 files changed, 99 insertions(+), 2 deletions(-)

diff --git a/solr/core/src/java/org/apache/solr/search/vector/KnnQParser.java 
b/solr/core/src/java/org/apache/solr/search/vector/KnnQParser.java
index 413eebe54f4..9220afd3c98 100644
--- a/solr/core/src/java/org/apache/solr/search/vector/KnnQParser.java
+++ b/solr/core/src/java/org/apache/solr/search/vector/KnnQParser.java
@@ -110,8 +110,9 @@ public class KnnQParser extends AbstractVectorQParserBase {
     final int topK = localParams.getInt(TOP_K, DEFAULT_TOP_K);
 
     final double efSearchScaleFactor = 
localParams.getDouble("efSearchScaleFactor", 1.0);
-    if (efSearchScaleFactor < 1.0) {
-      throw new IllegalArgumentException(
+    if (Double.isNaN(efSearchScaleFactor) || efSearchScaleFactor < 1.0) {
+      throw new SolrException(
+          SolrException.ErrorCode.BAD_REQUEST,
           "efSearchScaleFactor (" + efSearchScaleFactor + ") must be >= 1.0");
     }
     final int efSearch = (int) Math.round(efSearchScaleFactor * topK);
diff --git 
a/solr/core/src/test/org/apache/solr/search/vector/KnnQParserTest.java 
b/solr/core/src/test/org/apache/solr/search/vector/KnnQParserTest.java
index 5649fdae6e5..35a12b56a95 100644
--- a/solr/core/src/test/org/apache/solr/search/vector/KnnQParserTest.java
+++ b/solr/core/src/test/org/apache/solr/search/vector/KnnQParserTest.java
@@ -138,6 +138,49 @@ public class KnnQParserTest extends SolrTestCaseJ4 {
         SolrException.ErrorCode.BAD_REQUEST);
   }
 
+  @Test
+  public void efSearchScaleFactorLessThanOne_shouldThrowException() {
+    String vectorToSearch = "[1.0, 2.0, 3.0, 4.0]";
+
+    assertQEx(
+        "efSearchScaleFactor < 1.0 should throw Exception",
+        "efSearchScaleFactor (0.5) must be >= 1.0",
+        req(CommonParams.Q, "{!knn f=vector topK=5 efSearchScaleFactor=0.5}" + 
vectorToSearch, "fl", "id"),
+        SolrException.ErrorCode.BAD_REQUEST);
+
+    assertQEx(
+        "efSearchScaleFactor = 0.0 should throw Exception",
+        "efSearchScaleFactor (0.0) must be >= 1.0",
+        req(CommonParams.Q, "{!knn f=vector topK=5 efSearchScaleFactor=0.0}" + 
vectorToSearch, "fl", "id"),
+        SolrException.ErrorCode.BAD_REQUEST);
+  }
+
+  @Test
+  public void efSearchScaleFactorNaN_shouldThrowException() {
+    String vectorToSearch = "[1.0, 2.0, 3.0, 4.0]";
+
+    assertQEx(
+        "efSearchScaleFactor = NaN should throw Exception",
+        "efSearchScaleFactor (NaN) must be >= 1.0",
+        req(CommonParams.Q, "{!knn f=vector topK=5 efSearchScaleFactor=NaN}" + 
vectorToSearch, "fl", "id"),
+        SolrException.ErrorCode.BAD_REQUEST);
+  }
+
+  @Test
+  public void efSearchScaleFactorSet_shouldWorkCorrectly() {
+    String vectorToSearch = "[1.0, 2.0, 3.0, 4.0]";
+
+    // Test functional behavior with efSearchScaleFactor = 2.0
+    assertQ(
+        req(CommonParams.Q, "{!knn f=vector topK=5 efSearchScaleFactor=2.0}" + 
vectorToSearch, "fl", "id"),
+        "//result[@numFound='5']",
+        "//result/doc[1]/str[@name='id'][.='1']",
+        "//result/doc[2]/str[@name='id'][.='4']",
+        "//result/doc[3]/str[@name='id'][.='2']",
+        "//result/doc[4]/str[@name='id'][.='10']",
+        "//result/doc[5]/str[@name='id'][.='3']");
+  }
+
   @Test
   public void topKMissing_shouldReturnDefaultTopK() {
     String vectorToSearch = "[1.0, 2.0, 3.0, 4.0]";
@@ -442,6 +485,59 @@ public class KnnQParserTest extends SolrTestCaseJ4 {
         "//result/doc[10]/str[@name='id'][.='8']");
   }
 
+
+  @Test
+  public void efSearchScaleFactorWithEarlyTermination_shouldWorkCorrectly() {
+    String vectorToSearch = "[1.0, 2.0, 3.0, 4.0]";
+
+    // Test efSearchScaleFactor with early termination enabled - should return 
results
+    assertQ(
+        req(
+            CommonParams.Q,
+            "{!knn f=vector topK=5 efSearchScaleFactor=2.0 
earlyTermination=true saturationThreshold=0.989 patience=10}"
+                + vectorToSearch,
+            "fl",
+            "id"),
+        "//result[@numFound='5']",
+        "//result/doc[1]/str[@name='id'][.='1']",
+        "//result/doc[2]/str[@name='id'][.='4']");
+  }
+
+  @Test
+  public void efSearchScaleFactorWithSeedQuery_shouldWorkCorrectly() {
+    String vectorToSearch = "[1.0, 2.0, 3.0, 4.0]";
+
+    // Test efSearchScaleFactor with seed query - should return results
+    assertQ(
+        req(
+            CommonParams.Q,
+            "{!knn f=vector topK=4 efSearchScaleFactor=1.5 seedQuery='id:(1 4 
7 8 9)'}" + vectorToSearch,
+            "fl",
+            "id"),
+        "//result[@numFound='4']");
+  }
+
+  @Test
+  public void efSearchScaleFactorWithByteVectors_shouldWorkCorrectly() {
+    String vectorToSearch = "[2, 2, 1, 3]";
+
+    // Test functional behavior with byte vectors and efSearchScaleFactor
+    assertQ(
+        req(CommonParams.Q, "{!knn f=vector_byte_encoding topK=3 
efSearchScaleFactor=1.5}" + vectorToSearch, "fl", "id"),
+        "//result[@numFound='3']",
+        "//result/doc[1]/str[@name='id'][.='2']",
+        "//result/doc[2]/str[@name='id'][.='3']",
+        "//result/doc[3]/str[@name='id'][.='1']");
+
+    // Also test with default efSearchScaleFactor
+    assertQ(
+        req(CommonParams.Q, "{!knn f=vector_byte_encoding topK=3}" + 
vectorToSearch, "fl", "id"),
+        "//result[@numFound='3']",
+        "//result/doc[1]/str[@name='id'][.='2']",
+        "//result/doc[2]/str[@name='id'][.='3']",
+        "//result/doc[3]/str[@name='id'][.='1']");
+  }
+
   @Test
   public void 
knnQueryUsedInFilter_shouldFilterResultsBeforeTheQueryExecution() {
     String vectorToSearch = "[1.0, 2.0, 3.0, 4.0]";

Reply via email to