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
+ }
}