This is an automated email from the ASF dual-hosted git repository.
houston pushed a commit to branch branch_10x
in repository https://gitbox.apache.org/repos/asf/solr.git
The following commit(s) were added to refs/heads/branch_10x by this push:
new 47fcf231847 SOLR-18019: Optimize existence queries for non-docValued
PointFields (#3930)
47fcf231847 is described below
commit 47fcf231847ec1cd6829aa5b272a12c750cb4c70
Author: Houston Putman <[email protected]>
AuthorDate: Tue Dec 9 11:57:49 2025 -0800
SOLR-18019: Optimize existence queries for non-docValued PointFields (#3930)
(cherry picked from commit 3c7b671595a7700807d1ecfd31a5718022eee99c)
---
.../SOLR-18019-optimize-existence-queries.yml | 10 +++
.../org/apache/solr/schema/DoublePointField.java | 13 ++++
.../org/apache/solr/schema/FloatPointField.java | 13 ++++
.../apache/solr/search/TestSolrQueryParser.java | 75 +++++++++++++++-------
4 files changed, 88 insertions(+), 23 deletions(-)
diff --git a/changelog/unreleased/SOLR-18019-optimize-existence-queries.yml
b/changelog/unreleased/SOLR-18019-optimize-existence-queries.yml
new file mode 100644
index 00000000000..03bd0bdfdf9
--- /dev/null
+++ b/changelog/unreleased/SOLR-18019-optimize-existence-queries.yml
@@ -0,0 +1,10 @@
+# See https://github.com/apache/solr/blob/main/dev-docs/changelog.adoc
+title: Optimize existence queries for non-docValued FloatPointField and
DoublePointField
+type: other # added, changed, fixed, deprecated, removed, dependency_update,
security, other
+authors:
+ - name: Houston Putman
+ nick: HoustonPutman
+ url: https://home.apache.org/phonebook.html?uid=houston
+links:
+ - name: SOLR-18019
+ url: https://issues.apache.org/jira/browse/SOLR-18019
diff --git a/solr/core/src/java/org/apache/solr/schema/DoublePointField.java
b/solr/core/src/java/org/apache/solr/schema/DoublePointField.java
index 430d3ff968d..70cc45bfd5a 100644
--- a/solr/core/src/java/org/apache/solr/schema/DoublePointField.java
+++ b/solr/core/src/java/org/apache/solr/schema/DoublePointField.java
@@ -178,4 +178,17 @@ public class DoublePointField extends PointField
implements DoubleValueFieldType
protected StoredField getStoredField(SchemaField sf, Object value) {
return new StoredField(sf.getName(), (Double) this.toNativeType(value));
}
+
+ /**
+ * Override the default existence behavior, so that the non-docValued/norms
implementation matches
+ * NaN values for double and float fields. The [* TO *] query for those
fields does not match
+ * 'NaN' values, so they must be matched separately.
+ *
+ * <p>For doubles and floats the query behavior is equivalent to
field:[-Infinity TO NaN] since
+ * NaN has a value greater than +Infinity
+ */
+ @Override
+ public Query getSpecializedExistenceQuery(QParser parser, SchemaField field)
{
+ return DoublePoint.newRangeQuery(field.getName(),
Double.NEGATIVE_INFINITY, Double.NaN);
+ }
}
diff --git a/solr/core/src/java/org/apache/solr/schema/FloatPointField.java
b/solr/core/src/java/org/apache/solr/schema/FloatPointField.java
index e1b7786f8ac..4ed65fe45c3 100644
--- a/solr/core/src/java/org/apache/solr/schema/FloatPointField.java
+++ b/solr/core/src/java/org/apache/solr/schema/FloatPointField.java
@@ -178,4 +178,17 @@ public class FloatPointField extends PointField implements
FloatValueFieldType {
protected StoredField getStoredField(SchemaField sf, Object value) {
return new StoredField(sf.getName(), (Float) this.toNativeType(value));
}
+
+ /**
+ * Override the default existence behavior, so that the non-docValued/norms
implementation matches
+ * NaN values for double and float fields. The [* TO *] query for those
fields does not match
+ * 'NaN' values, so they must be matched separately.
+ *
+ * <p>For doubles and floats the query behavior is equivalent to
field:[-Infinity TO NaN] since
+ * NaN has a value greater than +Infinity
+ */
+ @Override
+ public Query getSpecializedExistenceQuery(QParser parser, SchemaField field)
{
+ return FloatPoint.newRangeQuery(field.getName(), Float.NEGATIVE_INFINITY,
Float.NaN);
+ }
}
diff --git a/solr/core/src/test/org/apache/solr/search/TestSolrQueryParser.java
b/solr/core/src/test/org/apache/solr/search/TestSolrQueryParser.java
index e8a8b3562f9..6dcf66563e7 100644
--- a/solr/core/src/test/org/apache/solr/search/TestSolrQueryParser.java
+++ b/solr/core/src/test/org/apache/solr/search/TestSolrQueryParser.java
@@ -32,6 +32,8 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
+import org.apache.lucene.document.DoublePoint;
+import org.apache.lucene.document.FloatPoint;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.BoostQuery;
@@ -40,6 +42,7 @@ import org.apache.lucene.search.FieldExistsQuery;
import org.apache.lucene.search.IndexOrDocValuesQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.PointInSetQuery;
+import org.apache.lucene.search.PointRangeQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermInSetQuery;
import org.apache.lucene.search.TermQuery;
@@ -1834,29 +1837,55 @@ public class TestSolrQueryParser extends SolrTestCaseJ4
{
createdQuery instanceof FieldExistsQuery);
} else if (schemaField.getType().getNumberType() == NumberType.DOUBLE
|| schemaField.getType().getNumberType() == NumberType.FLOAT) {
- assertTrue(
- "PointField with NaN values must include \"exists or NaN\" if
the field doesn't have norms or docValues: \""
- + query
- + "\".",
- createdQuery instanceof ConstantScoreQuery);
- assertTrue(
- "PointField with NaN values must include \"exists or NaN\" if
the field doesn't have norms or docValues: \""
- + query
- + "\".",
- ((ConstantScoreQuery) createdQuery).getQuery() instanceof
BooleanQuery);
- assertEquals(
- "PointField with NaN values must include \"exists or NaN\" if
the field doesn't have norms or docValues: \""
- + query
- + "\". This boolean query must be an OR.",
- 1,
- ((BooleanQuery) ((ConstantScoreQuery) createdQuery).getQuery())
- .getMinimumNumberShouldMatch());
- assertEquals(
- "PointField with NaN values must include \"exists or NaN\" if
the field doesn't have norms or docValues: \""
- + query
- + "\". This boolean query must have 2 clauses.",
- 2,
- ((BooleanQuery) ((ConstantScoreQuery)
createdQuery).getQuery()).clauses().size());
+ if (schemaField.getType().isPointField()) {
+ assertTrue(
+ "PointField with NaN values must do a range query with an
upper bound of NaN (Sorted higher than +Infinity) if the field doesn't have
norms or docValues: \""
+ + query
+ + "\".",
+ createdQuery instanceof PointRangeQuery);
+ if (schemaField.getType().getNumberType() == NumberType.DOUBLE) {
+ assertEquals(
+ "PointField with NaN values must do a range query with an
upper bound of NaN (Sorted higher than +Infinity) if the field doesn't have
norms or docValues: \""
+ + query
+ + "\".",
+ Double.NaN,
+ DoublePoint.decodeDimension(
+ ((PointRangeQuery) createdQuery).getUpperPoint(), 0),
+ 0);
+ } else {
+ assertEquals(
+ "PointField with NaN values must do a range query with an
upper bound of NaN (Sorted higher than +Infinity) if the field doesn't have
norms or docValues: \""
+ + query
+ + "\".",
+ Float.NaN,
+ FloatPoint.decodeDimension(((PointRangeQuery)
createdQuery).getUpperPoint(), 0),
+ 0);
+ }
+ } else {
+ assertTrue(
+ "PointField with NaN values must include \"exists or NaN\"
if the field doesn't have norms or docValues: \""
+ + query
+ + "\".",
+ createdQuery instanceof ConstantScoreQuery);
+ assertTrue(
+ "NumericField with NaN values must include \"exists or NaN\"
if the field doesn't have norms or docValues: \""
+ + query
+ + "\".",
+ ((ConstantScoreQuery) createdQuery).getQuery() instanceof
BooleanQuery);
+ assertEquals(
+ "NumericField with NaN values must include \"exists or NaN\"
if the field doesn't have norms or docValues: \""
+ + query
+ + "\". This boolean query must be an OR.",
+ 1,
+ ((BooleanQuery) ((ConstantScoreQuery)
createdQuery).getQuery())
+ .getMinimumNumberShouldMatch());
+ assertEquals(
+ "NumericField with NaN values must include \"exists or NaN\"
if the field doesn't have norms or docValues: \""
+ + query
+ + "\". This boolean query must have 2 clauses.",
+ 2,
+ ((BooleanQuery) ((ConstantScoreQuery)
createdQuery).getQuery()).clauses().size());
+ }
} else {
assertFalse(
"Field doesn't have docValues, so existence query \""