Skip to content

Commit 5a0c79a

Browse files
authored
Allow match field in enrich fields (#102734) (#103082)
It's perfectly fine for the match field of an enrich policy to be included in the enrich fields. However ESQL enrich consistently fails on such an enrich policy because it mistakenly excludes the match field from the enrich mapping during resolution.
1 parent bdd2b42 commit 5a0c79a

File tree

3 files changed

+37
-2
lines changed

3 files changed

+37
-2
lines changed

docs/changelog/102734.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 102734
2+
summary: Allow match field in enrich fields
3+
area: ES|QL
4+
type: bug
5+
issues: []

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -256,8 +256,10 @@ public static List<NamedExpression> calculateEnrichFields(
256256
List<NamedExpression> enrichFields,
257257
EnrichPolicy policy
258258
) {
259-
Map<String, Attribute> fieldMap = mapping.stream().collect(Collectors.toMap(NamedExpression::name, Function.identity()));
260-
fieldMap.remove(policy.getMatchField());
259+
Set<String> policyEnrichFieldSet = new HashSet<>(policy.getEnrichFields());
260+
Map<String, Attribute> fieldMap = mapping.stream()
261+
.filter(e -> policyEnrichFieldSet.contains(e.name()))
262+
.collect(Collectors.toMap(NamedExpression::name, Function.identity()));
261263
List<NamedExpression> result = new ArrayList<>();
262264
if (enrichFields == null || enrichFields.isEmpty()) {
263265
// use the policy to infer the enrich fields

x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTests.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99

1010
import org.elasticsearch.common.settings.Settings;
1111
import org.elasticsearch.test.ESTestCase;
12+
import org.elasticsearch.xpack.core.enrich.EnrichPolicy;
13+
import org.elasticsearch.xpack.esql.enrich.EnrichPolicyResolution;
14+
import org.elasticsearch.xpack.esql.expression.function.EsqlFunctionRegistry;
1215
import org.elasticsearch.xpack.esql.expression.function.aggregate.Max;
1316
import org.elasticsearch.xpack.esql.plan.logical.EsqlUnresolvedRelation;
1417
import org.elasticsearch.xpack.esql.plan.logical.Eval;
@@ -29,16 +32,20 @@
2932
import org.elasticsearch.xpack.ql.plan.logical.EsRelation;
3033
import org.elasticsearch.xpack.ql.plan.logical.Filter;
3134
import org.elasticsearch.xpack.ql.plan.logical.Limit;
35+
import org.elasticsearch.xpack.ql.plan.logical.LogicalPlan;
3236
import org.elasticsearch.xpack.ql.plan.logical.OrderBy;
3337
import org.elasticsearch.xpack.ql.type.DataType;
3438
import org.elasticsearch.xpack.ql.type.DataTypes;
3539
import org.elasticsearch.xpack.ql.type.TypesTests;
3640

3741
import java.util.List;
3842
import java.util.Map;
43+
import java.util.Set;
3944
import java.util.stream.IntStream;
4045

46+
import static org.elasticsearch.xpack.esql.EsqlTestUtils.TEST_VERIFIER;
4147
import static org.elasticsearch.xpack.esql.EsqlTestUtils.as;
48+
import static org.elasticsearch.xpack.esql.EsqlTestUtils.configuration;
4249
import static org.elasticsearch.xpack.esql.EsqlTestUtils.withDefaultLimitWarning;
4350
import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.analyze;
4451
import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.analyzer;
@@ -1311,6 +1318,27 @@ public void testEnrichExcludesPolicyKey() {
13111318
assertThat(e.getMessage(), containsString("Unknown column [id]"));
13121319
}
13131320

1321+
public void testEnrichFieldsIncludeMatchField() {
1322+
String query = """
1323+
FROM test
1324+
| EVAL x = to_string(languages)
1325+
| ENRICH languages ON x
1326+
| KEEP language_name, language_code
1327+
""";
1328+
IndexResolution testIndex = loadMapping("mapping-basic.json", "test");
1329+
IndexResolution languageIndex = loadMapping("mapping-languages.json", "languages");
1330+
var enrichPolicy = new EnrichPolicy("match", null, List.of("unused"), "language_code", List.of("language_code", "language_name"));
1331+
EnrichResolution enrichResolution = new EnrichResolution(
1332+
Set.of(new EnrichPolicyResolution("languages", enrichPolicy, languageIndex)),
1333+
Set.of("languages")
1334+
);
1335+
AnalyzerContext context = new AnalyzerContext(configuration(query), new EsqlFunctionRegistry(), testIndex, enrichResolution);
1336+
Analyzer analyzer = new Analyzer(context, TEST_VERIFIER);
1337+
LogicalPlan plan = analyze(query, analyzer);
1338+
var limit = as(plan, Limit.class);
1339+
assertThat(Expressions.names(limit.output()), contains("language_name", "language_code"));
1340+
}
1341+
13141342
public void testChainedEvalFieldsUse() {
13151343
var query = "from test | eval x0 = pow(salary, 1), x1 = pow(x0, 2), x2 = pow(x1, 3)";
13161344
int additionalEvals = randomIntBetween(0, 5);

0 commit comments

Comments
 (0)