-
Notifications
You must be signed in to change notification settings - Fork 25.6k
Initial support for TEXT fields in LOOKUP JOIN condition #119473
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
Changes from 7 commits
a4f3b5e
c1744c9
8eb6554
69572e5
417d3df
e799ef9
772659d
93779f9
cbcd532
0146742
e327808
77fc5bf
2b2f0dc
4380656
6a56279
3491006
d5d7cee
879ecd4
724153c
863cfc9
26a76f9
f0ce28a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -55,9 +55,11 @@ | |||||
| import org.elasticsearch.xpack.esql.core.expression.Attribute; | ||||||
| import org.elasticsearch.xpack.esql.core.expression.Expression; | ||||||
| import org.elasticsearch.xpack.esql.core.expression.Expressions; | ||||||
| import org.elasticsearch.xpack.esql.core.expression.FieldAttribute; | ||||||
| import org.elasticsearch.xpack.esql.core.expression.Literal; | ||||||
| import org.elasticsearch.xpack.esql.core.expression.NameId; | ||||||
| import org.elasticsearch.xpack.esql.core.expression.NamedExpression; | ||||||
| import org.elasticsearch.xpack.esql.core.expression.TypedAttribute; | ||||||
| import org.elasticsearch.xpack.esql.core.tree.Source; | ||||||
| import org.elasticsearch.xpack.esql.core.type.DataType; | ||||||
| import org.elasticsearch.xpack.esql.core.util.Holder; | ||||||
|
|
@@ -570,35 +572,49 @@ private PhysicalOperation planLookupJoin(LookupJoinExec join, LocalExecutionPlan | |||||
| throw new IllegalArgumentException("can't plan [" + join + "], found index with mode [" + entry.getValue() + "]"); | ||||||
| } | ||||||
| String indexName = entry.getKey(); | ||||||
| List<Layout.ChannelAndType> matchFields = new ArrayList<>(join.leftFields().size()); | ||||||
| for (Attribute m : join.leftFields()) { | ||||||
| Layout.ChannelAndType t = source.layout.get(m.id()); | ||||||
| if (t == null) { | ||||||
| throw new IllegalArgumentException("can't plan [" + join + "][" + m + "]"); | ||||||
| if (join.leftFields().size() != join.rightFields().size()) { | ||||||
| throw new IllegalArgumentException("can't plan [" + join + "]: mismatching left and right field count"); | ||||||
| } | ||||||
| List<MatchConfig> matchFields = new ArrayList<>(join.leftFields().size()); | ||||||
| for (int i = 0; i < join.leftFields().size(); i++) { | ||||||
| TypedAttribute left = (TypedAttribute) join.leftFields().get(i); | ||||||
| FieldAttribute right = (FieldAttribute) join.rightFields().get(i); | ||||||
| Layout.ChannelAndType input = source.layout.get(left.id()); | ||||||
| if (input == null) { | ||||||
| throw new IllegalArgumentException("can't plan [" + join + "][" + left + "]"); | ||||||
| } | ||||||
| matchFields.add(t); | ||||||
| matchFields.add(new MatchConfig(right, input)); | ||||||
| } | ||||||
| if (matchFields.size() != 1) { | ||||||
| throw new IllegalArgumentException("can't plan [" + join + "]"); | ||||||
| throw new IllegalArgumentException("can't plan [" + join + "]: multiple join predicates are not supported"); | ||||||
| } | ||||||
| // TODO support multiple match fields, and support more than equality predicates | ||||||
| MatchConfig matchConfig = matchFields.getFirst(); | ||||||
|
|
||||||
| return source.with( | ||||||
| new LookupFromIndexOperator.Factory( | ||||||
| sessionId, | ||||||
| parentTask, | ||||||
| context.queryPragmas().enrichMaxWorkers(), | ||||||
| matchFields.getFirst().channel(), | ||||||
| matchConfig.channel(), | ||||||
| lookupFromIndexService, | ||||||
| matchFields.getFirst().type(), | ||||||
| matchConfig.type(), | ||||||
| indexName, | ||||||
| join.leftFields().getFirst().name(), | ||||||
| matchConfig.fieldName(), | ||||||
| join.addedFields().stream().map(f -> (NamedExpression) f).toList(), | ||||||
| join.source() | ||||||
| ), | ||||||
| layout | ||||||
| ); | ||||||
| } | ||||||
|
|
||||||
| private record MatchConfig(String fieldName, int channel, DataType type) { | ||||||
| private MatchConfig(FieldAttribute match, Layout.ChannelAndType input) { | ||||||
| // Note, this handles TEXT fields with KEYWORD subfields, and we assume tha has been validated earlier during planning | ||||||
|
||||||
| // Note, this handles TEXT fields with KEYWORD subfields, and we assume tha has been validated earlier during planning | |
| // Note, this handles TEXT field with KEYWORD subfields, and we assume that has been validated earlier during planning |
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.
Could you please clarify "validated" means here? Is it existance of the nested .keyword field? If so could you please help me understand where such validation is happening?
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.
The PR is still in draft, but I planned to find that location and add such validation myself. It does not yet exist.
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.
I wonder if it is worth resolving
typeNamewirhfromTypeNamehere to avoid comparing strings?Something like
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.
I'm actually thinking of deleting this method entirely, since it is shadowed by the newer validation happening in the Validator. In the current draft I fixed both methods, but in reality we only need the one.