ilariapet commented on code in PR #3644:
URL: https://github.com/apache/solr/pull/3644#discussion_r2336672975


##########
solr/core/src/test/org/apache/solr/search/neural/KnnQParserTest.java:
##########
@@ -967,4 +968,281 @@ public void 
knnQueryAsRerank_shouldAddSimilarityFunctionScore() {
         "//result/doc[3]/str[@name='id'][.='3']",
         "//result/doc[4]/str[@name='id'][.='9']");
   }
+
+  @Test
+  public void 
testKnnFloatWithoutExplicitlyEarlyTermination_returnsKnnFloatVectorQuery() {
+    // It verifies that when no early termination parameters are provided,
+    // the default behavior is applied (early termination is disabled), and no 
special logic is
+    // triggered.
+    String vectorToSearch = "[1.0, 2.0, 3.0, 4.0]";
+
+    assertQ(
+        req(
+            CommonParams.Q,
+            "{!knn f=vector topK=5}" + vectorToSearch,
+            "fl",
+            "id",
+            "debugQuery",
+            "true"),
+        "//result[@numFound='5']",
+        
"//str[@name='parsedquery'][.='KnnFloatVectorQuery(KnnFloatVectorQuery:vector[1.0,...][5])']");
+  }
+
+  @Test
+  public void testKnnFloatWithoutEarlyTermination_returnsKnnFloatVectorQuery() 
{
+    // It verifies that when early termination is explicitly set to false, no 
special logic is
+    // triggered.
+    String vectorToSearch = "[1.0, 2.0, 3.0, 4.0]";
+
+    assertQ(
+        req(
+            CommonParams.Q,
+            "{!knn f=vector topK=5 earlyTermination=false}" + vectorToSearch,
+            "fl",
+            "id",
+            "debugQuery",
+            "true"),
+        "//result[@numFound='5']",
+        
"//str[@name='parsedquery'][.='KnnFloatVectorQuery(KnnFloatVectorQuery:vector[1.0,...][5])']");
+  }
+
+  @Test
+  public void 
testKnnFloatWithEarlyTerminationDefaultParams_returnsPatienceKnnVectorQuery() {
+    // It verifies that when early termination is explicitly set to true but 
no other parameters are
+    // provided, the PatienceKnnVectorQuery is executed using the default 
values for
+    // saturationThreshold and
+    // patience.
+    String vectorToSearch = "[1.0, 2.0, 3.0, 4.0]";
+
+    // IMPORTANT: The default values for `saturationThreshold` and `patience` 
are hardcoded here
+    // because they are currently private in Lucene's PatienceKnnVectorQuery 
implementation.
+    // If Lucene changes these defaults in a future release, this test will 
break and must be
+    // updated accordingly.
+    double defaultSaturationThreshold = 0.995;
+    int defaultPatience = 7;
+
+    String expectedParsedQuery =
+        String.format(
+            Locale.US,
+            
"PatienceKnnVectorQuery(PatienceKnnVectorQuery{saturationThreshold=%.3f, 
patience=%d, delegate=KnnFloatVectorQuery:vector[1.0,...][10]})",
+            defaultSaturationThreshold,
+            defaultPatience);
+
+    assertQ(
+        req(
+            CommonParams.Q,
+            "{!knn f=vector topK=10 earlyTermination=true}" + vectorToSearch,
+            "fl",
+            "id",
+            "debugQuery",
+            "true"),
+        "//result[@numFound='10']",
+        "//str[@name='parsedquery'][.='" + expectedParsedQuery + "']");
+  }
+
+  @Test
+  public void
+      
testKnnFloatWithEarlyTerminationCustomParams_returnsPatienceKnnVectorQueryCustomParams()
 {
+    // It verifies that when early termination is explicitly set to true and 
both
+    // saturationThreshold and patience
+    // parameters are provided, the PatienceKnnVectorQuery is executed using 
the specified custom
+    // values.
+    String vectorToSearch = "[1.0, 2.0 ,3.0, 4.0]";
+
+    double customSaturationThreshold = 0.989;
+    int customPatience = 10;
+
+    String query =
+        String.format(
+            Locale.US,
+            "{!knn f=vector topK=10 earlyTermination=true 
saturationThreshold=%.3f patience=%d}"
+                + vectorToSearch,
+            customSaturationThreshold,
+            customPatience);
+
+    String expectedParsedQuery =
+        String.format(
+            Locale.US,
+            
"PatienceKnnVectorQuery(PatienceKnnVectorQuery{saturationThreshold=%.3f, 
patience=%d, delegate=KnnFloatVectorQuery:vector[1.0,...][10]})",
+            customSaturationThreshold,
+            customPatience);
+
+    assertQ(
+        req(CommonParams.Q, query, "fl", "id", "debugQuery", "true"),
+        "//result[@numFound='10']",
+        "//str[@name='parsedquery'][.='" + expectedParsedQuery + "']");
+  }
+
+  @Test
+  public void
+      
testKnnByteWithEarlyTerminationCustomParams_returnsPatienceKnnVectorQueryCustomParams()
 {
+    // It verifies that when early termination is explicitly set to true and 
both
+    // saturationThreshold and patience
+    // parameters are provided, the PatienceKnnVectorQuery is executed using 
the specified custom
+    // values.
+    String vectorToSearch = "[2, 2, 1, 3]";
+
+    double customSaturationThreshold = 0.989;
+    int customPatience = 10;
+
+    String query =
+        String.format(
+            Locale.US,
+            "{!knn f=vector_byte_encoding topK=5 earlyTermination=true 
saturationThreshold=%.3f patience=%d}"
+                + vectorToSearch,
+            customSaturationThreshold,
+            customPatience);
+
+    String expectedParsedQuery =
+        String.format(
+            Locale.US,
+            
"PatienceKnnVectorQuery(PatienceKnnVectorQuery{saturationThreshold=%.3f, 
patience=%d, delegate=KnnByteVectorQuery:vector_byte_encoding[2,...][5]})",
+            customSaturationThreshold,
+            customPatience);
+
+    assertQ(
+        req(CommonParams.Q, query, "fl", "id", "debugQuery", "true"),
+        "//result[@numFound='5']",
+        "//str[@name='parsedquery'][.='" + expectedParsedQuery + "']");
+  }
+
+  @Test
+  public void
+      
testKnnFloatWithEarlyTerminationOnlyCustomParams_returnsPatienceKnnVectorQueryCustomParams()
 {
+    // It verifies that when early termination is NOT explicitly passed but 
both saturationThreshold
+    // and patience
+    // parameters are provided, the PatienceKnnVectorQuery is executed using 
the specified custom
+    // values.
+    String vectorToSearch = "[1.0, 2.0 ,3.0, 4.0]";
+
+    double customSaturationThreshold = 0.989;
+    int customPatience = 10;
+
+    String query =
+        String.format(
+            Locale.US,
+            "{!knn f=vector topK=10 saturationThreshold=%.3f patience=%d}" + 
vectorToSearch,
+            customSaturationThreshold,
+            customPatience);
+
+    String expectedParsedQuery =
+        String.format(
+            Locale.US,
+            
"PatienceKnnVectorQuery(PatienceKnnVectorQuery{saturationThreshold=%.3f, 
patience=%d, delegate=KnnFloatVectorQuery:vector[1.0,...][10]})",
+            customSaturationThreshold,
+            customPatience);
+
+    assertQ(
+        req(CommonParams.Q, query, "fl", "id", "debugQuery", "true"),
+        "//result[@numFound='10']",
+        "//str[@name='parsedquery'][.='" + expectedParsedQuery + "']");
+  }
+
+  @Test
+  public void outOfRangeSaturationThresholdValue_shouldThrowException() {
+    // It verifies that when an invalid saturationThreshold value (<= 0.0 or 
>= 1.0)
+    // is provided in the query, Solr throws a BAD_REQUEST exception with the 
expected message.
+    String vectorToSearch = "[1.0, 2.0, 3.0, 4.0]";
+
+    double saturationThreshold = 2.0; // out of range
+    int patience = 10;
+
+    assertQEx(
+        "Invalid saturationThreshold value: must be a double between 0.0 and 
1.0 (exclusive), got 2.0",
+        req(
+            CommonParams.Q,
+            String.format(
+                Locale.ROOT,
+                "{!knn f=vector topK=10 saturationThreshold=%.3f 
patience=%d}%s",
+                saturationThreshold,
+                patience,
+                vectorToSearch)),
+        SolrException.ErrorCode.BAD_REQUEST);
+  }
+
+  @Test
+  public void incorrectSaturationThresholdValue_shouldThrowException() {

Review Comment:
   check it



##########
solr/core/src/test/org/apache/solr/search/neural/KnnQParserTest.java:
##########
@@ -967,4 +968,281 @@ public void 
knnQueryAsRerank_shouldAddSimilarityFunctionScore() {
         "//result/doc[3]/str[@name='id'][.='3']",
         "//result/doc[4]/str[@name='id'][.='9']");
   }
+
+  @Test
+  public void 
testKnnFloatWithoutExplicitlyEarlyTermination_returnsKnnFloatVectorQuery() {
+    // It verifies that when no early termination parameters are provided,
+    // the default behavior is applied (early termination is disabled), and no 
special logic is
+    // triggered.
+    String vectorToSearch = "[1.0, 2.0, 3.0, 4.0]";
+
+    assertQ(
+        req(
+            CommonParams.Q,
+            "{!knn f=vector topK=5}" + vectorToSearch,
+            "fl",
+            "id",
+            "debugQuery",
+            "true"),
+        "//result[@numFound='5']",
+        
"//str[@name='parsedquery'][.='KnnFloatVectorQuery(KnnFloatVectorQuery:vector[1.0,...][5])']");
+  }
+
+  @Test
+  public void testKnnFloatWithoutEarlyTermination_returnsKnnFloatVectorQuery() 
{
+    // It verifies that when early termination is explicitly set to false, no 
special logic is
+    // triggered.
+    String vectorToSearch = "[1.0, 2.0, 3.0, 4.0]";
+
+    assertQ(
+        req(
+            CommonParams.Q,
+            "{!knn f=vector topK=5 earlyTermination=false}" + vectorToSearch,
+            "fl",
+            "id",
+            "debugQuery",
+            "true"),
+        "//result[@numFound='5']",
+        
"//str[@name='parsedquery'][.='KnnFloatVectorQuery(KnnFloatVectorQuery:vector[1.0,...][5])']");
+  }
+
+  @Test
+  public void 
testKnnFloatWithEarlyTerminationDefaultParams_returnsPatienceKnnVectorQuery() {
+    // It verifies that when early termination is explicitly set to true but 
no other parameters are
+    // provided, the PatienceKnnVectorQuery is executed using the default 
values for
+    // saturationThreshold and
+    // patience.
+    String vectorToSearch = "[1.0, 2.0, 3.0, 4.0]";
+
+    // IMPORTANT: The default values for `saturationThreshold` and `patience` 
are hardcoded here
+    // because they are currently private in Lucene's PatienceKnnVectorQuery 
implementation.
+    // If Lucene changes these defaults in a future release, this test will 
break and must be
+    // updated accordingly.
+    double defaultSaturationThreshold = 0.995;
+    int defaultPatience = 7;
+
+    String expectedParsedQuery =
+        String.format(
+            Locale.US,
+            
"PatienceKnnVectorQuery(PatienceKnnVectorQuery{saturationThreshold=%.3f, 
patience=%d, delegate=KnnFloatVectorQuery:vector[1.0,...][10]})",
+            defaultSaturationThreshold,
+            defaultPatience);
+
+    assertQ(
+        req(
+            CommonParams.Q,
+            "{!knn f=vector topK=10 earlyTermination=true}" + vectorToSearch,
+            "fl",
+            "id",
+            "debugQuery",
+            "true"),
+        "//result[@numFound='10']",
+        "//str[@name='parsedquery'][.='" + expectedParsedQuery + "']");
+  }
+
+  @Test
+  public void
+      
testKnnFloatWithEarlyTerminationCustomParams_returnsPatienceKnnVectorQueryCustomParams()
 {
+    // It verifies that when early termination is explicitly set to true and 
both
+    // saturationThreshold and patience
+    // parameters are provided, the PatienceKnnVectorQuery is executed using 
the specified custom
+    // values.
+    String vectorToSearch = "[1.0, 2.0 ,3.0, 4.0]";
+
+    double customSaturationThreshold = 0.989;
+    int customPatience = 10;
+
+    String query =
+        String.format(
+            Locale.US,
+            "{!knn f=vector topK=10 earlyTermination=true 
saturationThreshold=%.3f patience=%d}"
+                + vectorToSearch,
+            customSaturationThreshold,
+            customPatience);
+
+    String expectedParsedQuery =
+        String.format(
+            Locale.US,
+            
"PatienceKnnVectorQuery(PatienceKnnVectorQuery{saturationThreshold=%.3f, 
patience=%d, delegate=KnnFloatVectorQuery:vector[1.0,...][10]})",
+            customSaturationThreshold,
+            customPatience);
+
+    assertQ(
+        req(CommonParams.Q, query, "fl", "id", "debugQuery", "true"),
+        "//result[@numFound='10']",
+        "//str[@name='parsedquery'][.='" + expectedParsedQuery + "']");
+  }
+
+  @Test
+  public void
+      
testKnnByteWithEarlyTerminationCustomParams_returnsPatienceKnnVectorQueryCustomParams()
 {
+    // It verifies that when early termination is explicitly set to true and 
both
+    // saturationThreshold and patience
+    // parameters are provided, the PatienceKnnVectorQuery is executed using 
the specified custom
+    // values.
+    String vectorToSearch = "[2, 2, 1, 3]";
+
+    double customSaturationThreshold = 0.989;
+    int customPatience = 10;
+
+    String query =
+        String.format(
+            Locale.US,
+            "{!knn f=vector_byte_encoding topK=5 earlyTermination=true 
saturationThreshold=%.3f patience=%d}"
+                + vectorToSearch,
+            customSaturationThreshold,
+            customPatience);
+
+    String expectedParsedQuery =
+        String.format(
+            Locale.US,
+            
"PatienceKnnVectorQuery(PatienceKnnVectorQuery{saturationThreshold=%.3f, 
patience=%d, delegate=KnnByteVectorQuery:vector_byte_encoding[2,...][5]})",
+            customSaturationThreshold,
+            customPatience);
+
+    assertQ(
+        req(CommonParams.Q, query, "fl", "id", "debugQuery", "true"),
+        "//result[@numFound='5']",
+        "//str[@name='parsedquery'][.='" + expectedParsedQuery + "']");
+  }
+
+  @Test
+  public void
+      
testKnnFloatWithEarlyTerminationOnlyCustomParams_returnsPatienceKnnVectorQueryCustomParams()
 {
+    // It verifies that when early termination is NOT explicitly passed but 
both saturationThreshold
+    // and patience
+    // parameters are provided, the PatienceKnnVectorQuery is executed using 
the specified custom
+    // values.
+    String vectorToSearch = "[1.0, 2.0 ,3.0, 4.0]";
+
+    double customSaturationThreshold = 0.989;
+    int customPatience = 10;
+
+    String query =
+        String.format(
+            Locale.US,
+            "{!knn f=vector topK=10 saturationThreshold=%.3f patience=%d}" + 
vectorToSearch,
+            customSaturationThreshold,
+            customPatience);
+
+    String expectedParsedQuery =
+        String.format(
+            Locale.US,
+            
"PatienceKnnVectorQuery(PatienceKnnVectorQuery{saturationThreshold=%.3f, 
patience=%d, delegate=KnnFloatVectorQuery:vector[1.0,...][10]})",
+            customSaturationThreshold,
+            customPatience);
+
+    assertQ(
+        req(CommonParams.Q, query, "fl", "id", "debugQuery", "true"),
+        "//result[@numFound='10']",
+        "//str[@name='parsedquery'][.='" + expectedParsedQuery + "']");
+  }
+
+  @Test
+  public void outOfRangeSaturationThresholdValue_shouldThrowException() {
+    // It verifies that when an invalid saturationThreshold value (<= 0.0 or 
>= 1.0)
+    // is provided in the query, Solr throws a BAD_REQUEST exception with the 
expected message.
+    String vectorToSearch = "[1.0, 2.0, 3.0, 4.0]";
+
+    double saturationThreshold = 2.0; // out of range
+    int patience = 10;
+
+    assertQEx(
+        "Invalid saturationThreshold value: must be a double between 0.0 and 
1.0 (exclusive), got 2.0",
+        req(
+            CommonParams.Q,
+            String.format(
+                Locale.ROOT,
+                "{!knn f=vector topK=10 saturationThreshold=%.3f 
patience=%d}%s",
+                saturationThreshold,
+                patience,
+                vectorToSearch)),
+        SolrException.ErrorCode.BAD_REQUEST);
+  }
+
+  @Test
+  public void incorrectSaturationThresholdValue_shouldThrowException() {
+    // It verifies that when an invalid saturationThreshold value, e.g. 95%, 
is provided in the
+    // query, Solr throws a BAD_REQUEST exception with the expected message.
+    String vectorToSearch = "[1.0, 2.0, 3.0, 4.0]";
+
+    String saturationThreshold = "95%";
+    int patience = 10;
+
+    assertQEx(
+        "Invalid saturationThreshold value: not a valid double, got 95%",
+        req(
+            CommonParams.Q,
+            String.format(
+                Locale.ROOT,
+                "{!knn f=vector topK=10 saturationThreshold=%s patience=%d}%s",
+                saturationThreshold,
+                patience,
+                vectorToSearch)),
+        SolrException.ErrorCode.BAD_REQUEST);
+  }
+
+  @Test
+  public void outOfRangePatienceValue_shouldThrowException() {
+    // It verifies that when an invalid Patience value (< 7)
+    // is provided in the query, Solr throws a BAD_REQUEST exception with the 
expected message.
+    String vectorToSearch = "[1.0, 2.0, 3.0, 4.0]";
+
+    double saturationThreshold = 0.995;
+    int patience = 2; // out of range
+
+    assertQEx(
+        "Invalid patience value: must be an integer >= 7, got 2",
+        req(
+            CommonParams.Q,
+            String.format(
+                Locale.ROOT,
+                "{!knn f=vector topK=10 saturationThreshold=%.3f 
patience=%d}%s",
+                saturationThreshold,
+                patience,
+                vectorToSearch)),
+        SolrException.ErrorCode.BAD_REQUEST);
+  }
+
+  @Test
+  public void incorrectPatienceValue_shouldThrowException() {

Review Comment:
   check it



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to