Explorar o código

ES\QL: Fix scoring for non full text functions (#124540)

Carlos Delgado hai 7 meses
pai
achega
7950751788
Modificáronse 40 ficheiros con 508 adicións e 248 borrados
  1. 5 0
      docs/changelog/124540.yaml
  2. 9 3
      x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/querydsl/query/BoolQuery.java
  3. 1 1
      x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/querydsl/query/ExistsQuery.java
  4. 1 1
      x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/querydsl/query/GeoDistanceQuery.java
  5. 1 1
      x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/querydsl/query/MatchAll.java
  6. 2 2
      x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/querydsl/query/NotQuery.java
  7. 1 1
      x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/querydsl/query/PrefixQuery.java
  8. 31 2
      x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/querydsl/query/Query.java
  9. 6 1
      x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/querydsl/query/QueryStringQuery.java
  10. 1 1
      x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/querydsl/query/RangeQuery.java
  11. 1 1
      x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/querydsl/query/RegexQuery.java
  12. 19 3
      x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/querydsl/query/TermQuery.java
  13. 1 1
      x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/querydsl/query/TermsQuery.java
  14. 1 1
      x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/querydsl/query/WildcardQuery.java
  15. 1 1
      x-pack/plugin/esql-core/src/test/java/org/elasticsearch/xpack/esql/core/querydsl/query/LeafQueryTests.java
  16. 27 19
      x-pack/plugin/esql/qa/testFixtures/src/main/resources/scoring.csv-spec
  17. 225 111
      x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoringIT.java
  18. 6 1
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java
  19. 1 1
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/QueryBuilderResolver.java
  20. 2 1
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Term.java
  21. 1 1
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/PushFiltersToSource.java
  22. 1 1
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/PushStatsToSource.java
  23. 1 1
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plan/physical/EsStatsQueryExec.java
  24. 1 1
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java
  25. 1 1
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/PlannerUtils.java
  26. 6 1
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/querydsl/query/KqlQuery.java
  27. 6 1
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/querydsl/query/MatchQuery.java
  28. 1 1
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/querydsl/query/MultiMatchQuery.java
  29. 2 2
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/querydsl/query/SingleValueQuery.java
  30. 6 3
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/querydsl/query/SpatialRelatesQuery.java
  31. 7 1
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/querydsl/query/TranslationAwareExpressionQuery.java
  32. 1 1
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/QueryBuilderResolver.java
  33. 1 1
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MatchErrorTests.java
  34. 1 1
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MatchTests.java
  35. 1 1
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/QueryStringTests.java
  36. 52 44
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LocalPhysicalPlanOptimizerTests.java
  37. 22 14
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/PhysicalPlanOptimizerTests.java
  38. 46 10
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/FilterTests.java
  39. 8 8
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/QueryTranslatorTests.java
  40. 1 1
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/querydsl/query/QueryStringQueryTests.java

+ 5 - 0
docs/changelog/124540.yaml

@@ -0,0 +1,5 @@
+pr: 124540
+summary: "ES|QL: Fix scoring for full text functions"
+area: ES|QL
+type: bug
+issues: []

+ 9 - 3
x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/querydsl/query/BoolQuery.java

@@ -43,13 +43,14 @@ public class BoolQuery extends Query {
     }
 
     @Override
-    public QueryBuilder asBuilder() {
+    protected QueryBuilder asBuilder() {
         BoolQueryBuilder boolQuery = boolQuery();
         for (Query query : queries) {
+            QueryBuilder queryBuilder = query.toQueryBuilder();
             if (isAnd) {
-                boolQuery.must(query.asBuilder());
+                boolQuery.must(queryBuilder);
             } else {
-                boolQuery.should(query.asBuilder());
+                boolQuery.should(queryBuilder);
             }
         }
         return boolQuery;
@@ -94,4 +95,9 @@ public class BoolQuery extends Query {
         }
         return new BoolQuery(source, isAnd == false, negated);
     }
+
+    @Override
+    public boolean scorable() {
+        return true;
+    }
 }

+ 1 - 1
x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/querydsl/query/ExistsQuery.java

@@ -21,7 +21,7 @@ public class ExistsQuery extends Query {
     }
 
     @Override
-    public QueryBuilder asBuilder() {
+    protected QueryBuilder asBuilder() {
         return existsQuery(name);
     }
 

+ 1 - 1
x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/querydsl/query/GeoDistanceQuery.java

@@ -45,7 +45,7 @@ public class GeoDistanceQuery extends Query {
     }
 
     @Override
-    public QueryBuilder asBuilder() {
+    protected QueryBuilder asBuilder() {
         return QueryBuilders.geoDistanceQuery(field).distance(distance, DistanceUnit.METERS).point(lat, lon);
     }
 

+ 1 - 1
x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/querydsl/query/MatchAll.java

@@ -17,7 +17,7 @@ public class MatchAll extends Query {
     }
 
     @Override
-    public QueryBuilder asBuilder() {
+    protected QueryBuilder asBuilder() {
         return matchAllQuery();
     }
 

+ 2 - 2
x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/querydsl/query/NotQuery.java

@@ -32,8 +32,8 @@ public class NotQuery extends Query {
     }
 
     @Override
-    public QueryBuilder asBuilder() {
-        return boolQuery().mustNot(child.asBuilder());
+    protected QueryBuilder asBuilder() {
+        return boolQuery().mustNot(child.toQueryBuilder());
     }
 
     @Override

+ 1 - 1
x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/querydsl/query/PrefixQuery.java

@@ -34,7 +34,7 @@ public class PrefixQuery extends Query {
     }
 
     @Override
-    public QueryBuilder asBuilder() {
+    protected QueryBuilder asBuilder() {
         return prefixQuery(field, query).caseInsensitive(caseInsensitive);
     }
 

+ 31 - 2
x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/querydsl/query/Query.java

@@ -28,6 +28,10 @@ import org.elasticsearch.xpack.esql.core.tree.Source;
  * </p>
  */
 public abstract class Query {
+
+    // Boosting used to remove scoring from queries that don't contribute to it
+    public static final float NO_SCORE_BOOST = 0.0f;
+
     private final Source source;
 
     protected Query(Source source) {
@@ -46,9 +50,20 @@ public abstract class Query {
 
     /**
      * Convert to an Elasticsearch {@link QueryBuilder} all set up to execute
-     * the query.
+     * the query. This ensures that queries have appropriate boosting for scoring.
+     */
+    public final QueryBuilder toQueryBuilder() {
+        QueryBuilder builder = asBuilder();
+        if (scorable() == false) {
+            builder = unscore(builder);
+        }
+        return builder;
+    }
+
+    /**
+     * Used internally to convert to retrieve a {@link QueryBuilder} by queries.
      */
-    public abstract QueryBuilder asBuilder();
+    protected abstract QueryBuilder asBuilder();
 
     /**
      * Used by {@link Query#toString()} to produce a pretty string.
@@ -85,4 +100,18 @@ public abstract class Query {
     public Query negate(Source source) {
         return new NotQuery(source, this);
     }
+
+    /**
+     * Defines whether a query should contribute to the overall score
+     */
+    public boolean scorable() {
+        return false;
+    }
+
+    /**
+     * Removes score from a query builder, so score is not affected by the query
+     */
+    public static QueryBuilder unscore(QueryBuilder builder) {
+        return builder.boost(NO_SCORE_BOOST);
+    }
 }

+ 6 - 1
x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/querydsl/query/QueryStringQuery.java

@@ -88,7 +88,7 @@ public class QueryStringQuery extends Query {
     }
 
     @Override
-    public QueryBuilder asBuilder() {
+    protected QueryBuilder asBuilder() {
         final QueryStringQueryBuilder queryBuilder = QueryBuilders.queryStringQuery(query);
         queryBuilder.fields(fields);
         options.forEach((k, v) -> {
@@ -132,4 +132,9 @@ public class QueryStringQuery extends Query {
     protected String innerToString() {
         return fields + ":" + query;
     }
+
+    @Override
+    public boolean scorable() {
+        return true;
+    }
 }

+ 1 - 1
x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/querydsl/query/RangeQuery.java

@@ -77,7 +77,7 @@ public class RangeQuery extends Query {
     }
 
     @Override
-    public QueryBuilder asBuilder() {
+    protected QueryBuilder asBuilder() {
         RangeQueryBuilder queryBuilder = rangeQuery(field).from(lower, includeLower).to(upper, includeUpper);
         if (Strings.hasText(format)) {
             queryBuilder.format(format);

+ 1 - 1
x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/querydsl/query/RegexQuery.java

@@ -42,7 +42,7 @@ public class RegexQuery extends Query {
     }
 
     @Override
-    public QueryBuilder asBuilder() {
+    protected QueryBuilder asBuilder() {
         return regexpQuery(field, regex).caseInsensitive(caseInsensitive);
     }
 

+ 19 - 3
x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/querydsl/query/TermQuery.java

@@ -14,21 +14,31 @@ import java.util.Objects;
 
 import static org.elasticsearch.index.query.QueryBuilders.termQuery;
 
+/**
+ * Term query. It can be considered for scoring or not - filters that use term query as implementation will not use scoring,
+ * but the Term full text function will
+ */
 public class TermQuery extends Query {
 
     private final String term;
     private final Object value;
     private final boolean caseInsensitive;
+    private final boolean scorable;
 
     public TermQuery(Source source, String term, Object value) {
         this(source, term, value, false);
     }
 
     public TermQuery(Source source, String term, Object value, boolean caseInsensitive) {
+        this(source, term, value, caseInsensitive, false);
+    }
+
+    public TermQuery(Source source, String term, Object value, boolean caseInsensitive, boolean scorable) {
         super(source);
         this.term = term;
         this.value = value;
         this.caseInsensitive = caseInsensitive;
+        this.scorable = scorable;
     }
 
     public String term() {
@@ -44,7 +54,7 @@ public class TermQuery extends Query {
     }
 
     @Override
-    public QueryBuilder asBuilder() {
+    protected QueryBuilder asBuilder() {
         TermQueryBuilder qb = termQuery(term, value);
         // ES does not allow case_insensitive to be set to "false", it should be either "true" or not specified
         return caseInsensitive == false ? qb : qb.caseInsensitive(caseInsensitive);
@@ -52,7 +62,7 @@ public class TermQuery extends Query {
 
     @Override
     public int hashCode() {
-        return Objects.hash(term, value, caseInsensitive);
+        return Objects.hash(term, value, caseInsensitive, scorable);
     }
 
     @Override
@@ -68,11 +78,17 @@ public class TermQuery extends Query {
         TermQuery other = (TermQuery) obj;
         return Objects.equals(term, other.term)
             && Objects.equals(value, other.value)
-            && Objects.equals(caseInsensitive, other.caseInsensitive);
+            && Objects.equals(caseInsensitive, other.caseInsensitive)
+            && scorable == other.scorable;
     }
 
     @Override
     protected String innerToString() {
         return term + ":" + value;
     }
+
+    @Override
+    public boolean scorable() {
+        return scorable;
+    }
 }

+ 1 - 1
x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/querydsl/query/TermsQuery.java

@@ -26,7 +26,7 @@ public class TermsQuery extends Query {
     }
 
     @Override
-    public QueryBuilder asBuilder() {
+    protected QueryBuilder asBuilder() {
         return termsQuery(term, values);
     }
 

+ 1 - 1
x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/querydsl/query/WildcardQuery.java

@@ -43,7 +43,7 @@ public class WildcardQuery extends Query {
     }
 
     @Override
-    public QueryBuilder asBuilder() {
+    protected QueryBuilder asBuilder() {
         WildcardQueryBuilder wb = wildcardQuery(field, query);
         // ES does not allow case_insensitive to be set to "false", it should be either "true" or not specified
         return caseInsensitive == false ? wb : wb.caseInsensitive(caseInsensitive);

+ 1 - 1
x-pack/plugin/esql-core/src/test/java/org/elasticsearch/xpack/esql/core/querydsl/query/LeafQueryTests.java

@@ -23,7 +23,7 @@ public class LeafQueryTests extends ESTestCase {
         }
 
         @Override
-        public QueryBuilder asBuilder() {
+        protected QueryBuilder asBuilder() {
             return null;
         }
 

+ 27 - 19
x-pack/plugin/esql/qa/testFixtures/src/main/resources/scoring.csv-spec

@@ -145,6 +145,7 @@ book_no:keyword | title:text                                | author:text
 combinedMatchWithFunctionsScoring
 required_capability: metadata_score
 required_capability: match_operator_colon
+required_capability: non_full_text_functions_scoring
 
 from books metadata _score
 | where title:"Tolkien" AND author:"Tolkien" AND year > 2000
@@ -153,7 +154,7 @@ from books metadata _score
 | sort book_no;
 
 book_no:keyword | title:text               | author:text    | year:integer | _score:double
-5335            | Letters of J R R Tolkien | J.R.R. Tolkien | 2014         | 4.733664035797119
+5335            | Letters of J R R Tolkien | J.R.R. Tolkien | 2014         | 3.733664035797119
 ;
 
 singleQstrScoring
@@ -191,6 +192,7 @@ book_no:keyword | title:keyword | _score:double
 combinedMatchWithScoringEvalNoSort
 required_capability: metadata_score
 required_capability: match_operator_colon
+required_capability: non_full_text_functions_scoring
 
 from books metadata _score
 | where title:"Tolkien" AND author:"Tolkien" AND year > 2000
@@ -200,7 +202,7 @@ from books metadata _score
 
 ignoreOrder:true
 book_no:keyword | title:text               | author:text    | year:integer | c_score:double
-5335            | Letters of J R R Tolkien | J.R.R. Tolkien | 2014         | 5.0
+5335            | Letters of J R R Tolkien | J.R.R. Tolkien | 2014         | 4.0
 ;
 
 singleQstrScoringRename
@@ -241,6 +243,7 @@ book_no:keyword | author:text                                        | _score:do
 combinedMatchWithFunctionsScoringNoSort
 required_capability: metadata_score
 required_capability: match_operator_colon
+required_capability: non_full_text_functions_scoring
 
 from books metadata _score
 | where title:"Tolkien" AND author:"Tolkien" AND year > 2000
@@ -249,12 +252,13 @@ from books metadata _score
 
 ignoreOrder:true
 book_no:keyword | title:text               | author:text    | year:integer | _score:double
-5335            | Letters of J R R Tolkien | J.R.R. Tolkien | 2014         | 4.733664035797119
+5335            | Letters of J R R Tolkien | J.R.R. Tolkien | 2014         | 3.733664035797119
 ;
 
 combinedMatchWithScoringEval
 required_capability: metadata_score
 required_capability: match_operator_colon
+required_capability: non_full_text_functions_scoring
 
 from books metadata _score
 | where title:"Tolkien" AND author:"Tolkien" AND year > 2000
@@ -264,7 +268,7 @@ from books metadata _score
 | sort book_no;
 
 book_no:keyword | title:text               | author:text    | year:integer | c_score:double
-5335            | Letters of J R R Tolkien | J.R.R. Tolkien | 2014         | 5.0
+5335            | Letters of J R R Tolkien | J.R.R. Tolkien | 2014         | 4.0
 ;
 
 singleQstrScoringEval
@@ -361,6 +365,7 @@ _id:keyword
 scoresNonPushableFunctions
 
 required_capability: metadata_score
+required_capability: non_full_text_functions_scoring
 
 from books metadata _score 
 | where length(title) > 100
@@ -369,13 +374,14 @@ from books metadata _score
 ;
 
 book_no:keyword |  _score:double
-2924            | 1.0
-8678            | 1.0
+2924            | 0.0
+8678            | 0.0
 ;
 
 scoresPushableFunctions
 
 required_capability: metadata_score
+required_capability: non_full_text_functions_scoring
 
 from books metadata _score 
 | where year >= 2017
@@ -384,11 +390,11 @@ from books metadata _score
 ;
 
 book_no:keyword | _score:double
-6818            | 1.0
-7400            | 1.0
-8480            | 1.0
-8534            | 1.0
-8615            | 1.0
+6818            | 0.0
+7400            | 0.0
+8480            | 0.0
+8534            | 0.0
+8615            | 0.0
 ;
 
 conjunctionScoresPushableNonPushableFunctions
@@ -413,6 +419,7 @@ conjunctionScoresPushableFunctions
 
 required_capability: metadata_score
 required_capability: match_function
+required_capability: non_full_text_functions_scoring
 
 from books metadata _score 
 | where match(title, "Lord") and ratings > 4.6
@@ -421,8 +428,8 @@ from books metadata _score
 ;
 
 book_no:keyword |  _score:double
-7140            | 2.746896743774414 
-4023            | 2.5062403678894043
+7140            | 1.746896743774414 
+4023            | 1.5062403678894043
 ;
 
 disjunctionScoresPushableNonPushableFunctions
@@ -430,6 +437,7 @@ disjunctionScoresPushableNonPushableFunctions
 required_capability: metadata_score
 required_capability: match_operator_colon
 required_capability: full_text_functions_disjunctions_score
+required_capability: non_full_text_functions_scoring
 
 from books metadata _score 
 | where match(title, "Lord") or length(title) > 100
@@ -438,12 +446,12 @@ from books metadata _score
 ;
 
 book_no:keyword |  _score:double
-2675            | 3.5619282722473145
-2714            | 2.9245924949645996
-7140            | 2.746896743774414
-4023            | 2.5062403678894043
-2924            | 1.0
-8678            | 1.0
+2675            | 2.5619282722473145
+2714            | 1.9245924949645996
+7140            | 1.746896743774414
+4023            | 1.5062403678894043
+2924            | 0.0
+8678            | 0.0
 ;
 
 

+ 225 - 111
x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoringIT.java

@@ -7,150 +7,272 @@
 
 package org.elasticsearch.xpack.esql.plugin;
 
+import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
+
 import org.elasticsearch.action.index.IndexRequest;
 import org.elasticsearch.action.support.WriteRequest;
 import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.common.util.CollectionUtils;
+import org.elasticsearch.plugins.Plugin;
+import org.elasticsearch.xpack.esql.EsqlTestUtils;
 import org.elasticsearch.xpack.esql.action.AbstractEsqlIntegTestCase;
+import org.elasticsearch.xpack.kql.KqlPlugin;
 import org.junit.Before;
 
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Locale;
+import java.util.Map;
 
 import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
 import static org.elasticsearch.xpack.esql.EsqlTestUtils.getValuesList;
 import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.greaterThan;
-import static org.hamcrest.Matchers.is;
 import static org.hamcrest.Matchers.lessThan;
 
-//@TestLogging(value = "org.elasticsearch.xpack.esql:TRACE,org.elasticsearch.compute:TRACE", reason = "debug")
 public class ScoringIT extends AbstractEsqlIntegTestCase {
 
+    private final String matchingClause;
+
+    @Override
+    protected Collection<Class<? extends Plugin>> nodePlugins() {
+        return CollectionUtils.appendToCopy(super.nodePlugins(), KqlPlugin.class);
+    }
+
+    @ParametersFactory
+    public static List<Object[]> params() {
+        List<Object[]> params = new ArrayList<>();
+        params.add(new Object[] { "match(content, \"fox\")" });
+        params.add(new Object[] { "content:\"fox\"" });
+        params.add(new Object[] { "qstr(\"content: fox\")" });
+        params.add(new Object[] { "kql(\"content*: fox\")" });
+        params.add(new Object[] { "term(content, \"fox\")" });
+        return params;
+    }
+
+    public ScoringIT(String matchingClause) {
+        this.matchingClause = matchingClause;
+    }
+
     @Before
     public void setupIndex() {
         createAndPopulateIndex();
     }
 
-    public void testDefaultScoring() {
-        var query = """
-            FROM test METADATA _score
+    public void testWhereMatchWithScoring() {
+        var query = String.format(Locale.ROOT, """
+            FROM test
+            METADATA _score
+            | WHERE %s
             | KEEP id, _score
-            | SORT _score DESC, id ASC
-            """;
+            | SORT id ASC
+            """, matchingClause);
 
         try (var resp = run(query)) {
             assertColumnNames(resp.columns(), List.of("id", "_score"));
             assertColumnTypes(resp.columns(), List.of("integer", "double"));
-            List<List<Object>> values = getValuesList(resp);
-
-            assertThat(values.size(), equalTo(6));
-
-            for (int i = 0; i < 6; i++) {
-                assertThat(values.get(0).get(1), equalTo(1.0));
-            }
+            assertValues(resp.values(), List.of(List.of(1, 1.156558871269226), List.of(6, 0.9114001989364624)));
         }
     }
 
-    public void testScoringNonPushableFunctions() {
-        var query = """
-            FROM test METADATA _score
-            | WHERE length(content) < 20
+    public void testWhereMatchWithScoringDifferentSort() {
+
+        var query = String.format(Locale.ROOT, """
+            FROM test
+            METADATA _score
+            | WHERE %s
             | KEEP id, _score
-            | SORT _score DESC, id ASC
-            """;
+            | SORT id DESC
+            """, matchingClause);
+        ;
 
         try (var resp = run(query)) {
             assertColumnNames(resp.columns(), List.of("id", "_score"));
             assertColumnTypes(resp.columns(), List.of("integer", "double"));
-            List<List<Object>> values = getValuesList(resp);
-            assertThat(values.size(), equalTo(2));
+            assertValues(resp.values(), List.of(List.of(6, 0.9114001989364624), List.of(1, 1.156558871269226)));
+        }
+    }
 
-            assertThat(values.get(0).get(0), equalTo(1));
-            assertThat(values.get(1).get(0), equalTo(2));
+    public void testWhereMatchWithScoringSortScore() {
+        var query = String.format(Locale.ROOT, """
+            FROM test
+            METADATA _score
+            | WHERE %s
+            | KEEP id, _score
+            | SORT _score DESC
+            """, matchingClause);
 
-            assertThat((Double) values.get(0).get(1), is(1.0));
-            assertThat((Double) values.get(1).get(1), is(1.0));
+        try (var resp = run(query)) {
+            assertColumnNames(resp.columns(), List.of("id", "_score"));
+            assertColumnTypes(resp.columns(), List.of("integer", "double"));
+            assertValues(resp.values(), List.of(List.of(1, 1.156558871269226), List.of(6, 0.9114001989364624)));
         }
     }
 
-    public void testDisjunctionScoring() {
-        var query = """
-            FROM test METADATA _score
-            | WHERE match(content, "fox") OR length(content) < 20
+    public void testWhereMatchWithScoringNoSort() {
+        var query = String.format(Locale.ROOT, """
+            FROM test
+            METADATA _score
+            | WHERE %s
             | KEEP id, _score
-            | SORT _score DESC, id ASC
-            """;
+            """, matchingClause);
 
         try (var resp = run(query)) {
             assertColumnNames(resp.columns(), List.of("id", "_score"));
             assertColumnTypes(resp.columns(), List.of("integer", "double"));
-            List<List<Object>> values = getValuesList(resp);
-            assertThat(values.size(), equalTo(3));
+            assertValuesInAnyOrder(resp.values(), List.of(List.of(1, 1.156558871269226), List.of(6, 0.9114001989364624)));
+        }
+    }
 
-            assertThat(values.get(0).get(0), equalTo(1));
-            assertThat(values.get(1).get(0), equalTo(6));
-            assertThat(values.get(2).get(0), equalTo(2));
+    public void testMatchAllScoring() {
+        var query = """
+            FROM test
+            METADATA _score
+            | KEEP id, _score
+            """;
 
-            // Matches full text query and non pushable query
-            assertThat((Double) values.get(0).get(1), greaterThan(1.0));
-            assertThat((Double) values.get(1).get(1), greaterThan(1.0));
-            // Matches just non pushable query
-            assertThat((Double) values.get(2).get(1), equalTo(1.0));
-        }
+        assertZeroScore(query);
     }
 
-    public void testConjunctionPushableScoring() {
+    public void testNonPushableFunctionsScoring() {
         var query = """
-            FROM test METADATA _score
-            | WHERE match(content, "fox") AND id > 4
+            FROM test
+            METADATA _score
+            | WHERE length(content) < 20
             | KEEP id, _score
-            | SORT _score DESC, id ASC
             """;
 
-        try (var resp = run(query)) {
-            assertColumnNames(resp.columns(), List.of("id", "_score"));
-            assertColumnTypes(resp.columns(), List.of("integer", "double"));
-            List<List<Object>> values = getValuesList(resp);
-            assertThat(values.size(), equalTo(1));
+        assertZeroScore(query);
 
-            assertThat(values.get(0).get(0), equalTo(6));
+        query = """
+            FROM test
+            METADATA _score
+            | WHERE length(content) < 20 OR id > 4
+            | KEEP id, _score
+            """;
 
-            // Matches full text query and pushable query
-            assertThat((Double) values.get(0).get(1), greaterThan(1.0));
-        }
+        assertZeroScore(query);
+
+        query = """
+            FROM test
+            METADATA _score
+            | WHERE length(content) < 20 AND id < 4
+            | KEEP id, _score
+            """;
+
+        assertZeroScore(query);
     }
 
-    public void testConjunctionNonPushableScoring() {
+    public void testPushableFunctionsScoring() {
         var query = """
-            FROM test METADATA _score
-            | WHERE match(content, "fox") AND length(content) < 20
+            FROM test
+            METADATA _score
+            | WHERE id > 4
             | KEEP id, _score
-            | SORT _score DESC, id ASC
+            | SORT id ASC
+            """;
+
+        assertZeroScore(query);
+
+        query = """
+            FROM test
+            METADATA _score
+            | WHERE id > 4 AND id < 7
+            | KEEP id, _score
+            | SORT id ASC
             """;
 
+        assertZeroScore(query);
+    }
+
+    private void assertZeroScore(String query) {
         try (var resp = run(query)) {
-            assertColumnNames(resp.columns(), List.of("id", "_score"));
-            assertColumnTypes(resp.columns(), List.of("integer", "double"));
+            List<List<Object>> values = EsqlTestUtils.getValuesList(resp.values());
+            for (List<Object> value : values) {
+                assertThat((Double) value.get(1), equalTo(0.0));
+            }
+        }
+    }
+
+    public void testPushableAndFullTextFunctionsConjunctionScoring() {
+        var queryWithoutFilter = String.format(Locale.ROOT, """
+            FROM test
+            METADATA _score
+            | WHERE %s
+            | KEEP id, _score
+            | SORT id ASC
+            """, matchingClause);
+        var query = String.format(Locale.ROOT, """
+            FROM test
+            METADATA _score
+            | WHERE %s AND id > 4
+            | KEEP id, _score
+            | SORT id ASC
+            """, matchingClause);
+        checkSameScores(queryWithoutFilter, query);
+
+        query = String.format(Locale.ROOT, """
+            FROM test
+            METADATA _score
+            | WHERE %s AND (id > 4 or id < 2)
+            | KEEP id, _score
+            | SORT id ASC
+            """, matchingClause);
+        queryWithoutFilter = String.format(Locale.ROOT, """
+            FROM test
+            METADATA _score
+            | WHERE %s
+            | KEEP id, _score
+            | SORT id ASC
+            """, matchingClause);
+        checkSameScores(queryWithoutFilter, query);
+    }
+
+    public void testDisjunctionScoring() {
+        var queryWithoutFilter = String.format(Locale.ROOT, """
+            FROM test
+            METADATA _score
+            | WHERE %s OR length(content) < 20
+            | KEEP id, _score
+            | SORT _score DESC, id ASC
+            """, matchingClause);
+        var query = String.format(Locale.ROOT, """
+            FROM test
+            METADATA _score
+            | WHERE %s
+            | KEEP id, _score
+            | SORT _score DESC, id ASC
+            """, matchingClause);
+
+        checkSameScores(queryWithoutFilter, query);
+
+        try (var resp = run(queryWithoutFilter)) {
             List<List<Object>> values = getValuesList(resp);
-            assertThat(values.size(), equalTo(1));
+            assertThat(values.size(), equalTo(3));
 
             assertThat(values.get(0).get(0), equalTo(1));
+            assertThat(values.get(1).get(0), equalTo(6));
+            assertThat(values.get(2).get(0), equalTo(2));
 
-            // Matches full text query and pushable query
-            assertThat((Double) values.get(0).get(1), greaterThan(1.0));
+            // Matches full text query and non pushable query
+            assertThat((Double) values.get(0).get(1), greaterThan(0.0));
+            assertThat((Double) values.get(1).get(1), greaterThan(0.0));
+            // Matches just non pushable query
+            assertThat((Double) values.get(2).get(1), equalTo(0.0));
         }
     }
 
     public void testDisjunctionScoringPushableFunctions() {
-        var query = """
+        var query = String.format(Locale.ROOT, """
             FROM test METADATA _score
-            | WHERE match(content, "fox") OR match(content, "quick")
+            | WHERE %s OR match(content, "quick")
             | KEEP id, _score
             | SORT _score DESC, id ASC
-            """;
+            """, matchingClause);
 
         try (var resp = run(query)) {
-            assertColumnNames(resp.columns(), List.of("id", "_score"));
-            assertColumnTypes(resp.columns(), List.of("integer", "double"));
             List<List<Object>> values = getValuesList(resp);
             assertThat(values.size(), equalTo(2));
 
@@ -165,16 +287,22 @@ public class ScoringIT extends AbstractEsqlIntegTestCase {
     }
 
     public void testDisjunctionScoringMultipleNonPushableFunctions() {
-        var query = """
+        var query = String.format(Locale.ROOT, """
             FROM test METADATA _score
-            | WHERE match(content, "fox") OR length(content) < 20 AND id > 2
+            | WHERE %s
             | KEEP id, _score
             | SORT _score DESC
-            """;
+            """, matchingClause);
+        var queryWithoutFilter = String.format(Locale.ROOT, """
+            FROM test METADATA _score
+            | WHERE %s OR length(content) < 20 AND id > 2
+            | KEEP id, _score
+            | SORT _score DESC
+            """, matchingClause);
 
-        try (var resp = run(query)) {
-            assertColumnNames(resp.columns(), List.of("id", "_score"));
-            assertColumnTypes(resp.columns(), List.of("integer", "double"));
+        checkSameScores(queryWithoutFilter, query);
+
+        try (var resp = run(queryWithoutFilter)) {
             List<List<Object>> values = getValuesList(resp);
             assertThat(values.size(), equalTo(2));
 
@@ -182,57 +310,43 @@ public class ScoringIT extends AbstractEsqlIntegTestCase {
             assertThat(values.get(1).get(0), equalTo(6));
 
             // Matches the full text query and the two pushable query
-            assertThat((Double) values.get(0).get(1), greaterThan(2.0));
-            assertThat((Double) values.get(0).get(1), lessThan(3.0));
+            assertThat((Double) values.get(0).get(1), greaterThan(0.0));
             // Matches just the match function
-            assertThat((Double) values.get(1).get(1), lessThan(2.0));
-            assertThat((Double) values.get(1).get(1), greaterThan(1.0));
+            assertThat((Double) values.get(1).get(1), lessThan(1.0));
+            assertThat((Double) values.get(1).get(1), greaterThan(0.1));
         }
     }
 
     public void testDisjunctionScoringWithNot() {
-        var query = """
+        var query = String.format(Locale.ROOT, """
             FROM test METADATA _score
-            | WHERE NOT(match(content, "dog")) OR length(content) > 50
+            | WHERE NOT(%s) OR length(content) > 50
             | KEEP id, _score
             | SORT _score DESC, id ASC
-            """;
+            """, matchingClause);
 
         try (var resp = run(query)) {
-            assertColumnNames(resp.columns(), List.of("id", "_score"));
-            assertColumnTypes(resp.columns(), List.of("integer", "double"));
-            List<List<Object>> values = getValuesList(resp);
-            assertThat(values.size(), equalTo(3));
-
-            assertThat(values.get(0).get(0), equalTo(1));
-            assertThat(values.get(1).get(0), equalTo(4));
-            assertThat(values.get(2).get(0), equalTo(5));
-
-            // Matches NOT gets 0.0 and default score is 1.0
-            assertThat((Double) values.get(0).get(1), equalTo(1.0));
-            assertThat((Double) values.get(1).get(1), equalTo(1.0));
-            assertThat((Double) values.get(2).get(1), equalTo(1.0));
+            // Matches NOT gets 0.0
+            assertThat(getValuesList(resp), equalTo(List.of(List.of(2, 0.0), List.of(3, 0.0), List.of(4, 0.0), List.of(5, 0.0))));
         }
     }
 
-    public void testScoringWithNoFullTextFunction() {
-        var query = """
-            FROM test METADATA _score
-            | WHERE length(content) > 50
-            | KEEP id, _score
-            | SORT _score DESC, id ASC
-            """;
-
+    private void checkSameScores(String queryWithoutFilter, String query) {
+        Map<Integer, Double> expectedScores = new HashMap<>();
+        try (var respWithoutFilter = run(queryWithoutFilter)) {
+            List<List<Object>> valuesList = EsqlTestUtils.getValuesList(respWithoutFilter);
+            for (List<Object> result : valuesList) {
+                expectedScores.put((Integer) result.get(0), (Double) result.get(1));
+            }
+        }
         try (var resp = run(query)) {
             assertColumnNames(resp.columns(), List.of("id", "_score"));
             assertColumnTypes(resp.columns(), List.of("integer", "double"));
-            List<List<Object>> values = getValuesList(resp);
-            assertThat(values.size(), equalTo(1));
-
-            assertThat(values.get(0).get(0), equalTo(4));
-
-            // Non pushable query gets score of 0.0, summed with 1.0 coming from Lucene
-            assertThat((Double) values.get(0).get(1), equalTo(1.0));
+            List<List<Object>> values = EsqlTestUtils.getValuesList(resp.values());
+            for (List<Object> value : values) {
+                Double score = (Double) value.get(1);
+                assertThat(expectedScores.get((Integer) value.get(0)), equalTo(score));
+            }
         }
     }
 

+ 6 - 1
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java

@@ -891,7 +891,12 @@ public class EsqlCapabilities {
         /**
          * Use double parameter markers to represent field or function names.
          */
-        DOUBLE_PARAMETER_MARKERS_FOR_IDENTIFIERS(Build.current().isSnapshot());
+        DOUBLE_PARAMETER_MARKERS_FOR_IDENTIFIERS(Build.current().isSnapshot()),
+
+        /**
+         * Non full text functions do not contribute to score
+         */
+        NON_FULL_TEXT_FUNCTIONS_SCORING;
 
         private final boolean enabled;
 

+ 1 - 1
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/QueryBuilderResolver.java

@@ -76,7 +76,7 @@ public final class QueryBuilderResolver {
             Holder<Boolean> updated = new Holder<>(false);
             LogicalPlan newPlan = plan.transformExpressionsDown(FullTextFunction.class, f -> {
                 QueryBuilder builder = f.queryBuilder(), initial = builder;
-                builder = builder == null ? f.asQuery(TranslatorHandler.TRANSLATOR_HANDLER).asBuilder() : builder;
+                builder = builder == null ? f.asQuery(TranslatorHandler.TRANSLATOR_HANDLER).toQueryBuilder() : builder;
                 try {
                     builder = builder.rewrite(ctx);
                 } catch (IOException e) {

+ 2 - 1
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Term.java

@@ -141,7 +141,8 @@ public class Term extends FullTextFunction implements PostAnalysisPlanVerificati
 
     @Override
     protected Query translate(TranslatorHandler handler) {
-        return new TermQuery(source(), ((FieldAttribute) field()).name(), queryAsObject());
+        // Uses a term query that contributes to scoring
+        return new TermQuery(source(), ((FieldAttribute) field()).name(), queryAsObject(), false, true);
     }
 
     @Override

+ 1 - 1
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/PushFiltersToSource.java

@@ -100,7 +100,7 @@ public class PushFiltersToSource extends PhysicalOptimizerRules.ParameterizedOpt
         List<Expression> newPushable = combineEligiblePushableToRange(pushable);
         if (newPushable.size() > 0) { // update the executable with pushable conditions
             Query queryDSL = TRANSLATOR_HANDLER.asQuery(Predicates.combineAnd(newPushable));
-            QueryBuilder planQuery = queryDSL.asBuilder();
+            QueryBuilder planQuery = queryDSL.toQueryBuilder();
             Queries.Clause combiningQueryClauseType = queryExec.hasScoring() ? Queries.Clause.MUST : Queries.Clause.FILTER;
             var query = Queries.combine(combiningQueryClauseType, asList(queryExec.query(), planQuery));
             queryExec = new EsQueryExec(

+ 1 - 1
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/PushStatsToSource.java

@@ -107,7 +107,7 @@ public class PushStatsToSource extends PhysicalOptimizerRules.ParameterizedOptim
                                         return null; // can't push down
                                     }
                                     var countFilter = TRANSLATOR_HANDLER.asQuery(count.filter());
-                                    query = Queries.combine(Queries.Clause.MUST, asList(countFilter.asBuilder(), query));
+                                    query = Queries.combine(Queries.Clause.MUST, asList(countFilter.toQueryBuilder(), query));
                                 }
                                 return new EsStatsQueryExec.Stat(fieldName, COUNT, query);
                             }

+ 1 - 1
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plan/physical/EsStatsQueryExec.java

@@ -38,7 +38,7 @@ public class EsStatsQueryExec extends LeafExec implements EstimatesRowSize {
 
     public record Stat(String name, StatsType type, QueryBuilder query) {
         public QueryBuilder filter(QueryBuilder sourceQuery) {
-            return query == null ? sourceQuery : Queries.combine(Queries.Clause.FILTER, asList(sourceQuery, query));
+            return query == null ? sourceQuery : Queries.combine(Queries.Clause.FILTER, asList(sourceQuery, query)).boost(0.0f);
         }
     }
 

+ 1 - 1
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java

@@ -173,7 +173,7 @@ public class EsPhysicalOperationProviders extends AbstractPhysicalOperationProvi
     }
 
     public Function<org.elasticsearch.compute.lucene.ShardContext, Query> querySupplier(QueryBuilder builder) {
-        QueryBuilder qb = builder == null ? QueryBuilders.matchAllQuery() : builder;
+        QueryBuilder qb = builder == null ? QueryBuilders.matchAllQuery().boost(0.0f) : builder;
         return ctx -> shardContexts.get(ctx.index()).toQuery(qb);
     }
 

+ 1 - 1
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/PlannerUtils.java

@@ -220,7 +220,7 @@ public class PlannerUtils {
                     }
                 }
                 if (matches.isEmpty() == false) {
-                    requestFilters.add(TRANSLATOR_HANDLER.asQuery(Predicates.combineAnd(matches)).asBuilder());
+                    requestFilters.add(TRANSLATOR_HANDLER.asQuery(Predicates.combineAnd(matches)).toQueryBuilder());
                 }
             });
         });

+ 6 - 1
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/querydsl/query/KqlQuery.java

@@ -43,7 +43,7 @@ public class KqlQuery extends Query {
     }
 
     @Override
-    public QueryBuilder asBuilder() {
+    protected QueryBuilder asBuilder() {
         final KqlQueryBuilder queryBuilder = new KqlQueryBuilder(query);
         options.forEach((k, v) -> {
             if (BUILDER_APPLIERS.containsKey(k)) {
@@ -82,4 +82,9 @@ public class KqlQuery extends Query {
     protected String innerToString() {
         return query;
     }
+
+    @Override
+    public boolean scorable() {
+        return true;
+    }
 }

+ 6 - 1
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/querydsl/query/MatchQuery.java

@@ -72,7 +72,7 @@ public class MatchQuery extends Query {
     }
 
     @Override
-    public QueryBuilder asBuilder() {
+    protected QueryBuilder asBuilder() {
         final MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery(name, text);
         options.forEach((k, v) -> {
             if (BUILDER_APPLIERS.containsKey(k)) {
@@ -125,4 +125,9 @@ public class MatchQuery extends Query {
     public Map<String, Object> options() {
         return options;
     }
+
+    @Override
+    public boolean scorable() {
+        return true;
+    }
 }

+ 1 - 1
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/querydsl/query/MultiMatchQuery.java

@@ -61,7 +61,7 @@ public class MultiMatchQuery extends Query {
     }
 
     @Override
-    public QueryBuilder asBuilder() {
+    protected QueryBuilder asBuilder() {
         final MultiMatchQueryBuilder queryBuilder = QueryBuilders.multiMatchQuery(query);
         queryBuilder.fields(fields);
         queryBuilder.analyzer(predicate.analyzer());

+ 2 - 2
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/querydsl/query/SingleValueQuery.java

@@ -65,8 +65,8 @@ public class SingleValueQuery extends Query {
     }
 
     @Override
-    public Builder asBuilder() {
-        return new Builder(next.asBuilder(), field, next.source());
+    protected Builder asBuilder() {
+        return new Builder(next.toQueryBuilder(), field, next.source());
     }
 
     @Override

+ 6 - 3
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/querydsl/query/SpatialRelatesQuery.java

@@ -46,7 +46,7 @@ public class SpatialRelatesQuery extends Query {
     }
 
     @Override
-    public QueryBuilder asBuilder() {
+    protected QueryBuilder asBuilder() {
         return DataType.isSpatialGeo(dataType) ? new GeoShapeQueryBuilder() : new CartesianShapeQueryBuilder();
     }
 
@@ -94,6 +94,8 @@ public class SpatialRelatesQuery extends Query {
      */
     public abstract class ShapeQueryBuilder implements QueryBuilder {
 
+        private float boost = 0.0f;
+
         protected void doToXContent(String queryName, XContentBuilder builder, Params params) throws IOException {
             builder.startObject();
             builder.startObject(queryName);
@@ -139,12 +141,13 @@ public class SpatialRelatesQuery extends Query {
 
         @Override
         public float boost() {
-            return 0;
+            return boost;
         }
 
         @Override
         public QueryBuilder boost(float boost) {
-            throw new UnsupportedOperationException("Unimplemented: float");
+            this.boost = boost;
+            return this;
         }
 
         @Override

+ 7 - 1
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/querydsl/query/TranslationAwareExpressionQuery.java

@@ -26,7 +26,7 @@ public class TranslationAwareExpressionQuery extends Query {
     }
 
     @Override
-    public QueryBuilder asBuilder() {
+    protected QueryBuilder asBuilder() {
         return queryBuilder;
     }
 
@@ -34,4 +34,10 @@ public class TranslationAwareExpressionQuery extends Query {
     protected String innerToString() {
         return queryBuilder.toString();
     }
+
+    @Override
+    public boolean scorable() {
+        // All Full Text Functions are translated to queries using this method
+        return true;
+    }
 }

+ 1 - 1
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/QueryBuilderResolver.java

@@ -140,7 +140,7 @@ public class QueryBuilderResolver {
             this.queryBuilderMap = new HashMap<>();
 
             for (FullTextFunction func : functions) {
-                queryBuilderMap.put(func, TRANSLATOR_HANDLER.asQuery(func).asBuilder());
+                queryBuilderMap.put(func, TRANSLATOR_HANDLER.asQuery(func).toQueryBuilder());
             }
         }
 

+ 1 - 1
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MatchErrorTests.java

@@ -40,7 +40,7 @@ public class MatchErrorTests extends ErrorsForCasesWithoutExamplesTestCase {
         // We need to add the QueryBuilder to the match expression, as it is used to implement equals() and hashCode() and
         // thus test the serialization methods. But we can only do this if the parameters make sense .
         if (args.get(0) instanceof FieldAttribute && args.get(1).foldable()) {
-            QueryBuilder queryBuilder = TRANSLATOR_HANDLER.asQuery(match).asBuilder();
+            QueryBuilder queryBuilder = TRANSLATOR_HANDLER.asQuery(match).toQueryBuilder();
             match.replaceQueryBuilder(queryBuilder);
         }
         return match;

+ 1 - 1
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MatchTests.java

@@ -80,7 +80,7 @@ public class MatchTests extends AbstractMatchFullTextFunctionTests {
         // We need to add the QueryBuilder to the match expression, as it is used to implement equals() and hashCode() and
         // thus test the serialization methods. But we can only do this if the parameters make sense .
         if (args.get(0) instanceof FieldAttribute && args.get(1).foldable()) {
-            QueryBuilder queryBuilder = TRANSLATOR_HANDLER.asQuery(match).asBuilder();
+            QueryBuilder queryBuilder = TRANSLATOR_HANDLER.asQuery(match).toQueryBuilder();
             match.replaceQueryBuilder(queryBuilder);
         }
         return match;

+ 1 - 1
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/QueryStringTests.java

@@ -79,7 +79,7 @@ public class QueryStringTests extends NoneFieldFullTextFunctionTestCase {
         // We need to add the QueryBuilder to the match expression, as it is used to implement equals() and hashCode() and
         // thus test the serialization methods. But we can only do this if the parameters make sense .
         if (args.get(0).foldable()) {
-            QueryBuilder queryBuilder = TRANSLATOR_HANDLER.asQuery(qstr).asBuilder();
+            QueryBuilder queryBuilder = TRANSLATOR_HANDLER.asQuery(qstr).toQueryBuilder();
             qstr.replaceQueryBuilder(queryBuilder);
         }
         return qstr;

+ 52 - 44
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LocalPhysicalPlanOptimizerTests.java

@@ -93,11 +93,18 @@ import java.util.function.Function;
 
 import static java.util.Arrays.asList;
 import static org.elasticsearch.compute.aggregation.AggregatorMode.FINAL;
+import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
+import static org.elasticsearch.index.query.QueryBuilders.existsQuery;
+import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
+import static org.elasticsearch.index.query.QueryBuilders.rangeQuery;
+import static org.elasticsearch.index.query.QueryBuilders.termQuery;
+import static org.elasticsearch.index.query.QueryBuilders.termsQuery;
 import static org.elasticsearch.xpack.esql.EsqlTestUtils.as;
 import static org.elasticsearch.xpack.esql.EsqlTestUtils.configuration;
 import static org.elasticsearch.xpack.esql.EsqlTestUtils.loadMapping;
 import static org.elasticsearch.xpack.esql.EsqlTestUtils.unboundLogicalOptimizerContext;
 import static org.elasticsearch.xpack.esql.EsqlTestUtils.withDefaultLimitWarning;
+import static org.elasticsearch.xpack.esql.core.querydsl.query.Query.unscore;
 import static org.elasticsearch.xpack.esql.plan.physical.EsStatsQueryExec.StatsType;
 import static org.hamcrest.Matchers.contains;
 import static org.hamcrest.Matchers.equalTo;
@@ -238,7 +245,7 @@ public class LocalPhysicalPlanOptimizerTests extends MapperServiceTestCase {
         var plan = plannerOptimizer.plan("from test | where emp_no > 10040 | stats c = count(emp_no)", IS_SV_STATS);
         var stat = queryStatsFor(plan);
         assertThat(stat.type(), is(StatsType.COUNT));
-        assertThat(stat.query(), is(QueryBuilders.existsQuery("emp_no")));
+        assertThat(stat.query(), is(existsQuery("emp_no")));
     }
 
     /**
@@ -266,7 +273,7 @@ public class LocalPhysicalPlanOptimizerTests extends MapperServiceTestCase {
         assertThat(esStatsQuery.limit(), is(nullValue()));
         assertThat(Expressions.names(esStatsQuery.output()), contains("$$c$count", "$$c$seen"));
         var stat = as(esStatsQuery.stats().get(0), Stat.class);
-        assertThat(stat.query(), is(QueryBuilders.existsQuery("salary")));
+        assertThat(stat.query(), is(existsQuery("salary")));
     }
 
     // optimized doesn't know yet how to push down count over field
@@ -288,11 +295,11 @@ public class LocalPhysicalPlanOptimizerTests extends MapperServiceTestCase {
         assertThat(Expressions.names(esStatsQuery.output()), contains("$$c$count", "$$c$seen"));
         var stat = as(esStatsQuery.stats().get(0), Stat.class);
         Source source = new Source(2, 8, "salary > 1000");
-        var exists = QueryBuilders.existsQuery("salary");
+        var exists = existsQuery("salary");
         assertThat(stat.query(), is(exists));
-        var range = wrapWithSingleQuery(query, QueryBuilders.rangeQuery("salary").gt(1000), "salary", source);
-        var expected = QueryBuilders.boolQuery().must(range).must(exists);
-        assertThat(expected.toString(), is(esStatsQuery.query().toString()));
+        var range = wrapWithSingleQuery(query, unscore(rangeQuery("salary").gt(1000)), "salary", source);
+        var expected = boolQuery().must(range).must(unscore(exists));
+        assertThat(esStatsQuery.query().toString(), is(expected.toString()));
     }
 
     // optimized doesn't know yet how to push down count over field
@@ -397,7 +404,7 @@ public class LocalPhysicalPlanOptimizerTests extends MapperServiceTestCase {
         assertThat(esStatsQuery.limit(), is(nullValue()));
         assertThat(Expressions.names(esStatsQuery.output()), contains("$$c$count", "$$c$seen"));
         var source = ((SingleValueQuery.Builder) esStatsQuery.query()).source();
-        var expected = wrapWithSingleQuery(query, QueryBuilders.rangeQuery("emp_no").gt(10010), "emp_no", source);
+        var expected = wrapWithSingleQuery(query, unscore(rangeQuery("emp_no").gt(10010)), "emp_no", source);
         assertThat(expected.toString(), is(esStatsQuery.query().toString()));
     }
 
@@ -448,7 +455,7 @@ public class LocalPhysicalPlanOptimizerTests extends MapperServiceTestCase {
                         {
                             "exists": {
                                 "field": "hire_date",
-                                "boost": 1.0
+                                "boost": 0.0
                             }
                         },
                         {
@@ -458,7 +465,7 @@ public class LocalPhysicalPlanOptimizerTests extends MapperServiceTestCase {
                                     "range": {
                                         "emp_no": {
                                             "lt": 10042,
-                                            "boost": 1.0
+                                            "boost": 0.0
                                         }
                                     }
                                 },
@@ -525,9 +532,9 @@ public class LocalPhysicalPlanOptimizerTests extends MapperServiceTestCase {
         assertThat(as(query.limit(), Literal.class).value(), is(1000));
 
         Source filterSource = new Source(2, 37, "emp_no > 10000");
-        var range = wrapWithSingleQuery(queryText, QueryBuilders.rangeQuery("emp_no").gt(10010), "emp_no", filterSource);
+        var range = wrapWithSingleQuery(queryText, unscore(rangeQuery("emp_no").gt(10010)), "emp_no", filterSource);
         var queryString = QueryBuilders.queryStringQuery("last_name: Smith");
-        var expected = QueryBuilders.boolQuery().must(queryString).must(range);
+        var expected = boolQuery().must(queryString).must(range);
         assertThat(query.query().toString(), is(expected.toString()));
     }
 
@@ -560,9 +567,9 @@ public class LocalPhysicalPlanOptimizerTests extends MapperServiceTestCase {
         assertThat(as(query.limit(), Literal.class).value(), is(1000));
 
         Source filterSource = new Source(2, 37, "cidr_match(ip, \"127.0.0.1/32\")");
-        var terms = wrapWithSingleQuery(queryText, QueryBuilders.termsQuery("ip", "127.0.0.1/32"), "ip", filterSource);
+        var terms = wrapWithSingleQuery(queryText, unscore(termsQuery("ip", "127.0.0.1/32")), "ip", filterSource);
         var queryString = QueryBuilders.queryStringQuery("last_name: Smith");
-        var expected = QueryBuilders.boolQuery().must(queryString).must(terms);
+        var expected = boolQuery().must(queryString).must(terms);
         assertThat(query.query().toString(), is(expected.toString()));
     }
 
@@ -595,9 +602,9 @@ public class LocalPhysicalPlanOptimizerTests extends MapperServiceTestCase {
         assertThat(as(query.limit(), Literal.class).value(), is(1000));
 
         Source filterSource = new Source(3, 8, "emp_no > 10000");
-        var range = wrapWithSingleQuery(queryText, QueryBuilders.rangeQuery("emp_no").gt(10010), "emp_no", filterSource);
+        var range = wrapWithSingleQuery(queryText, unscore(rangeQuery("emp_no").gt(10010)), "emp_no", filterSource);
         var queryString = QueryBuilders.queryStringQuery("last_name: Smith");
-        var expected = QueryBuilders.boolQuery().must(queryString).must(range);
+        var expected = boolQuery().must(queryString).must(range);
         assertThat(query.query().toString(), is(expected.toString()));
     }
 
@@ -629,7 +636,7 @@ public class LocalPhysicalPlanOptimizerTests extends MapperServiceTestCase {
 
         var queryStringLeft = QueryBuilders.queryStringQuery("last_name: Smith");
         var queryStringRight = QueryBuilders.queryStringQuery("emp_no: [10010 TO *]");
-        var expected = QueryBuilders.boolQuery().must(queryStringLeft).must(queryStringRight);
+        var expected = boolQuery().must(queryStringLeft).must(queryStringRight);
         assertThat(query.query().toString(), is(expected.toString()));
     }
 
@@ -686,9 +693,9 @@ public class LocalPhysicalPlanOptimizerTests extends MapperServiceTestCase {
         assertThat(as(query.limit(), Literal.class).value(), is(1000));
 
         Source filterSource = new Source(2, 38, "emp_no > 10000");
-        var range = wrapWithSingleQuery(queryText, QueryBuilders.rangeQuery("emp_no").gt(10010), "emp_no", filterSource);
+        var range = wrapWithSingleQuery(queryText, unscore(rangeQuery("emp_no").gt(10010)), "emp_no", filterSource);
         var queryString = QueryBuilders.matchQuery("last_name", "Smith").lenient(true);
-        var expected = QueryBuilders.boolQuery().must(queryString).must(range);
+        var expected = boolQuery().must(queryString).must(range);
         assertThat(query.query().toString(), is(expected.toString()));
     }
 
@@ -721,9 +728,9 @@ public class LocalPhysicalPlanOptimizerTests extends MapperServiceTestCase {
         assertThat(as(query.limit(), Literal.class).value(), is(1000));
 
         Source filterSource = new Source(2, 32, "cidr_match(ip, \"127.0.0.1/32\")");
-        var terms = wrapWithSingleQuery(queryText, QueryBuilders.termsQuery("ip", "127.0.0.1/32"), "ip", filterSource);
+        var terms = wrapWithSingleQuery(queryText, unscore(termsQuery("ip", "127.0.0.1/32")), "ip", filterSource);
         var queryString = QueryBuilders.matchQuery("text", "beta").lenient(true);
-        var expected = QueryBuilders.boolQuery().must(queryString).must(terms);
+        var expected = boolQuery().must(queryString).must(terms);
         assertThat(query.query().toString(), is(expected.toString()));
     }
 
@@ -755,9 +762,9 @@ public class LocalPhysicalPlanOptimizerTests extends MapperServiceTestCase {
         assertThat(as(query.limit(), Literal.class).value(), is(1000));
 
         Source filterSource = new Source(3, 8, "emp_no > 10000");
-        var range = wrapWithSingleQuery(queryText, QueryBuilders.rangeQuery("emp_no").gt(10010), "emp_no", filterSource);
+        var range = wrapWithSingleQuery(queryText, unscore(rangeQuery("emp_no").gt(10010)), "emp_no", filterSource);
         var queryString = QueryBuilders.matchQuery("last_name", "Smith").lenient(true);
-        var expected = QueryBuilders.boolQuery().must(queryString).must(range);
+        var expected = boolQuery().must(queryString).must(range);
         assertThat(query.query().toString(), is(expected.toString()));
     }
 
@@ -788,7 +795,7 @@ public class LocalPhysicalPlanOptimizerTests extends MapperServiceTestCase {
 
         var queryStringLeft = QueryBuilders.matchQuery("last_name", "Smith").lenient(true);
         var queryStringRight = QueryBuilders.matchQuery("first_name", "John").lenient(true);
-        var expected = QueryBuilders.boolQuery().must(queryStringLeft).must(queryStringRight);
+        var expected = boolQuery().must(queryStringLeft).must(queryStringRight);
         assertThat(query.query().toString(), is(expected.toString()));
     }
 
@@ -845,9 +852,9 @@ public class LocalPhysicalPlanOptimizerTests extends MapperServiceTestCase {
         assertThat(as(query.limit(), Literal.class).value(), is(1000));
 
         Source filterSource = new Source(2, 36, "emp_no > 10000");
-        var range = wrapWithSingleQuery(queryText, QueryBuilders.rangeQuery("emp_no").gt(10010), "emp_no", filterSource);
+        var range = wrapWithSingleQuery(queryText, unscore(rangeQuery("emp_no").gt(10010)), "emp_no", filterSource);
         var kqlQuery = kqlQueryBuilder("last_name: Smith");
-        var expected = QueryBuilders.boolQuery().must(kqlQuery).must(range);
+        var expected = boolQuery().must(kqlQuery).must(range);
         assertThat(query.query().toString(), is(expected.toString()));
     }
 
@@ -880,9 +887,9 @@ public class LocalPhysicalPlanOptimizerTests extends MapperServiceTestCase {
         assertThat(as(query.limit(), Literal.class).value(), is(1000));
 
         Source filterSource = new Source(2, 36, "cidr_match(ip, \"127.0.0.1/32\")");
-        var terms = wrapWithSingleQuery(queryText, QueryBuilders.termsQuery("ip", "127.0.0.1/32"), "ip", filterSource);
+        var terms = wrapWithSingleQuery(queryText, unscore(termsQuery("ip", "127.0.0.1/32")), "ip", filterSource);
         var kqlQuery = kqlQueryBuilder("last_name: Smith");
-        var expected = QueryBuilders.boolQuery().must(kqlQuery).must(terms);
+        var expected = boolQuery().must(kqlQuery).must(terms);
         assertThat(query.query().toString(), is(expected.toString()));
     }
 
@@ -915,9 +922,9 @@ public class LocalPhysicalPlanOptimizerTests extends MapperServiceTestCase {
         assertThat(as(query.limit(), Literal.class).value(), is(1000));
 
         Source filterSource = new Source(3, 8, "emp_no > 10000");
-        var range = wrapWithSingleQuery(queryText, QueryBuilders.rangeQuery("emp_no").gt(10010), "emp_no", filterSource);
+        var range = wrapWithSingleQuery(queryText, unscore(rangeQuery("emp_no").gt(10010)), "emp_no", filterSource);
         var kqlQuery = kqlQueryBuilder("last_name: Smith");
-        var expected = QueryBuilders.boolQuery().must(kqlQuery).must(range);
+        var expected = boolQuery().must(kqlQuery).must(range);
         assertThat(query.query().toString(), is(expected.toString()));
     }
 
@@ -949,7 +956,7 @@ public class LocalPhysicalPlanOptimizerTests extends MapperServiceTestCase {
 
         var kqlQueryLeft = kqlQueryBuilder("last_name: Smith");
         var kqlQueryRight = kqlQueryBuilder("emp_no > 10010");
-        var expected = QueryBuilders.boolQuery().must(kqlQueryLeft).must(kqlQueryRight);
+        var expected = boolQuery().must(kqlQueryLeft).must(kqlQueryRight);
         assertThat(query.query().toString(), is(expected.toString()));
     }
 
@@ -1012,7 +1019,7 @@ public class LocalPhysicalPlanOptimizerTests extends MapperServiceTestCase {
         var field = as(project.child(), FieldExtractExec.class);
         var query = as(field.child(), EsQueryExec.class);
         assertThat(as(query.limit(), Literal.class).value(), is(1000));
-        var expected = QueryBuilders.existsQuery("emp_no");
+        var expected = unscore(existsQuery("emp_no"));
         assertThat(query.query().toString(), is(expected.toString()));
     }
 
@@ -1036,7 +1043,7 @@ public class LocalPhysicalPlanOptimizerTests extends MapperServiceTestCase {
         var field = as(project.child(), FieldExtractExec.class);
         var query = as(field.child(), EsQueryExec.class);
         assertThat(as(query.limit(), Literal.class).value(), is(1000));
-        var expected = QueryBuilders.boolQuery().mustNot(QueryBuilders.existsQuery("emp_no"));
+        var expected = boolQuery().mustNot(unscore(existsQuery("emp_no")));
         assertThat(query.query().toString(), is(expected.toString()));
     }
 
@@ -1062,7 +1069,7 @@ public class LocalPhysicalPlanOptimizerTests extends MapperServiceTestCase {
         var partialAgg = as(exchange.child(), AggregateExec.class);
         var fieldExtract = as(partialAgg.child(), FieldExtractExec.class);
         var query = as(fieldExtract.child(), EsQueryExec.class);
-        var expected = QueryBuilders.existsQuery(textField);
+        var expected = unscore(existsQuery(textField));
         assertThat(query.query().toString(), is(expected.toString()));
     }
 
@@ -1085,7 +1092,7 @@ public class LocalPhysicalPlanOptimizerTests extends MapperServiceTestCase {
         var project = as(exchange.child(), ProjectExec.class);
         var fieldExtract = as(project.child(), FieldExtractExec.class);
         var query = as(fieldExtract.child(), EsQueryExec.class);
-        var expected = QueryBuilders.boolQuery().mustNot(QueryBuilders.existsQuery(textField));
+        var expected = boolQuery().mustNot(unscore(existsQuery(textField)));
         assertThat(query.query().toString(), is(expected.toString()));
     }
 
@@ -1148,7 +1155,7 @@ public class LocalPhysicalPlanOptimizerTests extends MapperServiceTestCase {
         assertThat(esStatsQuery.limit(), is(nullValue()));
         assertThat(Expressions.names(esStatsQuery.output()), contains("$$c$count", "$$c$seen"));
         var stat = as(esStatsQuery.stats().get(0), Stat.class);
-        assertThat(stat.query(), is(QueryBuilders.existsQuery("job")));
+        assertThat(stat.query(), is(existsQuery("job")));
     }
 
     private record OutOfRangeTestCase(String fieldName, String tooLow, String tooHigh) {};
@@ -1211,7 +1218,7 @@ public class LocalPhysicalPlanOptimizerTests extends MapperServiceTestCase {
                 assertThat(actualLuceneQuery.field(), equalTo(testCase.fieldName));
                 assertThat(actualLuceneQuery.source(), equalTo(expectedSource));
 
-                assertThat(actualLuceneQuery.next(), equalTo(QueryBuilders.matchAllQuery()));
+                assertThat(actualLuceneQuery.next(), equalTo(unscore(matchAllQuery())));
             }
 
             for (String falsePredicate : alwaysFalsePredicates) {
@@ -1226,7 +1233,7 @@ public class LocalPhysicalPlanOptimizerTests extends MapperServiceTestCase {
                 assertThat(actualLuceneQuery.field(), equalTo(testCase.fieldName));
                 assertThat(actualLuceneQuery.source(), equalTo(expectedSource));
 
-                var expectedInnerQuery = QueryBuilders.boolQuery().mustNot(QueryBuilders.matchAllQuery());
+                var expectedInnerQuery = unscore(boolQuery().mustNot(unscore(matchAllQuery())));
                 assertThat(actualLuceneQuery.next(), equalTo(expectedInnerQuery));
             }
         }
@@ -1262,11 +1269,12 @@ public class LocalPhysicalPlanOptimizerTests extends MapperServiceTestCase {
                     QueryBuilder actualInnerLuceneQuery = actualLuceneQuery.next();
 
                     if (predicate.equals(EQ)) {
-                        QueryBuilder expectedInnerQuery = QueryBuilders.termQuery(testCase.fieldName, Double.parseDouble(value));
+                        QueryBuilder expectedInnerQuery = unscore(termQuery(testCase.fieldName, Double.parseDouble(value)));
                         assertThat(actualInnerLuceneQuery, equalTo(expectedInnerQuery));
                     } else if (predicate.equals(NEQ)) {
-                        QueryBuilder expectedInnerQuery = QueryBuilders.boolQuery()
-                            .mustNot(QueryBuilders.termQuery(testCase.fieldName, Double.parseDouble(value)));
+                        QueryBuilder expectedInnerQuery = unscore(
+                            boolQuery().mustNot(unscore(termQuery(testCase.fieldName, Double.parseDouble(value))))
+                        );
                         assertThat(actualInnerLuceneQuery, equalTo(expectedInnerQuery));
                     } else { // one of LT, LTE, GT, GTE
                         assertTrue(actualInnerLuceneQuery instanceof RangeQueryBuilder);
@@ -1537,7 +1545,7 @@ public class LocalPhysicalPlanOptimizerTests extends MapperServiceTestCase {
         Source filterSource = new Source(4, 8, "emp_no > 10000");
         var expectedLuceneQuery = new BoolQueryBuilder().must(new MatchQueryBuilder("first_name", "Anna").lenient(true))
             .must(new MatchQueryBuilder("first_name", "Anneke").lenient(true))
-            .must(wrapWithSingleQuery(query, QueryBuilders.rangeQuery("emp_no").gt(10000), "emp_no", filterSource))
+            .must(wrapWithSingleQuery(query, unscore(rangeQuery("emp_no").gt(10000)), "emp_no", filterSource))
             .must(new MatchQueryBuilder("last_name", "Xinglin").lenient(true));
         assertThat(actualLuceneQuery.toString(), is(expectedLuceneQuery.toString()));
     }
@@ -1674,7 +1682,7 @@ public class LocalPhysicalPlanOptimizerTests extends MapperServiceTestCase {
         var field = as(project.child(), FieldExtractExec.class);
         var query = as(field.child(), EsQueryExec.class);
         assertThat(as(query.limit(), Literal.class).value(), is(1000));
-        var expected = QueryBuilders.termQuery("last_name", "Smith");
+        var expected = termQuery("last_name", "Smith");
         assertThat(query.query().toString(), is(expected.toString()));
     }
 
@@ -1737,7 +1745,7 @@ public class LocalPhysicalPlanOptimizerTests extends MapperServiceTestCase {
         var esQuery = as(fieldExtract.child(), EsQueryExec.class);
         Source source = new Source(2, 38, "salary > 10000");
         BoolQueryBuilder expected = new BoolQueryBuilder().must(new MatchQueryBuilder("last_name", "Smith").lenient(true))
-            .must(wrapWithSingleQuery(query, QueryBuilders.rangeQuery("salary").gt(10000), "salary", source));
+            .must(wrapWithSingleQuery(query, unscore(rangeQuery("salary").gt(10000)), "salary", source));
         assertThat(esQuery.query().toString(), equalTo(expected.toString()));
     }
 
@@ -1774,7 +1782,7 @@ public class LocalPhysicalPlanOptimizerTests extends MapperServiceTestCase {
         var esQuery = as(fieldExtract.child(), EsQueryExec.class);
         Source source = new Source(2, 37, "emp_no > 10");
         BoolQueryBuilder expected = new BoolQueryBuilder().should(new MatchQueryBuilder("last_name", "Smith").lenient(true))
-            .should(wrapWithSingleQuery(query, QueryBuilders.rangeQuery("emp_no").gt(10), "emp_no", source));
+            .should(wrapWithSingleQuery(query, unscore(rangeQuery("emp_no").gt(10)), "emp_no", source));
         assertThat(esQuery.query().toString(), equalTo(expected.toString()));
     }
 

+ 22 - 14
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/PhysicalPlanOptimizerTests.java

@@ -174,6 +174,7 @@ import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.defaultLoo
 import static org.elasticsearch.xpack.esql.core.expression.Expressions.name;
 import static org.elasticsearch.xpack.esql.core.expression.Expressions.names;
 import static org.elasticsearch.xpack.esql.core.expression.function.scalar.FunctionTestUtils.l;
+import static org.elasticsearch.xpack.esql.core.querydsl.query.Query.unscore;
 import static org.elasticsearch.xpack.esql.core.type.DataType.CARTESIAN_POINT;
 import static org.elasticsearch.xpack.esql.core.type.DataType.CARTESIAN_SHAPE;
 import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_POINT;
@@ -866,7 +867,7 @@ public class PhysicalPlanOptimizerTests extends ESTestCase {
 
         var query = source(extract.child());
         assertThat(query.estimatedRowSize(), equalTo(Integer.BYTES * 2 /* for doc id, emp_no*/));
-        assertThat(query.query(), is(existsQuery("emp_no")));
+        assertThat(query.query(), is(unscore(existsQuery("emp_no"))));
     }
 
     /**
@@ -901,7 +902,7 @@ public class PhysicalPlanOptimizerTests extends ESTestCase {
 
         var query = source(extract.child());
         assertThat(query.estimatedRowSize(), equalTo(Integer.BYTES * 2 /* for doc id, emp_no*/));
-        assertThat(query.query(), is(existsQuery("emp_no")));
+        assertThat(query.query(), is(unscore(existsQuery("emp_no"))));
     }
 
     public void testQueryForStatWithMultiAgg() {
@@ -922,7 +923,7 @@ public class PhysicalPlanOptimizerTests extends ESTestCase {
 
         var query = source(extract.child());
         assertThat(query.estimatedRowSize(), equalTo(Integer.BYTES * 3 /* for doc id, emp_no, salary*/));
-        assertThat(query.query(), is(boolQuery().should(existsQuery("emp_no")).should(existsQuery("salary"))));
+        assertThat(query.query(), is(boolQuery().should(unscore(existsQuery("emp_no"))).should(unscore(existsQuery("salary")))));
     }
 
     /**
@@ -1947,7 +1948,8 @@ public class PhysicalPlanOptimizerTests extends ESTestCase {
                   "term" : {
                     "first_name" : {
                       "value" : "FOO",
-                      "case_insensitive" : true
+                      "case_insensitive" : true,
+                      "boost": 0.0
                     }
                   }
                 },
@@ -1991,7 +1993,8 @@ public class PhysicalPlanOptimizerTests extends ESTestCase {
                   "term" : {
                     "first_name" : {
                       "value" : "foo",
-                      "case_insensitive" : true
+                      "case_insensitive" : true,
+                      "boost": 0.0
                     }
                   }
                 },
@@ -2015,12 +2018,13 @@ public class PhysicalPlanOptimizerTests extends ESTestCase {
                         "term" : {
                           "first_name" : {
                             "value" : "FOO",
-                            "case_insensitive" : true
+                            "case_insensitive" : true,
+                            "boost": 0.0
                           }
                         }
                       }
                     ],
-                    "boost" : 1.0
+                    "boost": 0.0
                   }
                 },
                 "source" : "to_upper(first_name) != \\"FOO\\"@2:9"
@@ -2043,12 +2047,13 @@ public class PhysicalPlanOptimizerTests extends ESTestCase {
                         "term" : {
                           "first_name" : {
                             "value" : "foo",
-                            "case_insensitive" : true
+                            "case_insensitive" : true,
+                            "boost": 0.0
                           }
                         }
                       }
                     ],
-                    "boost" : 1.0
+                    "boost" : 0.0
                   }
                 },
                 "source" : "to_lower(first_name) != \\"foo\\"@2:9"
@@ -2074,12 +2079,13 @@ public class PhysicalPlanOptimizerTests extends ESTestCase {
                               "term" : {
                                 "first_name" : {
                                   "value" : "foo",
-                                  "case_insensitive" : true
+                                  "case_insensitive" : true,
+                                  "boost": 0.0
                                 }
                               }
                             }
                           ],
-                          "boost" : 1.0
+                          "boost": 0.0
                         }
                       },
                       "source" : "to_lower(first_name) != \\"foo\\"@2:9"
@@ -2092,7 +2098,8 @@ public class PhysicalPlanOptimizerTests extends ESTestCase {
                         "term" : {
                           "first_name" : {
                             "value" : "FOO",
-                            "case_insensitive" : true
+                            "case_insensitive" : true,
+                            "boost": 0.0
                           }
                         }
                       },
@@ -2106,7 +2113,7 @@ public class PhysicalPlanOptimizerTests extends ESTestCase {
                         "range" : {
                           "emp_no" : {
                             "gt" : 10,
-                            "boost" : 1.0
+                            "boost" : 0.0
                           }
                         }
                       },
@@ -2144,7 +2151,8 @@ public class PhysicalPlanOptimizerTests extends ESTestCase {
                   "term" : {
                     "first_name" : {
                       "value" : "foo",
-                      "case_insensitive" : true
+                      "case_insensitive" : true,
+                      "boost" : 0.0
                     }
                   }
                 },

+ 46 - 10
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/FilterTests.java

@@ -54,6 +54,7 @@ import static org.elasticsearch.xpack.esql.EsqlTestUtils.loadMapping;
 import static org.elasticsearch.xpack.esql.EsqlTestUtils.unboundLogicalOptimizerContext;
 import static org.elasticsearch.xpack.esql.EsqlTestUtils.withDefaultLimitWarning;
 import static org.elasticsearch.xpack.esql.SerializationTestUtils.assertSerialization;
+import static org.elasticsearch.xpack.esql.core.querydsl.query.Query.unscore;
 import static org.elasticsearch.xpack.esql.core.util.Queries.Clause.FILTER;
 import static org.elasticsearch.xpack.esql.core.util.Queries.Clause.MUST;
 import static org.elasticsearch.xpack.esql.core.util.Queries.Clause.SHOULD;
@@ -110,7 +111,7 @@ public class FilterTests extends ESTestCase {
         var plan = plan(query, null);
 
         var filter = filterQueryForTransportNodes(plan);
-        var expected = singleValueQuery(query, rangeQuery(EMP_NO).gt(value), EMP_NO, ((SingleValueQuery.Builder) filter).source());
+        var expected = singleValueQuery(query, unscore(rangeQuery(EMP_NO).gt(value)), EMP_NO, ((SingleValueQuery.Builder) filter).source());
         assertEquals(expected.toString(), filter.toString());
     }
 
@@ -128,7 +129,7 @@ public class FilterTests extends ESTestCase {
         var builder = ((BoolQueryBuilder) filter).filter().get(1);
         var queryFilter = singleValueQuery(
             query,
-            rangeQuery(EMP_NO).gt(value).includeUpper(false),
+            unscore(rangeQuery(EMP_NO).gt(value).includeUpper(false)),
             EMP_NO,
             ((SingleValueQuery.Builder) builder).source()
         );
@@ -149,8 +150,18 @@ public class FilterTests extends ESTestCase {
 
         var filter = filterQueryForTransportNodes(plan);
         var musts = ((BoolQueryBuilder) ((BoolQueryBuilder) filter).filter().get(1)).must();
-        var left = singleValueQuery(query, rangeQuery(EMP_NO).gt(lowValue), EMP_NO, ((SingleValueQuery.Builder) musts.get(0)).source());
-        var right = singleValueQuery(query, rangeQuery(EMP_NO).lt(highValue), EMP_NO, ((SingleValueQuery.Builder) musts.get(1)).source());
+        var left = singleValueQuery(
+            query,
+            unscore(rangeQuery(EMP_NO).gt(lowValue)),
+            EMP_NO,
+            ((SingleValueQuery.Builder) musts.get(0)).source()
+        );
+        var right = singleValueQuery(
+            query,
+            unscore(rangeQuery(EMP_NO).lt(highValue)),
+            EMP_NO,
+            ((SingleValueQuery.Builder) musts.get(1)).source()
+        );
         var must = Queries.combine(MUST, asList(left, right));
         var expected = Queries.combine(FILTER, asList(restFilter, must));
         assertEquals(expected.toString(), filter.toString());
@@ -184,8 +195,18 @@ public class FilterTests extends ESTestCase {
 
         var filter = filterQueryForTransportNodes(plan);
         var shoulds = ((BoolQueryBuilder) ((BoolQueryBuilder) filter).filter().get(1)).should();
-        var left = singleValueQuery(query, rangeQuery(EMP_NO).gt(lowValue), EMP_NO, ((SingleValueQuery.Builder) shoulds.get(0)).source());
-        var right = singleValueQuery(query, rangeQuery(EMP_NO).lt(highValue), EMP_NO, ((SingleValueQuery.Builder) shoulds.get(1)).source());
+        var left = singleValueQuery(
+            query,
+            unscore(rangeQuery(EMP_NO).gt(lowValue)),
+            EMP_NO,
+            ((SingleValueQuery.Builder) shoulds.get(0)).source()
+        );
+        var right = singleValueQuery(
+            query,
+            unscore(rangeQuery(EMP_NO).lt(highValue)),
+            EMP_NO,
+            ((SingleValueQuery.Builder) shoulds.get(1)).source()
+        );
         var should = Queries.combine(SHOULD, asList(left, right));
         var expected = Queries.combine(FILTER, asList(restFilter, should));
         assertEquals(expected.toString(), filter.toString());
@@ -205,8 +226,18 @@ public class FilterTests extends ESTestCase {
 
         var filter = filterQueryForTransportNodes(plan);
         var musts = ((BoolQueryBuilder) ((BoolQueryBuilder) filter).filter().get(1)).must();
-        var left = singleValueQuery(query, rangeQuery(EMP_NO).gt(lowValue), EMP_NO, ((SingleValueQuery.Builder) musts.get(0)).source());
-        var right = singleValueQuery(query, rangeQuery(EMP_NO).lt(highValue), EMP_NO, ((SingleValueQuery.Builder) musts.get(1)).source());
+        var left = singleValueQuery(
+            query,
+            unscore(rangeQuery(EMP_NO).gt(lowValue)),
+            EMP_NO,
+            ((SingleValueQuery.Builder) musts.get(0)).source()
+        );
+        var right = singleValueQuery(
+            query,
+            unscore(rangeQuery(EMP_NO).lt(highValue)),
+            EMP_NO,
+            ((SingleValueQuery.Builder) musts.get(1)).source()
+        );
         var must = Queries.combine(MUST, asList(left, right));
         var expected = Queries.combine(FILTER, asList(restFilter, must));
         assertEquals(expected.toString(), filter.toString());
@@ -229,7 +260,12 @@ public class FilterTests extends ESTestCase {
 
         var filter = filterQueryForTransportNodes(plan);
         var builder = ((BoolQueryBuilder) filter).filter().get(1);
-        var queryFilter = singleValueQuery(query, rangeQuery(EMP_NO).gt(lowValue), EMP_NO, ((SingleValueQuery.Builder) builder).source());
+        var queryFilter = singleValueQuery(
+            query,
+            unscore(rangeQuery(EMP_NO).gt(lowValue)),
+            EMP_NO,
+            ((SingleValueQuery.Builder) builder).source()
+        );
         var expected = Queries.combine(FILTER, asList(restFilter, queryFilter));
         assertEquals(expected.toString(), filter.toString());
     }
@@ -314,7 +350,7 @@ public class FilterTests extends ESTestCase {
     }
 
     private QueryBuilder restFilterQuery(String field) {
-        return rangeQuery(field).lt("2020-12-34");
+        return unscore(rangeQuery(field).lt("2020-12-34"));
     }
 
     private QueryBuilder filterQueryForTransportNodes(PhysicalPlan plan) {

+ 8 - 8
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/QueryTranslatorTests.java

@@ -99,11 +99,11 @@ public class QueryTranslatorTests extends ESTestCase {
 
         assertQueryTranslation("""
             FROM test | WHERE "1.2.3" == version""", containsString("""
-            "esql_single_value":{"field":"version","next":{"term":{"version":{"value":"1.2.3"}"""));
+            "esql_single_value":{"field":"version","next":{"term":{"version":{"value":"1.2.3","boost":0.0}"""));
 
         assertQueryTranslation("""
             FROM test | WHERE "foo" == keyword""", containsString("""
-            "esql_single_value":{"field":"keyword","next":{"term":{"keyword":{"value":"foo"}"""));
+            "esql_single_value":{"field":"keyword","next":{"term":{"keyword":{"value":"foo","boost":0.0}"""));
 
         assertQueryTranslation("""
             FROM test | WHERE "2007-12-03T10:15:30+01:00" == date""", containsString("""
@@ -111,7 +111,7 @@ public class QueryTranslatorTests extends ESTestCase {
 
         assertQueryTranslation("""
             FROM test | WHERE ip != "127.0.0.1\"""", containsString("""
-            "esql_single_value":{"field":"ip","next":{"bool":{"must_not":[{"term":{"ip":{"value":"127.0.0.1"}"""));
+            "esql_single_value":{"field":"ip","next":{"bool":{"must_not":[{"term":{"ip":{"value":"127.0.0.1","boost":0.0}}"""));
     }
 
     public void testRanges() {
@@ -195,28 +195,28 @@ public class QueryTranslatorTests extends ESTestCase {
         assertQueryTranslation("""
             FROM test | WHERE "2007-12-03T10:15:30Z" <= date AND date <= "2024-01-01T10:15:30\"""", containsString("""
             "esql_single_value":{"field":"date","next":{"range":{"date":{"gte":"2007-12-03T10:15:30.000Z","lte":"2024-01-01T10:15:30.000Z",\
-            "time_zone":"Z","format":"strict_date_optional_time","boost":1.0}}}"""));
+            "time_zone":"Z","format":"strict_date_optional_time","boost":0.0}}}"""));
 
         assertQueryTranslation("""
             FROM test | WHERE "2007-12-03T10:15:30" <= date AND date <= "2024-01-01T10:15:30Z\"""", containsString("""
             "esql_single_value":{"field":"date","next":{"range":{"date":{"gte":"2007-12-03T10:15:30.000Z","lte":"2024-01-01T10:15:30.000Z",\
-            "time_zone":"Z","format":"strict_date_optional_time","boost":1.0}}}"""));
+            "time_zone":"Z","format":"strict_date_optional_time","boost":0.0}}}"""));
 
         // various timezones
         assertQueryTranslation("""
             FROM test | WHERE "2007-12-03T10:15:30+01:00" < date AND date < "2024-01-01T10:15:30+01:00\"""", containsString("""
             "esql_single_value":{"field":"date","next":{"range":{"date":{"gt":"2007-12-03T09:15:30.000Z","lt":"2024-01-01T09:15:30.000Z",\
-            "time_zone":"Z","format":"strict_date_optional_time","boost":1.0}}}"""));
+            "time_zone":"Z","format":"strict_date_optional_time","boost":0.0}}}"""));
 
         assertQueryTranslation("""
             FROM test | WHERE "2007-12-03T10:15:30-01:00" <= date AND date <= "2024-01-01T10:15:30+01:00\"""", containsString("""
             "esql_single_value":{"field":"date","next":{"range":{"date":{"gte":"2007-12-03T11:15:30.000Z","lte":"2024-01-01T09:15:30.000Z",\
-            "time_zone":"Z","format":"strict_date_optional_time","boost":1.0}}}"""));
+            "time_zone":"Z","format":"strict_date_optional_time","boost":0.0}}}"""));
 
         assertQueryTranslation("""
             FROM test | WHERE "2007-12-03T10:15:30" <= date AND date <= "2024-01-01T10:15:30+01:00\"""", containsString("""
             "esql_single_value":{"field":"date","next":{"range":{"date":{"gte":"2007-12-03T10:15:30.000Z","lte":"2024-01-01T09:15:30.000Z",\
-            "time_zone":"Z","format":"strict_date_optional_time","boost":1.0}}}"""));
+            "time_zone":"Z","format":"strict_date_optional_time","boost":0.0}}}"""));
     }
 
     public void testIPs() {

+ 1 - 1
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/querydsl/query/QueryStringQueryTests.java

@@ -39,7 +39,7 @@ public class QueryStringQueryTests extends ESTestCase {
     private static QueryStringQueryBuilder getBuilder(Map<String, Object> options) {
         final Source source = new Source(1, 1, StringUtils.EMPTY);
         final QueryStringQuery query = new QueryStringQuery(source, "eggplant", Collections.singletonMap("foo", 1.0f), options);
-        return (QueryStringQueryBuilder) query.asBuilder();
+        return (QueryStringQueryBuilder) query.toQueryBuilder();
     }
 
     public void testToString() {