-
Notifications
You must be signed in to change notification settings - Fork 25.6k
ES|QL: Enable semantic search in FORK #125960
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,8 +12,10 @@ | |
| import org.elasticsearch.index.query.QueryBuilder; | ||
| import org.elasticsearch.index.query.QueryRewriteContext; | ||
| import org.elasticsearch.index.query.Rewriteable; | ||
| import org.elasticsearch.xpack.esql.core.expression.Expression; | ||
| import org.elasticsearch.xpack.esql.core.util.Holder; | ||
| import org.elasticsearch.xpack.esql.plan.logical.EsRelation; | ||
| import org.elasticsearch.xpack.esql.plan.logical.Fork; | ||
| import org.elasticsearch.xpack.esql.plan.logical.LogicalPlan; | ||
| import org.elasticsearch.xpack.esql.planner.TranslatorHandler; | ||
| import org.elasticsearch.xpack.esql.plugin.TransportActionServices; | ||
|
|
@@ -22,6 +24,8 @@ | |
| import java.io.IOException; | ||
| import java.util.HashSet; | ||
| import java.util.Set; | ||
| import java.util.function.Function; | ||
| import java.util.stream.Collectors; | ||
|
|
||
| /** | ||
| * Some {@link FullTextFunction} implementations such as {@link org.elasticsearch.xpack.esql.expression.function.fulltext.Match} | ||
|
|
@@ -34,11 +38,7 @@ public final class QueryBuilderResolver { | |
| private QueryBuilderResolver() {} | ||
|
|
||
| public static void resolveQueryBuilders(LogicalPlan plan, TransportActionServices services, ActionListener<LogicalPlan> listener) { | ||
| var hasFullTextFunctions = plan.anyMatch(p -> { | ||
| Holder<Boolean> hasFullTextFunction = new Holder<>(false); | ||
| p.forEachExpression(FullTextFunction.class, unused -> hasFullTextFunction.set(true)); | ||
| return hasFullTextFunction.get(); | ||
| }); | ||
| var hasFullTextFunctions = hasFullTextFunctions(plan); | ||
| if (hasFullTextFunctions) { | ||
| Rewriteable.rewriteAndFetch( | ||
| new FullTextFunctionsRewritable(plan), | ||
|
|
@@ -69,12 +69,29 @@ private static Set<String> indexNames(LogicalPlan plan) { | |
| return indexNames; | ||
| } | ||
|
|
||
| private static boolean hasFullTextFunctions(LogicalPlan plan) { | ||
| return plan.anyMatch(p -> { | ||
| Holder<Boolean> hasFullTextFunction = new Holder<>(false); | ||
| p.forEachExpression(FullTextFunction.class, unused -> hasFullTextFunction.set(true)); | ||
|
|
||
| if (p instanceof Fork fork) { | ||
| fork.subPlans().forEach(subPlan -> { | ||
| if (hasFullTextFunctions(subPlan)) { | ||
| hasFullTextFunction.set(true); | ||
| } | ||
| }); | ||
| } | ||
|
|
||
| return hasFullTextFunction.get(); | ||
| }); | ||
| } | ||
|
|
||
| private record FullTextFunctionsRewritable(LogicalPlan plan) implements Rewriteable<QueryBuilderResolver.FullTextFunctionsRewritable> { | ||
| @Override | ||
| public FullTextFunctionsRewritable rewrite(QueryRewriteContext ctx) throws IOException { | ||
| Holder<IOException> exceptionHolder = new Holder<>(); | ||
| Holder<Boolean> updated = new Holder<>(false); | ||
| LogicalPlan newPlan = plan.transformExpressionsDown(FullTextFunction.class, f -> { | ||
| LogicalPlan newPlan = transformPlan(plan, f -> { | ||
| QueryBuilder builder = f.queryBuilder(), initial = builder; | ||
| builder = builder == null ? f.asQuery(TranslatorHandler.TRANSLATOR_HANDLER).toQueryBuilder() : builder; | ||
| try { | ||
|
|
@@ -91,5 +108,15 @@ public FullTextFunctionsRewritable rewrite(QueryRewriteContext ctx) throws IOExc | |
| } | ||
| return updated.get() ? new FullTextFunctionsRewritable(newPlan) : this; | ||
| } | ||
|
|
||
| private LogicalPlan transformPlan(LogicalPlan plan, Function<FullTextFunction, ? extends Expression> rule) { | ||
| return plan.transformExpressionsDown(FullTextFunction.class, rule).transformDown(Fork.class, fork -> { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here, we may override |
||
| var subPlans = fork.subPlans() | ||
| .stream() | ||
| .map(subPlan -> subPlan.transformExpressionsDown(FullTextFunction.class, rule)) | ||
| .collect(Collectors.toList()); | ||
| return new Fork(fork.source(), fork.child(), subPlans); | ||
| }); | ||
| } | ||
| } | ||
| } | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should
ForkimplementforEachExpressioninstead? That would make things easier for the clients that will not need to take it into account, and be in line with theCompositepattern...Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No,
Forkshould not implementforEachExpression.There is a slippery slope if we decide to do that since in the future we might decide we need to implement
anyMatch,forEachExpressionUp,forEachExpressionDownetc and that's not what we want.We either treat
Forkas the outlier it currently is (because we have nothing like it in ES|QL atm) or we go back and makeForka n-ary plan (it is currently aUnaryPlan).If
Forksub plans are treated as children then we would most likely not need to make any big changes toQueryBuilderResolver.While it sound good in theory to just make
Forka n-ary plan, we tried this already when we did the POC and found out it has its own set of challenges.So for now I am focusing on getting
Forkto work as it should even if it means having this special handling in a couple of places.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you already went down that route, that's enough to me 😅