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

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

commit 9303a26b7ec093c3260c2c9ebac0dca24f7790dd
Author: Ishan Chattopadhyaya <[email protected]>
AuthorDate: Thu Aug 7 20:30:35 2025 +0530

    SOLR-17631: Tidy, logging fixes, note on using lucene-sandbox
---
 gradle/libs.versions.toml                          |   3 +-
 solr/core/build.gradle                             |   1 +
 .../java/org/apache/solr/query/SolrRangeQuery.java |  14 ++-
 .../org/apache/solr/request/DocValuesFacets.java   |   4 +-
 .../solr/search/ComplexPhraseQParserPlugin.java    |  14 +--
 .../solr/search/ExpressionValueSourceParser.java   | 123 ++++++++++-----------
 .../src/java/org/apache/solr/search/Grouping.java  |  17 ++-
 .../solr/util/SolrDefaultScorerSupplier.java       |  16 +++
 .../PathHierarchyTokenizerFactoryTest.java         |   8 +-
 .../solr/uninverting/TestFieldCacheSortRandom.java |  15 ++-
 .../java/org/apache/solr/ltr/LTRScoringQuery.java  |   5 +-
 .../pages/major-changes-in-solr-10.adoc            |   2 +
 12 files changed, 127 insertions(+), 95 deletions(-)

diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 342f6f29165..f05420bd748 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -278,6 +278,7 @@ apache-lucene-join = { module = 
"org.apache.lucene:lucene-join", version.ref = "
 apache-lucene-misc = { module = "org.apache.lucene:lucene-misc", version.ref = 
"apache-lucene" }
 apache-lucene-queries = { module = "org.apache.lucene:lucene-queries", 
version.ref = "apache-lucene" }
 apache-lucene-queryparser = { module = "org.apache.lucene:lucene-queryparser", 
version.ref = "apache-lucene" }
+apache-lucene-sandbox = { module = "org.apache.lucene:lucene-sandbox", 
version.ref = "apache-lucene" }
 apache-lucene-spatialextras = { module = 
"org.apache.lucene:lucene-spatial-extras", version.ref = "apache-lucene" }
 apache-lucene-suggest = { module = "org.apache.lucene:lucene-suggest", 
version.ref = "apache-lucene" }
 apache-lucene-testframework = { module = 
"org.apache.lucene:lucene-test-framework", version.ref = "apache-lucene" }
@@ -436,9 +437,9 @@ kotlinx-coroutines-test = { module = 
"org.jetbrains.kotlinx:kotlinx-coroutines-t
 kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", 
version.ref = "kotlinx-datetime" }
 kotlinx-serialization-core = { module = 
"org.jetbrains.kotlinx:kotlinx-serialization-core", version.ref = 
"kotlinx-serialization" }
 kotlinx-serialization-json = { module = 
"org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = 
"kotlinx-serialization" }
+ktor-client-auth = { module = "io.ktor:ktor-client-auth", version.ref = "ktor" 
}
 ktor-client-cio = { module = "io.ktor:ktor-client-cio", version.ref = "ktor" }
 ktor-client-contentNegotiation = { module = 
"io.ktor:ktor-client-content-negotiation", version.ref = "ktor" }
-ktor-client-auth = { module = "io.ktor:ktor-client-auth", version.ref = "ktor" 
}
 ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" 
}
 ktor-client-mock = { module = "io.ktor:ktor-client-mock", version.ref = "ktor" 
}
 ktor-client-serialization-json = { module = 
"io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktor" }
diff --git a/solr/core/build.gradle b/solr/core/build.gradle
index f6e3c3114a5..74a2b9e64d7 100644
--- a/solr/core/build.gradle
+++ b/solr/core/build.gradle
@@ -91,6 +91,7 @@ dependencies {
   implementation libs.apache.lucene.join
   implementation libs.apache.lucene.misc
   implementation libs.apache.lucene.queryparser
+  implementation libs.apache.lucene.sandbox
   implementation libs.apache.lucene.spatialextras
   implementation libs.apache.lucene.suggest
 
diff --git a/solr/core/src/java/org/apache/solr/query/SolrRangeQuery.java 
b/solr/core/src/java/org/apache/solr/query/SolrRangeQuery.java
index 60236135eaf..91bc00fc0dc 100644
--- a/solr/core/src/java/org/apache/solr/query/SolrRangeQuery.java
+++ b/solr/core/src/java/org/apache/solr/query/SolrRangeQuery.java
@@ -540,11 +540,15 @@ public final class SolrRangeQuery extends 
ExtendedQueryBase implements DocSetPro
 
     public Scorer scorerInternal(LeafReaderContext context) throws IOException 
{
       final SegState weightOrBitSet = getSegState(context);
-      log.info("Query: " + getQuery());
-      log.info("weight: " + weightOrBitSet.weight);
-      if (weightOrBitSet.weight != null)
-        log.info("weight's scorer: " + weightOrBitSet.weight.scorer(context));
-      log.info("set: " + weightOrBitSet.set);
+      if (log.isDebugEnabled()) {
+        log.debug("Query: {}", getQuery());
+        log.debug("weight: {}", weightOrBitSet.weight);
+        if (weightOrBitSet.weight != null) {
+          Scorer scorer = weightOrBitSet.weight.scorer(context);
+          log.debug("weight's scorer: {}", scorer);
+        }
+        log.debug("set: {}", weightOrBitSet.set);
+      }
       if (weightOrBitSet.weight != null) {
         Scorer ret = weightOrBitSet.weight.scorer(context);
         return ret;
diff --git a/solr/core/src/java/org/apache/solr/request/DocValuesFacets.java 
b/solr/core/src/java/org/apache/solr/request/DocValuesFacets.java
index 5b66da544fe..c37d2ad2ea9 100644
--- a/solr/core/src/java/org/apache/solr/request/DocValuesFacets.java
+++ b/solr/core/src/java/org/apache/solr/request/DocValuesFacets.java
@@ -430,7 +430,7 @@ public class DocValuesFacets {
         for (int o = 0; o < si.docValueCount(); o++) {
           long ord = si.nextOrd();
           if (ord == -1) // NO_MORE_ORDS
-            break;
+          break;
           int term = (int) ord;
           if (map != null) {
             term = (int) ordMap.get(term);
@@ -465,7 +465,7 @@ public class DocValuesFacets {
         for (int o = 0; o < si.docValueCount(); o++) {
           long ord = si.nextOrd();
           if (ord == -1) // NO_MORE_ORDS
-            break;
+          break;
           int term = (int) ord;
           segCounts[1 + term]++;
         }
diff --git 
a/solr/core/src/java/org/apache/solr/search/ComplexPhraseQParserPlugin.java 
b/solr/core/src/java/org/apache/solr/search/ComplexPhraseQParserPlugin.java
index fbb32a951bf..2292b175121 100644
--- a/solr/core/src/java/org/apache/solr/search/ComplexPhraseQParserPlugin.java
+++ b/solr/core/src/java/org/apache/solr/search/ComplexPhraseQParserPlugin.java
@@ -78,13 +78,13 @@ public class ComplexPhraseQParserPlugin extends 
QParserPlugin {
       protected org.apache.lucene.search.Query getWildcardQuery(String field, 
String termStr)
           throws SyntaxError {
         Query q = super.getWildcardQuery(field, termStr);
-        
+
         // For complex phrase queries, we need to ensure wildcard queries and 
automaton queries
         // use SCORING_BOOLEAN_REWRITE to avoid the new constant score 
wrappers in Lucene 10
         if (q instanceof WildcardQuery) {
           WildcardQuery wq = (WildcardQuery) q;
           return new WildcardQuery(
-              wq.getTerm(), 
+              wq.getTerm(),
               Operations.DEFAULT_DETERMINIZE_WORK_LIMIT,
               MultiTermQuery.SCORING_BOOLEAN_REWRITE);
         } else if (q instanceof AutomatonQuery) {
@@ -93,12 +93,12 @@ public class ComplexPhraseQParserPlugin extends 
QParserPlugin {
           // We can't access the term directly, but for reversed wildcard 
queries,
           // we can use a placeholder term since the automaton contains the 
actual matching logic
           return new AutomatonQuery(
-              new Term(field, ""), 
+              new Term(field, ""),
               aq.getAutomaton(),
               aq.isAutomatonBinary(),
               MultiTermQuery.SCORING_BOOLEAN_REWRITE);
         }
-        
+
         return q;
       }
 
@@ -155,17 +155,17 @@ public class ComplexPhraseQParserPlugin extends 
QParserPlugin {
                 // Get the wildcard query from the reverse-aware parser
                 org.apache.lucene.search.Query wildcardQuery =
                     reverseAwareParser.getWildcardQuery(t.field(), t.text());
-                
+
                 // In Lucene 10, we need to ensure wildcard queries use 
SCORING_BOOLEAN_REWRITE
                 // for complex phrase queries to work properly
                 if (wildcardQuery instanceof WildcardQuery) {
                   WildcardQuery wq = (WildcardQuery) wildcardQuery;
                   return new WildcardQuery(
-                      wq.getTerm(), 
+                      wq.getTerm(),
                       Operations.DEFAULT_DETERMINIZE_WORK_LIMIT,
                       MultiTermQuery.SCORING_BOOLEAN_REWRITE);
                 }
-                
+
                 return wildcardQuery;
               } catch (SyntaxError e) {
                 throw new RuntimeException(e);
diff --git 
a/solr/core/src/java/org/apache/solr/search/ExpressionValueSourceParser.java 
b/solr/core/src/java/org/apache/solr/search/ExpressionValueSourceParser.java
index e62f5a19227..67b2ebe75e2 100644
--- a/solr/core/src/java/org/apache/solr/search/ExpressionValueSourceParser.java
+++ b/solr/core/src/java/org/apache/solr/search/ExpressionValueSourceParser.java
@@ -37,8 +37,8 @@ import org.apache.lucene.search.DoubleValuesSource;
 import org.apache.lucene.search.FieldComparator;
 import org.apache.lucene.search.FieldComparatorSource;
 import org.apache.lucene.search.IndexSearcher;
-import org.apache.lucene.search.Scorable;
 import org.apache.lucene.search.Pruning;
+import org.apache.lucene.search.Scorable;
 import org.apache.lucene.search.SimpleFieldComparator;
 import org.apache.lucene.search.SortField;
 import org.apache.solr.common.SolrException;
@@ -113,10 +113,10 @@ public class ExpressionValueSourceParser extends 
ValueSourceParser {
     IndexSchema schema = fp.getReq().getSchema();
     SolrBindings b = new SolrBindings(scoreKey, schema, positionalArgs);
     DoubleValuesSource doubleValuesSource = 
expression.getDoubleValuesSource(b);
-    
+
     // Check if this expression needs scores by examining if it contains score 
references
     boolean needsScores = doubleValuesSource.needsScores();
-    
+
     if (needsScores) {
       // For score-dependent expressions, create a custom ValueSource that can
       // properly integrate with Lucene's sorting scorer mechanism
@@ -128,33 +128,34 @@ public class ExpressionValueSourceParser extends 
ValueSourceParser {
   }
 
   /**
-   * A custom ValueSource that properly handles score-dependent expressions by 
implementing
-   * the setScorer() pattern required by Lucene's sorting mechanism.
-   * 
-   * This solves the fundamental issue where 
ValueSourceComparator.doSetNextReader() 
-   * is called during sorting setup when no scorer is available, but 
expressions need
-   * scores to work correctly.
+   * A custom ValueSource that properly handles score-dependent expressions by 
implementing the
+   * setScorer() pattern required by Lucene's sorting mechanism.
+   *
+   * <p>This solves the fundamental issue where 
ValueSourceComparator.doSetNextReader() is called
+   * during sorting setup when no scorer is available, but expressions need 
scores to work
+   * correctly.
    */
   private static class ScoreAwareValueSource extends ValueSource {
     private final DoubleValuesSource doubleValuesSource;
-    
+
     public ScoreAwareValueSource(DoubleValuesSource doubleValuesSource) {
       this.doubleValuesSource = doubleValuesSource;
     }
-    
+
     @Override
-    public FunctionValues getValues(java.util.Map<Object, Object> context, 
LeafReaderContext readerContext) throws IOException {
+    public FunctionValues getValues(
+        java.util.Map<Object, Object> context, LeafReaderContext 
readerContext) throws IOException {
       // Get scorer from context (may be null during setup)
       Scorable scorer = (Scorable) context.get("scorer");
       DoubleValues scores = scorer == null ? null : 
DoubleValuesSource.fromScorer(scorer);
-      
+
       // Get the DoubleValues from our source
       DoubleValues doubleValues = doubleValuesSource.getValues(readerContext, 
scores);
-      
+
       // Return a ScoreAwareFunctionValues that can be updated when scorer 
becomes available
       return new ScoreAwareFunctionValues(doubleValuesSource, readerContext, 
doubleValues);
     }
-    
+
     @Override
     public boolean equals(Object o) {
       if (this == o) return true;
@@ -162,68 +163,67 @@ public class ExpressionValueSourceParser extends 
ValueSourceParser {
       ScoreAwareValueSource that = (ScoreAwareValueSource) o;
       return doubleValuesSource.equals(that.doubleValuesSource);
     }
-    
+
     @Override
     public int hashCode() {
       return doubleValuesSource.hashCode();
     }
-    
+
     @Override
     public String description() {
       return "ScoreAware(" + doubleValuesSource.toString() + ")";
     }
-    
+
     @Override
     public SortField getSortField(boolean reverse) {
       // Create a SortField that uses our custom comparator
       return new SortField(description(), new ScoreAwareComparatorSource(), 
reverse);
     }
-    
-    /**
-     * Custom FieldComparatorSource that implements the setScorer() pattern
-     */
+
+    /** Custom FieldComparatorSource that implements the setScorer() pattern */
     private class ScoreAwareComparatorSource extends FieldComparatorSource {
       @Override
-      public FieldComparator<?> newComparator(String fieldname, int numHits, 
Pruning pruning, boolean reversed) {
+      public FieldComparator<?> newComparator(
+          String fieldname, int numHits, Pruning pruning, boolean reversed) {
         return new ScoreAwareComparator(numHits);
       }
     }
-    
+
     /**
-     * Custom FieldComparator that properly implements setScorer() to ensure
-     * scores are available during sorting
+     * Custom FieldComparator that properly implements setScorer() to ensure 
scores are available
+     * during sorting
      */
     private class ScoreAwareComparator extends SimpleFieldComparator<Double> {
       private final double[] values;
       private ScoreAwareFunctionValues functionValues;
       private double bottom;
       private double topValue;
-      
+
       public ScoreAwareComparator(int numHits) {
         this.values = new double[numHits];
       }
-      
+
       @Override
       public int compare(int slot1, int slot2) {
         return Double.compare(values[slot1], values[slot2]);
       }
-      
+
       @Override
       public int compareBottom(int doc) throws IOException {
         return Double.compare(bottom, functionValues.doubleVal(doc));
       }
-      
+
       @Override
       public void copy(int slot, int doc) throws IOException {
         values[slot] = functionValues.doubleVal(doc);
       }
-      
+
       @Override
       public void doSetNextReader(LeafReaderContext context) throws 
IOException {
         // Create initial FunctionValues (may have null scorer)
         functionValues = (ScoreAwareFunctionValues) getValues(new 
java.util.HashMap<>(), context);
       }
-      
+
       @Override
       public void setScorer(Scorable scorer) throws IOException {
         // This is the key method that was missing in ValueSourceComparator!
@@ -232,49 +232,48 @@ public class ExpressionValueSourceParser extends 
ValueSourceParser {
           functionValues.updateScorer(scorer);
         }
       }
-      
+
       @Override
       public void setBottom(int bottom) {
         this.bottom = values[bottom];
       }
-      
+
       @Override
       public void setTopValue(Double value) {
         this.topValue = value;
       }
-      
+
       @Override
       public Double value(int slot) {
         return values[slot];
       }
-      
+
       @Override
       public int compareTop(int doc) throws IOException {
         return Double.compare(topValue, functionValues.doubleVal(doc));
       }
     }
   }
-  
-  /**
-   * FunctionValues that can be updated with a scorer when it becomes available
-   */
+
+  /** FunctionValues that can be updated with a scorer when it becomes 
available */
   private static class ScoreAwareFunctionValues extends FunctionValues {
     private final DoubleValuesSource source;
     private final LeafReaderContext context;
     private DoubleValues doubleValues;
-    
-    public ScoreAwareFunctionValues(DoubleValuesSource source, 
LeafReaderContext context, DoubleValues initialDoubleValues) {
+
+    public ScoreAwareFunctionValues(
+        DoubleValuesSource source, LeafReaderContext context, DoubleValues 
initialDoubleValues) {
       this.source = source;
       this.context = context;
       this.doubleValues = initialDoubleValues;
     }
-    
+
     public void updateScorer(Scorable scorer) throws IOException {
       // When scorer becomes available, recreate DoubleValues with actual 
scores
       DoubleValues scores = DoubleValuesSource.fromScorer(scorer);
       this.doubleValues = source.getValues(context, scores);
     }
-    
+
     @Override
     public double doubleVal(int doc) throws IOException {
       if (!doubleValues.advanceExact(doc)) {
@@ -282,27 +281,27 @@ public class ExpressionValueSourceParser extends 
ValueSourceParser {
       }
       return doubleValues.doubleValue();
     }
-    
+
     @Override
     public float floatVal(int doc) throws IOException {
       return (float) doubleVal(doc);
     }
-    
+
     @Override
     public int intVal(int doc) throws IOException {
       return (int) doubleVal(doc);
     }
-    
+
     @Override
     public long longVal(int doc) throws IOException {
       return (long) doubleVal(doc);
     }
-    
+
     @Override
     public String strVal(int doc) throws IOException {
       return Float.toString(floatVal(doc));
     }
-    
+
     @Override
     public String toString(int doc) throws IOException {
       return Double.toString(doubleVal(doc));
@@ -364,17 +363,17 @@ public class ExpressionValueSourceParser extends 
ValueSourceParser {
 
   /**
    * Custom DoubleValuesSource for scores that handles the Lucene 10 assertion 
gracefully.
-   * 
-   * The core issue: Lucene 10's DoubleValuesSource.SCORES has an assertion 
that scores != null,
+   *
+   * <p>The core issue: Lucene 10's DoubleValuesSource.SCORES has an assertion 
that scores != null,
    * but during ValueSource sorting setup, scores can be null. This creates a 
timing mismatch
    * between when the expression is evaluated and when the scorer is available.
-   * 
-   * This implementation bypasses the assertion and provides reasonable 
fallback behavior
-   * when scores are not available, while delegating to the original 
implementation when
-   * scores are available.
+   *
+   * <p>This implementation bypasses the assertion and provides reasonable 
fallback behavior when
+   * scores are not available, while delegating to the original implementation 
when scores are
+   * available.
    */
   private static class ScoreDoubleValuesSource extends DoubleValuesSource {
-    
+
     @Override
     public DoubleValues getValues(LeafReaderContext ctx, DoubleValues scores) 
throws IOException {
       // Instead of calling DoubleValuesSource.SCORES.getValues() which has 
the assertion,
@@ -414,16 +413,16 @@ public class ExpressionValueSourceParser extends 
ValueSourceParser {
   }
 
   /**
-   * A DoubleValues implementation that handles score access with a graceful 
fallback
-   * when scores are not available (e.g., during sorting setup).
+   * A DoubleValues implementation that handles score access with a graceful 
fallback when scores
+   * are not available (e.g., during sorting setup).
    */
   private static class ScoreDoubleValues extends DoubleValues {
     private final DoubleValues scores;
-    
+
     public ScoreDoubleValues(DoubleValues scores) {
       this.scores = scores;
     }
-    
+
     @Override
     public double doubleValue() throws IOException {
       if (scores != null) {
@@ -432,7 +431,7 @@ public class ExpressionValueSourceParser extends 
ValueSourceParser {
       } else {
         // When scores are null (during sorting setup or other contexts where
         // no scorer is available), return 0.0 as a fallback.
-        // 
+        //
         // NOTE: This breaks score-based sorting because all documents get the
         // same score (0.0), but it avoids the assertion error and allows the
         // query to complete. The fundamental issue is that the legacy 
ValueSource
@@ -441,7 +440,7 @@ public class ExpressionValueSourceParser extends 
ValueSourceParser {
         return 0.0;
       }
     }
-    
+
     @Override
     public boolean advanceExact(int doc) throws IOException {
       if (scores != null) {
diff --git a/solr/core/src/java/org/apache/solr/search/Grouping.java 
b/solr/core/src/java/org/apache/solr/search/Grouping.java
index 72055ee0f96..24770bebf22 100644
--- a/solr/core/src/java/org/apache/solr/search/Grouping.java
+++ b/solr/core/src/java/org/apache/solr/search/Grouping.java
@@ -30,13 +30,11 @@ import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.search.CachingCollector;
 import org.apache.lucene.search.Collector;
-import org.apache.lucene.search.MatchAllDocsQuery;
 import org.apache.lucene.search.MatchNoDocsQuery;
 import org.apache.lucene.search.MultiCollector;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.ScoreDoc;
 import org.apache.lucene.search.Sort;
-import org.apache.lucene.search.SortField;
 import org.apache.lucene.search.TopDocs;
 import org.apache.lucene.search.TopDocsCollector;
 import org.apache.lucene.search.TopFieldCollector;
@@ -299,7 +297,8 @@ public class Grouping {
 
     SolrIndexSearcher.ProcessedFilter pf = 
searcher.getProcessedFilter(cmd.getFilterList());
 
-    final Query searchQuery = 
QueryUtils.combineQueryAndFilter(QueryUtils.makeQueryable(cmd.getQuery()), 
pf.filter);
+    final Query searchQuery =
+        
QueryUtils.combineQueryAndFilter(QueryUtils.makeQueryable(cmd.getQuery()), 
pf.filter);
     maxDoc = searcher.maxDoc();
 
     needScores = (cmd.getFlags() & SolrIndexSearcher.GET_SCORES) != 0;
@@ -569,7 +568,9 @@ public class Grouping {
     protected void populateScoresIfNecessary() throws IOException {
       if (needScores) {
         for (GroupDocs<?> groups : result.groups) {
-          log.info("Group score is 1: " + groups.maxScore());
+          if (log.isDebugEnabled()) {
+            log.debug("Group score is 1: {}", groups.maxScore());
+          }
           TopFieldCollector.populateScores(groups.scoreDocs(), searcher, 
query);
         }
       }
@@ -612,7 +613,9 @@ public class Grouping {
 
       float score = groups.maxScore();
       maxScore = maxAvoidNaN(score, maxScore);
-      log.info("Here, score is " + score + " and maxScore is " + maxScore);
+      if (log.isDebugEnabled()) {
+        log.debug("Here, score is {} and maxScore is {}", score, maxScore);
+      }
       DocSlice docs =
           new DocSlice(
               off,
@@ -900,7 +903,9 @@ public class Grouping {
         maxScore = topDocs.scoreDocs.length == 0 ? Float.NaN : 
topDocs.scoreDocs[0].score;
       } else if (needScores) {
         // use top-level query to populate the scores
-        log.info("Group score is 2: " + maxScoreCollector.getMaxScore());
+        if (log.isDebugEnabled()) {
+          log.debug("Group score is 2: {}", maxScoreCollector.getMaxScore());
+        }
         TopFieldCollector.populateScores(topDocs.scoreDocs, searcher, 
Grouping.this.query);
         maxScore = maxScoreCollector.getMaxScore();
       } else {
diff --git 
a/solr/core/src/java/org/apache/solr/util/SolrDefaultScorerSupplier.java 
b/solr/core/src/java/org/apache/solr/util/SolrDefaultScorerSupplier.java
index 200761bc4e1..c3923ea6b87 100644
--- a/solr/core/src/java/org/apache/solr/util/SolrDefaultScorerSupplier.java
+++ b/solr/core/src/java/org/apache/solr/util/SolrDefaultScorerSupplier.java
@@ -1,3 +1,19 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package org.apache.solr.util;
 
 import java.io.IOException;
diff --git 
a/solr/core/src/test/org/apache/solr/analysis/PathHierarchyTokenizerFactoryTest.java
 
b/solr/core/src/test/org/apache/solr/analysis/PathHierarchyTokenizerFactoryTest.java
index 68d2b0db0ad..8f368b437ba 100644
--- 
a/solr/core/src/test/org/apache/solr/analysis/PathHierarchyTokenizerFactoryTest.java
+++ 
b/solr/core/src/test/org/apache/solr/analysis/PathHierarchyTokenizerFactoryTest.java
@@ -88,10 +88,12 @@ public class PathHierarchyTokenizerFactoryTest extends 
SolrTestCaseJ4 {
   }
 
   public void testAncestors() {
-    // NOTE: In Lucene 10+, PathHierarchyTokenizer produces sequential tokens 
instead of overlapping tokens.
-    // This changes the behavior of ancestor queries - they now match based on 
sequential token positions
+    // NOTE: In Lucene 10+, PathHierarchyTokenizer produces sequential tokens 
instead of overlapping
+    // tokens.
+    // This changes the behavior of ancestor queries - they now match based on 
sequential token
+    // positions
     // rather than overlapping positions, so ancestor matching behavior has 
changed.
-    
+
     assertQ(
         req("{!field f=cat_ancestor}Books/NonFic/Science"),
         "//*[@numFound='2']",
diff --git 
a/solr/core/src/test/org/apache/solr/uninverting/TestFieldCacheSortRandom.java 
b/solr/core/src/test/org/apache/solr/uninverting/TestFieldCacheSortRandom.java
index 7bb77f7187c..a70bc3418e6 100644
--- 
a/solr/core/src/test/org/apache/solr/uninverting/TestFieldCacheSortRandom.java
+++ 
b/solr/core/src/test/org/apache/solr/uninverting/TestFieldCacheSortRandom.java
@@ -258,20 +258,23 @@ public class TestFieldCacheSortRandom extends 
SolrTestCase {
                   + s.storedFields().document(fd.doc).get("id"));
         }
       }
-      
+
       // For STRING_VAL type (using BinaryDocValues), we cannot manually 
compare the sorted order
-      // because Lucene 10+ changed the internal sorting behavior for 
BinaryDocValues. 
-      // The manual BytesRef.compareTo() used in this test doesn't match the 
actual Lucene sort order.
+      // because Lucene 10+ changed the internal sorting behavior for 
BinaryDocValues.
+      // The manual BytesRef.compareTo() used in this test doesn't match the 
actual Lucene sort
+      // order.
       // Instead, we just validate that the uninverting is working correctly 
by checking that:
       // 1. No exceptions are thrown
       // 2. Returned values are valid BytesRef or null
-      // This ensures doc values uninverting works without assuming specific 
sort implementation details.
+      // This ensures doc values uninverting works without assuming specific 
sort implementation
+      // details.
       if (type == SortField.Type.STRING_VAL) {
         for (int hitIDX = 0; hitIDX < hits.scoreDocs.length; hitIDX++) {
           final FieldDoc fd = (FieldDoc) hits.scoreDocs[hitIDX];
           Object sortValue = fd.fields[0];
-          assertTrue("Sort value should be BytesRef or null", 
-                     sortValue == null || sortValue instanceof BytesRef);
+          assertTrue(
+              "Sort value should be BytesRef or null",
+              sortValue == null || sortValue instanceof BytesRef);
         }
         continue; // Skip the exact comparison for STRING_VAL
       }
diff --git a/solr/modules/ltr/src/java/org/apache/solr/ltr/LTRScoringQuery.java 
b/solr/modules/ltr/src/java/org/apache/solr/ltr/LTRScoringQuery.java
index 0712d6c6e7d..85b33fc3ebd 100644
--- a/solr/modules/ltr/src/java/org/apache/solr/ltr/LTRScoringQuery.java
+++ b/solr/modules/ltr/src/java/org/apache/solr/ltr/LTRScoringQuery.java
@@ -32,7 +32,6 @@ import java.util.concurrent.Semaphore;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.search.DisiPriorityQueue;
 import org.apache.lucene.search.DisiWrapper;
-import org.apache.lucene.search.DisjunctionDISIApproximation;
 import org.apache.lucene.search.DocIdSetIterator;
 import org.apache.lucene.search.Explanation;
 import org.apache.lucene.search.IndexSearcher;
@@ -662,7 +661,7 @@ public class LTRScoringQuery extends Query implements 
Accountable {
               targetDoc = activeDoc;
               return targetDoc;
             }
-            
+
             if (activeDoc == targetDoc) {
               // Advance the underlying disjunction
               DisiWrapper top = subScorers.top();
@@ -690,7 +689,7 @@ public class LTRScoringQuery extends Query implements 
Accountable {
             targetDoc = target;
             return targetDoc;
           }
-          
+
           private int advanceInternal(int target) throws IOException {
             // Advance the underlying disjunction to the target
             DisiWrapper top;
diff --git 
a/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-10.adoc 
b/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-10.adoc
index bbbda70b6c1..2dc4958e8cd 100644
--- 
a/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-10.adoc
+++ 
b/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-10.adoc
@@ -132,6 +132,8 @@ Solr upgraded to Jetty 12.x from 10.x as Jetty 10 and 11 
have reached end-of-lif
 
 Due to Lucene 10 changes (https://github.com/apache/lucene/pull/12875), 
`PathHierarchyTokenizer` now produces sequential tokens (position increment = 
1) instead of overlapping tokens (position increment = 0). This affects 
ancestor queries that relied on overlapping token matching. Users should test 
existing queries and update configurations if needed.
 
+* In Lucene 10, the `OrdinalIterator` class has been moved from the main 
`lucene-facet` module to the `lucene-sandbox` module. This requires Solr core 
to now include a dependency on `lucene-sandbox` to support faceting operations 
that use this class.
+
 *Example configuration change:*
 [source,xml]
 ----

Reply via email to