Skip to content

Commit 8d93564

Browse files
committed
Test and javadoc
1 parent ec77a9f commit 8d93564

File tree

2 files changed

+47
-5
lines changed
  • x-pack/plugin/esql

2 files changed

+47
-5
lines changed

x-pack/plugin/esql/qa/server/single-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/PushQueriesIT.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public void testPushEqualityOnDefaults() throws IOException {
5353
testPushQuery(value, """
5454
FROM test
5555
| WHERE test == "%value"
56-
""", "*:*", true, true);
56+
""", "#test.keyword:%value -_ignored:test.keyword", false, true);
5757
}
5858

5959
public void testPushEqualityOnDefaultsTooBigToPush() throws IOException {
@@ -69,7 +69,7 @@ public void testPushInequalityOnDefaults() throws IOException {
6969
testPushQuery(value, """
7070
FROM test
7171
| WHERE test != "%different_value"
72-
""", "*:*", true, true);
72+
""", "(-test.keyword:%different_value #*:*) _ignored:test.keyword", true, true);
7373
}
7474

7575
public void testPushInequalityOnDefaultsTooBigToPush() throws IOException {

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/capabilities/TranslationAware.java

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,28 @@
77

88
package org.elasticsearch.xpack.esql.capabilities;
99

10+
import org.elasticsearch.compute.lucene.LuceneTopNSourceOperator;
11+
import org.elasticsearch.compute.operator.FilterOperator;
1012
import org.elasticsearch.xpack.esql.core.expression.Expression;
1113
import org.elasticsearch.xpack.esql.core.querydsl.query.Query;
1214
import org.elasticsearch.xpack.esql.optimizer.rules.physical.local.LucenePushdownPredicates;
1315
import org.elasticsearch.xpack.esql.planner.TranslatorHandler;
1416

1517
/**
16-
* Expressions implementing this interface can get called on data nodes to provide an Elasticsearch/Lucene query.
18+
* Expressions implementing this interface are asked provide an
19+
* Elasticsearch/Lucene query on the as part of the data node optimizations.
1720
*/
1821
public interface TranslationAware {
1922
/**
20-
* Indicates whether the expression can be translated or not.
21-
* Usually checks whether the expression arguments are actual fields that exist in Lucene.
23+
* Can this instance be translated or not? Usually checks whether the
24+
* expression arguments are actual fields that exist in Lucene. See {@link Translatable}
25+
* for precisely what can be signaled from this method.
2226
*/
2327
Translatable translatable(LucenePushdownPredicates pushdownPredicates);
2428

29+
/**
30+
* Is an {@link Expression} translatable?
31+
*/
2532
static TranslationAware.Translatable translatable(Expression exp, LucenePushdownPredicates lucenePushdownPredicates) {
2633
if (exp instanceof TranslationAware aware) {
2734
return aware.translatable(lucenePushdownPredicates);
@@ -50,9 +57,44 @@ interface SingleValueTranslationAware extends TranslationAware {
5057
Expression singleValueField();
5158
}
5259

60+
/**
61+
* How is this expression translatable?
62+
*/
5363
enum Translatable {
64+
/**
65+
* Not translatable at all. Calling {@link TranslationAware#asQuery} is an error.
66+
* The expression will stay in the query plan and be filtered via a {@link FilterOperator}.
67+
* Imagine {@code kwd == "a"} when {@code kwd} is configured without a search index.
68+
*/
5469
NO(FinishedTranslatable.NO),
70+
/**
71+
* Entirely translatable into a lucene query. Calling {@link TranslationAware#asQuery}
72+
* will produce a query that matches all documents matching this expression and
73+
* <strong>only</strong> documents matching this expression. Imagine {@code kwd == "a"}
74+
* when {@code kwd} has a search index and doc values - which is the
75+
* default configuration. This will entirely remove the clause from the
76+
* {@code WHERE}, removing the entire {@link FilterOperator} if it's empty. Sometimes
77+
* this allows us to push the entire top-n operation to lucene with
78+
* a {@link LuceneTopNSourceOperator}.
79+
*/
5580
YES(FinishedTranslatable.YES),
81+
/**
82+
* Translation requires a recheck. Calling {@link TranslationAware#asQuery} will
83+
* produce a query that matches all documents matching this expression but might
84+
* match more documents that do not match the expression. This will cause us to
85+
* push a query to lucene <strong>and</strong> keep the query in the query plan,
86+
* rechecking it via a {@link FilterOperator}. This can never push the entire
87+
* top-n to Lucene, but it's still quite a lot better than the full scan from
88+
* {@link #NO}.
89+
* <p>
90+
* Imagine {@code kwd == "a"} where {@code kwd} has a search index but doesn't
91+
* have doc values. In that case we can find candidate matches in lucene but
92+
* can't tell if those docs are single-valued. If they are multivalued they'll
93+
* still match the query but won't match the expression. Thus, the double-checking.
94+
* <strong>Technically</strong> we could just check for single-valued-ness in
95+
* this case, but it's simpler to
96+
* </p>
97+
*/
5698
RECHECK(FinishedTranslatable.RECHECK),
5799
YES_BUT_RECHECK_NEGATED(FinishedTranslatable.YES);
58100

0 commit comments

Comments
 (0)