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

janhoy pushed a commit to branch branch_9x
in repository https://gitbox.apache.org/repos/asf/solr.git


The following commit(s) were added to refs/heads/branch_9x by this push:
     new 1d003f4c5ae SOLR-18006 Fix reverse distance sorting on 
LatLonPointSpatialField (#3923)
1d003f4c5ae is described below

commit 1d003f4c5ae7924f34cb91bc905cd742940cf159
Author: Jan Høydahl <[email protected]>
AuthorDate: Fri Dec 5 14:07:36 2025 +0100

    SOLR-18006 Fix reverse distance sorting on LatLonPointSpatialField (#3923)
    
    Co-authored-by: David Smiley <[email protected]>
    (cherry picked from commit 153e4e47a358a813cf4db77b88c704436368fd92)
---
 ...rse dist sorting on LatLonPointSpatialField.yml | 12 ++++++
 .../solr/schema/LatLonPointSpatialField.java       | 48 +++++++++++++++++++---
 .../solr/collection1/conf/solrconfig-spatial.xml   |  7 ++++
 .../org/apache/solr/search/TestSolr4Spatial2.java  | 41 ++++++++++++++++++
 4 files changed, 103 insertions(+), 5 deletions(-)

diff --git a/changelog/unreleased/SOLR-18006-Fix reverse dist sorting on 
LatLonPointSpatialField.yml b/changelog/unreleased/SOLR-18006-Fix reverse dist 
sorting on LatLonPointSpatialField.yml
new file mode 100644
index 00000000000..d3306164c38
--- /dev/null
+++ b/changelog/unreleased/SOLR-18006-Fix reverse dist sorting on 
LatLonPointSpatialField.yml   
@@ -0,0 +1,12 @@
+# See https://github.com/apache/solr/blob/main/dev-docs/changelog.adoc
+title: Fix reverse distance sorting on LatLonPointSpatialField when combined 
with filter cache
+type: fixed # added, changed, fixed, deprecated, removed, dependency_update, 
security, other
+authors:
+  - name: Jan Høydahl
+    url: https://home.apache.org/phonebook.html?uid=janhoy
+  - name: Umut Saribiyik
+    nick: umut-sar
+  - name: David Smiley
+links:
+  - name: SOLR-18006
+    url: https://issues.apache.org/jira/browse/SOLR-18006
diff --git 
a/solr/core/src/java/org/apache/solr/schema/LatLonPointSpatialField.java 
b/solr/core/src/java/org/apache/solr/schema/LatLonPointSpatialField.java
index 5010ba27075..7a6f013e87a 100644
--- a/solr/core/src/java/org/apache/solr/schema/LatLonPointSpatialField.java
+++ b/solr/core/src/java/org/apache/solr/schema/LatLonPointSpatialField.java
@@ -34,6 +34,7 @@ import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.search.DoubleValues;
 import org.apache.lucene.search.DoubleValuesSource;
 import org.apache.lucene.search.FieldComparator;
+import org.apache.lucene.search.FieldComparatorSource;
 import org.apache.lucene.search.IndexOrDocValuesQuery;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.LeafFieldComparator;
@@ -53,11 +54,10 @@ import org.locationtech.spatial4j.shape.Rectangle;
 import org.locationtech.spatial4j.shape.Shape;
 
 /**
- * A spatial implementation based on Lucene's {@code LatLonPoint} and {@code 
LatLonDocValuesField}.
+ * A spatial implementation based on Lucene's {@link LatLonPoint} and {@link 
LatLonDocValuesField}.
  * The first is based on Lucene's "Points" API, which is a BKD Index. This 
field type is strictly
  * limited to coordinates in lat/lon decimal degrees. The accuracy is about a 
centimeter (1.042cm).
  */
-// TODO once LLP & LLDVF are out of Lucene Sandbox, we should be able to 
javadoc reference them.
 public class LatLonPointSpatialField
     extends 
AbstractSpatialFieldType<LatLonPointSpatialField.LatLonPointSpatialStrategy>
     implements SchemaAware {
@@ -319,11 +319,49 @@ public class LatLonPointSpatialField
 
       @Override
       public SortField getSortField(boolean reverse) {
+        SortField distanceSortAsc =
+            LatLonDocValuesField.newDistanceSort(fieldName, queryPoint.getY(), 
queryPoint.getX());
+        // If only we could call sortField.setReverse(), we would.  So instead 
we create a SortField
+        // using a reverse boolean constructor.  The FieldComparatorSource is 
always ascending.
         if (reverse) {
-          return super.getSortField(true); // will use an impl that calls 
getValues
+          return new SortField(
+              distanceSortAsc.getField(),
+              new DistanceFieldComparatorSource(distanceSortAsc, queryPoint),
+              true);
+        }
+        return distanceSortAsc;
+      }
+
+      // to implement equals & hashCode on info that isn't in SortField -- 
just the queryPoint
+      private static class DistanceFieldComparatorSource extends 
FieldComparatorSource {
+        private final SortField distanceSortAsc;
+        private final Point queryPoint;
+
+        DistanceFieldComparatorSource(SortField distanceSortAsc, Point 
queryPoint) {
+          this.distanceSortAsc = distanceSortAsc;
+          this.queryPoint = queryPoint;
+        }
+
+        @Override
+        public FieldComparator<?> newComparator(
+            String fieldname,
+            int numHits,
+            Pruning pruning,
+            boolean reversed) { // 'reversed' is an FYI.  It's implemented by 
the caller chain.
+          return distanceSortAsc.getComparator(numHits, pruning);
+        }
+
+        @Override
+        public boolean equals(Object o) {
+          if (o == null || getClass() != o.getClass()) return false;
+          var that = (DistanceFieldComparatorSource) o;
+          return Objects.equals(queryPoint, that.queryPoint);
+        }
+
+        @Override
+        public int hashCode() {
+          return Objects.hashCode(queryPoint);
         }
-        return LatLonDocValuesField.newDistanceSort(
-            fieldName, queryPoint.getY(), queryPoint.getX());
       }
     }
   }
diff --git 
a/solr/core/src/test-files/solr/collection1/conf/solrconfig-spatial.xml 
b/solr/core/src/test-files/solr/collection1/conf/solrconfig-spatial.xml
index 889d1c24968..a3d09a034a5 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-spatial.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-spatial.xml
@@ -38,5 +38,12 @@
            initialSize="0"
            autowarmCount="100%"
            regenerator="solr.NoOpRegenerator"/>
+
+    <!-- Needed to trigger SOLR-18006 -->
+    <filterCache
+      size="512"
+      initialSize="512"
+      autowarmCount="2"
+      async="${solr.filterCache.async:false}"/>
   </query>
 </config>
diff --git a/solr/core/src/test/org/apache/solr/search/TestSolr4Spatial2.java 
b/solr/core/src/test/org/apache/solr/search/TestSolr4Spatial2.java
index 4456934937c..fc65dcd4531 100644
--- a/solr/core/src/test/org/apache/solr/search/TestSolr4Spatial2.java
+++ b/solr/core/src/test/org/apache/solr/search/TestSolr4Spatial2.java
@@ -554,4 +554,45 @@ public class TestSolr4Spatial2 extends SolrTestCaseJ4 {
             "sort", "min(geodist(),geodist(55.4721936,-2.24703,llp)) asc"),
         "/response/docs/[0]/id=='2'");
   }
+
+  @Test
+  public void testSOLR18006_GeodistDescWithFilterQuery() throws Exception {
+    // SOLR-18006: geodist() desc sorting causes NPE when spatial query is in 
filter query
+    // Reproduction from JIRA issue with exact coordinates and parameters
+    String fieldName = "llp_km";
+
+    // Index sample documents from JIRA issue
+    assertU(adoc("id", "pt-001", fieldName, "48.106651,11.628476"));
+    assertU(adoc("id", "pt-002", fieldName, "48.113089,11.622016"));
+    assertU(adoc("id", "pt-003", fieldName, "48.137154,11.576124"));
+    assertU(adoc("id", "pt-004", fieldName, "48.135125,11.581981"));
+    assertU(adoc("id", "pt-005", fieldName, "48.121,11.612"));
+    assertU(adoc("id", "pt-006", fieldName, "48.09,11.64"));
+    assertU(commit());
+
+    // Test descending sort with filter query - exact query from JIRA that 
triggers NPE
+    // Expected order by distance DESC from 
pt=48.11308880280511,11.622015740056845:
+    // pt-003 (48.137154,11.576124) - farthest
+    // pt-004 (48.135125,11.581981)
+    // pt-006 (48.09,11.64)
+    // pt-005 (48.121,11.612)
+    // pt-001 (48.106651,11.628476)
+    // pt-002 (48.113089,11.622016) - closest
+    assertJQ(
+        req(
+            "q", "*:*",
+            "fq", "{!geofilt}",
+            "sfield", fieldName,
+            "pt", "48.11308880280511,11.622015740056845",
+            "d", "10",
+            "fl", "id",
+            "sort", "geodist() desc"),
+        "/response/numFound==6",
+        "/response/docs/[0]/id=='pt-003'", // farthest
+        "/response/docs/[1]/id=='pt-004'",
+        "/response/docs/[2]/id=='pt-006'",
+        "/response/docs/[3]/id=='pt-005'",
+        "/response/docs/[4]/id=='pt-001'",
+        "/response/docs/[5]/id=='pt-002'"); // closest
+  }
 }

Reply via email to