From fd3051c6c36e21a32238b8d25d65cf2af0ccf2c0 Mon Sep 17 00:00:00 2001 From: Parker Timmins Date: Fri, 18 Jul 2025 18:37:17 -0500 Subject: [PATCH 1/7] Initial work on adding multi-field for all string type fields --- .../datageneration/FieldType.java | 10 ++- .../DefaultMappingParametersHandler.java | 83 +++++++++++++++---- .../leaf/MatchOnlyTextFieldDataGenerator.java | 28 +++++++ .../leaf/PatternedTextFieldDataGenerator.java | 28 +++++++ 4 files changed, 134 insertions(+), 15 deletions(-) create mode 100644 test/framework/src/main/java/org/elasticsearch/datageneration/fields/leaf/MatchOnlyTextFieldDataGenerator.java create mode 100644 test/framework/src/main/java/org/elasticsearch/datageneration/fields/leaf/PatternedTextFieldDataGenerator.java diff --git a/test/framework/src/main/java/org/elasticsearch/datageneration/FieldType.java b/test/framework/src/main/java/org/elasticsearch/datageneration/FieldType.java index eab2149019204..4052299d79f85 100644 --- a/test/framework/src/main/java/org/elasticsearch/datageneration/FieldType.java +++ b/test/framework/src/main/java/org/elasticsearch/datageneration/FieldType.java @@ -23,6 +23,8 @@ import org.elasticsearch.datageneration.fields.leaf.IpFieldDataGenerator; import org.elasticsearch.datageneration.fields.leaf.KeywordFieldDataGenerator; import org.elasticsearch.datageneration.fields.leaf.LongFieldDataGenerator; +import org.elasticsearch.datageneration.fields.leaf.MatchOnlyTextFieldDataGenerator; +import org.elasticsearch.datageneration.fields.leaf.PatternedTextFieldDataGenerator; import org.elasticsearch.datageneration.fields.leaf.ScaledFloatFieldDataGenerator; import org.elasticsearch.datageneration.fields.leaf.ShortFieldDataGenerator; import org.elasticsearch.datageneration.fields.leaf.TextFieldDataGenerator; @@ -50,7 +52,9 @@ public enum FieldType { TEXT("text"), IP("ip"), CONSTANT_KEYWORD("constant_keyword"), - WILDCARD("wildcard"); + WILDCARD("wildcard"), + MATCH_ONLY_TEXT("match_only_text"), + PATTERNED_TEXT("patterned_text"); private final String name; @@ -78,6 +82,8 @@ public FieldDataGenerator generator(String fieldName, DataSource dataSource) { case IP -> new IpFieldDataGenerator(dataSource); case CONSTANT_KEYWORD -> new ConstantKeywordFieldDataGenerator(); case WILDCARD -> new WildcardFieldDataGenerator(dataSource); + case MATCH_ONLY_TEXT -> new MatchOnlyTextFieldDataGenerator(dataSource); + case PATTERNED_TEXT -> new PatternedTextFieldDataGenerator(dataSource); }; } @@ -101,6 +107,8 @@ public static FieldType tryParse(String name) { case "ip" -> FieldType.IP; case "constant_keyword" -> FieldType.CONSTANT_KEYWORD; case "wildcard" -> FieldType.WILDCARD; + case "match_only_text" -> FieldType.MATCH_ONLY_TEXT; + case "patterned_text" -> FieldType.PATTERNED_TEXT; default -> null; }; } diff --git a/test/framework/src/main/java/org/elasticsearch/datageneration/datasource/DefaultMappingParametersHandler.java b/test/framework/src/main/java/org/elasticsearch/datageneration/datasource/DefaultMappingParametersHandler.java index 2e234f8aec41c..c7ec736fbec3f 100644 --- a/test/framework/src/main/java/org/elasticsearch/datageneration/datasource/DefaultMappingParametersHandler.java +++ b/test/framework/src/main/java/org/elasticsearch/datageneration/datasource/DefaultMappingParametersHandler.java @@ -15,6 +15,7 @@ import org.elasticsearch.geometry.utils.WellKnownText; import org.elasticsearch.index.mapper.Mapper; import org.elasticsearch.index.mapper.ObjectMapper; +import org.elasticsearch.script.field.Field; import org.elasticsearch.test.ESTestCase; import java.time.Instant; @@ -22,6 +23,7 @@ import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; import java.util.HashMap; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.function.Supplier; @@ -37,17 +39,19 @@ public DataSourceResponse.LeafMappingParametersGenerator handle(DataSourceReques } return new DataSourceResponse.LeafMappingParametersGenerator(switch (fieldType) { - case KEYWORD -> keywordMapping(request); + case KEYWORD -> keywordMapping(false, request); case LONG, INTEGER, SHORT, BYTE, DOUBLE, FLOAT, HALF_FLOAT, UNSIGNED_LONG -> numberMapping(fieldType); case SCALED_FLOAT -> scaledFloatMapping(); case COUNTED_KEYWORD -> countedKeywordMapping(); case BOOLEAN -> booleanMapping(); case DATE -> dateMapping(); case GEO_POINT -> geoPointMapping(); - case TEXT -> textMapping(request); + case TEXT -> textMapping(false, request); case IP -> ipMapping(); case CONSTANT_KEYWORD -> constantKeywordMapping(); - case WILDCARD -> wildcardMapping(); + case WILDCARD -> wildcardMapping(false, request); + case MATCH_ONLY_TEXT -> matchOnlyTextMapping(false, request); + case PATTERNED_TEXT -> patternedTextMapping(false, request); }); } @@ -77,7 +81,7 @@ private Supplier> numberMapping(FieldType fieldType) { }; } - private Supplier> keywordMapping(DataSourceRequest.LeafMappingParametersGenerator request) { + private Supplier> keywordMapping(boolean hasParent, DataSourceRequest.LeafMappingParametersGenerator request) { return () -> { var mapping = commonMappingParameters(); @@ -96,12 +100,15 @@ private Supplier> keywordMapping(DataSourceRequest.LeafMappi } } - if (ESTestCase.randomDouble() <= 0.2) { + if (ESTestCase.randomDouble() <= 0.3) { mapping.put("ignore_above", ESTestCase.randomIntBetween(1, 100)); } if (ESTestCase.randomDouble() <= 0.2) { mapping.put("null_value", ESTestCase.randomAlphaOfLengthBetween(0, 10)); } + if (hasParent == false && ESTestCase.randomDouble() <= 0.2) { + mapping.put("fields", stringSubField(FieldType.KEYWORD, request)); + } return mapping; }; @@ -196,19 +203,15 @@ private Supplier> geoPointMapping() { }; } - private Supplier> textMapping(DataSourceRequest.LeafMappingParametersGenerator request) { + private Supplier> textMapping(boolean hasParent, DataSourceRequest.LeafMappingParametersGenerator request) { return () -> { var mapping = new HashMap(); mapping.put("store", ESTestCase.randomBoolean()); mapping.put("index", ESTestCase.randomBoolean()); - if (ESTestCase.randomDouble() <= 0.1) { - var keywordMultiFieldMapping = keywordMapping(request).get(); - keywordMultiFieldMapping.put("type", "keyword"); - keywordMultiFieldMapping.remove("copy_to"); - - mapping.put("fields", Map.of("kwd", keywordMultiFieldMapping)); + if (hasParent == false && ESTestCase.randomDouble() <= 0.2) { + mapping.put("fields", stringSubField(FieldType.TEXT, request)); } return mapping; @@ -243,17 +246,69 @@ private Supplier> constantKeywordMapping() { }; } - private Supplier> wildcardMapping() { + private Supplier> wildcardMapping(boolean hasParent, DataSourceRequest.LeafMappingParametersGenerator request) { return () -> { var mapping = new HashMap(); - if (ESTestCase.randomDouble() <= 0.2) { + if (ESTestCase.randomDouble() <= 0.3) { mapping.put("ignore_above", ESTestCase.randomIntBetween(1, 100)); } if (ESTestCase.randomDouble() <= 0.2) { mapping.put("null_value", ESTestCase.randomAlphaOfLengthBetween(0, 10)); } + if (hasParent == false && ESTestCase.randomDouble() <= 0.2) { + mapping.put("fields", stringSubField(FieldType.PATTERNED_TEXT, request)); + } + return mapping; + }; + } + private Supplier> stringSubField(FieldType parent, DataSourceRequest.LeafMappingParametersGenerator request) { + /** + * text -> keyword, wildcard + * match_only_text -> keyword, wildcard + * patterned_text -> keyword, wildcard + * keyword -> text, match_only_text, patterned_tet, wildcard + * wildcard -> keyword, text, match_only_text, patterned_text + * + */ + return () -> { + var subFields = new HashMap>>(); + subFields.put(FieldType.KEYWORD, () -> { + var mapping = keywordMapping(true, request).get(); + mapping.remove("copy_to"); + return mapping; + }); + subFields.put(FieldType.TEXT, () -> wildcardMapping(true, request).get()); + subFields.put(FieldType.MATCH_ONLY_TEXT, () -> matchOnlyTextMapping(true, request).get()); + subFields.put(FieldType.WILDCARD, () -> wildcardMapping(true, request).get()); + subFields.put(FieldType.PATTERNED_TEXT, () -> matchOnlyTextMapping(true, request).get()); + + var options = subFields.entrySet().stream().filter(e -> e.getKey().equals(parent) == false).toList(); + var child = ESTestCase.randomFrom(options); + FieldType childType = child.getKey(); + var childValue = child.getValue().get(); + childValue.put("type", childType.toString()); + return Map.of("subfield_" + childType, childValue); + }; + } + + private Supplier> matchOnlyTextMapping(boolean hasParent, DataSourceRequest.LeafMappingParametersGenerator request) { + return () -> { + var mapping = new HashMap(); + if (hasParent == false && ESTestCase.randomDouble() <= 0.2) { + mapping.put("fields", stringSubField(FieldType.MATCH_ONLY_TEXT, request)); + } + return mapping; + }; + } + + private Supplier> patternedTextMapping(boolean hasParent, DataSourceRequest.LeafMappingParametersGenerator request) { + return () -> { + var mapping = new HashMap(); + if (hasParent == false && ESTestCase.randomDouble() <= 0.2) { + mapping.put("fields", stringSubField(FieldType.PATTERNED_TEXT, request)); + } return mapping; }; } diff --git a/test/framework/src/main/java/org/elasticsearch/datageneration/fields/leaf/MatchOnlyTextFieldDataGenerator.java b/test/framework/src/main/java/org/elasticsearch/datageneration/fields/leaf/MatchOnlyTextFieldDataGenerator.java new file mode 100644 index 0000000000000..f4493fd9b4ee9 --- /dev/null +++ b/test/framework/src/main/java/org/elasticsearch/datageneration/fields/leaf/MatchOnlyTextFieldDataGenerator.java @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.datageneration.fields.leaf; + +import org.elasticsearch.datageneration.FieldDataGenerator; +import org.elasticsearch.datageneration.datasource.DataSource; + +import java.util.Map; + +public class MatchOnlyTextFieldDataGenerator implements FieldDataGenerator { + private final FieldDataGenerator textGenerator; + + public MatchOnlyTextFieldDataGenerator(DataSource dataSource) { + this.textGenerator = new TextFieldDataGenerator(dataSource); + } + + @Override + public Object generateValue(Map fieldMapping) { + return textGenerator.generateValue(fieldMapping); + } +} diff --git a/test/framework/src/main/java/org/elasticsearch/datageneration/fields/leaf/PatternedTextFieldDataGenerator.java b/test/framework/src/main/java/org/elasticsearch/datageneration/fields/leaf/PatternedTextFieldDataGenerator.java new file mode 100644 index 0000000000000..a181e1a0d65b8 --- /dev/null +++ b/test/framework/src/main/java/org/elasticsearch/datageneration/fields/leaf/PatternedTextFieldDataGenerator.java @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.datageneration.fields.leaf; + +import org.elasticsearch.datageneration.FieldDataGenerator; +import org.elasticsearch.datageneration.datasource.DataSource; + +import java.util.Map; + +public class PatternedTextFieldDataGenerator implements FieldDataGenerator { + private final FieldDataGenerator textGenerator; + + public PatternedTextFieldDataGenerator(DataSource dataSource) { + this.textGenerator = new TextFieldDataGenerator(dataSource); + } + + @Override + public Object generateValue(Map fieldMapping) { + return textGenerator.generateValue(fieldMapping); + } +} From 381b84e0e4142326540e2d002bb579c47876300e Mon Sep 17 00:00:00 2001 From: Parker Timmins Date: Tue, 22 Jul 2025 16:30:48 -0500 Subject: [PATCH 2/7] remove patterned_text tests --- .../datageneration/FieldType.java | 9 ++-- .../DefaultMappingParametersHandler.java | 50 +++++++------------ .../leaf/PatternedTextFieldDataGenerator.java | 28 ----------- 3 files changed, 22 insertions(+), 65 deletions(-) delete mode 100644 test/framework/src/main/java/org/elasticsearch/datageneration/fields/leaf/PatternedTextFieldDataGenerator.java diff --git a/test/framework/src/main/java/org/elasticsearch/datageneration/FieldType.java b/test/framework/src/main/java/org/elasticsearch/datageneration/FieldType.java index 4052299d79f85..488359d71764b 100644 --- a/test/framework/src/main/java/org/elasticsearch/datageneration/FieldType.java +++ b/test/framework/src/main/java/org/elasticsearch/datageneration/FieldType.java @@ -24,7 +24,6 @@ import org.elasticsearch.datageneration.fields.leaf.KeywordFieldDataGenerator; import org.elasticsearch.datageneration.fields.leaf.LongFieldDataGenerator; import org.elasticsearch.datageneration.fields.leaf.MatchOnlyTextFieldDataGenerator; -import org.elasticsearch.datageneration.fields.leaf.PatternedTextFieldDataGenerator; import org.elasticsearch.datageneration.fields.leaf.ScaledFloatFieldDataGenerator; import org.elasticsearch.datageneration.fields.leaf.ShortFieldDataGenerator; import org.elasticsearch.datageneration.fields.leaf.TextFieldDataGenerator; @@ -53,8 +52,8 @@ public enum FieldType { IP("ip"), CONSTANT_KEYWORD("constant_keyword"), WILDCARD("wildcard"), - MATCH_ONLY_TEXT("match_only_text"), - PATTERNED_TEXT("patterned_text"); + MATCH_ONLY_TEXT("match_only_text"); +// PATTERNED_TEXT("patterned_text"); private final String name; @@ -83,7 +82,7 @@ public FieldDataGenerator generator(String fieldName, DataSource dataSource) { case CONSTANT_KEYWORD -> new ConstantKeywordFieldDataGenerator(); case WILDCARD -> new WildcardFieldDataGenerator(dataSource); case MATCH_ONLY_TEXT -> new MatchOnlyTextFieldDataGenerator(dataSource); - case PATTERNED_TEXT -> new PatternedTextFieldDataGenerator(dataSource); +// case PATTERNED_TEXT -> new PatternedTextFieldDataGenerator(dataSource); }; } @@ -108,7 +107,7 @@ public static FieldType tryParse(String name) { case "constant_keyword" -> FieldType.CONSTANT_KEYWORD; case "wildcard" -> FieldType.WILDCARD; case "match_only_text" -> FieldType.MATCH_ONLY_TEXT; - case "patterned_text" -> FieldType.PATTERNED_TEXT; +// case "patterned_text" -> FieldType.PATTERNED_TEXT; default -> null; }; } diff --git a/test/framework/src/main/java/org/elasticsearch/datageneration/datasource/DefaultMappingParametersHandler.java b/test/framework/src/main/java/org/elasticsearch/datageneration/datasource/DefaultMappingParametersHandler.java index c7ec736fbec3f..cc7a8d9782426 100644 --- a/test/framework/src/main/java/org/elasticsearch/datageneration/datasource/DefaultMappingParametersHandler.java +++ b/test/framework/src/main/java/org/elasticsearch/datageneration/datasource/DefaultMappingParametersHandler.java @@ -51,7 +51,6 @@ public DataSourceResponse.LeafMappingParametersGenerator handle(DataSourceReques case CONSTANT_KEYWORD -> constantKeywordMapping(); case WILDCARD -> wildcardMapping(false, request); case MATCH_ONLY_TEXT -> matchOnlyTextMapping(false, request); - case PATTERNED_TEXT -> patternedTextMapping(false, request); }); } @@ -257,13 +256,13 @@ private Supplier> wildcardMapping(boolean hasParent, DataSou mapping.put("null_value", ESTestCase.randomAlphaOfLengthBetween(0, 10)); } if (hasParent == false && ESTestCase.randomDouble() <= 0.2) { - mapping.put("fields", stringSubField(FieldType.PATTERNED_TEXT, request)); + mapping.put("fields", stringSubField(FieldType.WILDCARD, request)); } return mapping; }; } - private Supplier> stringSubField(FieldType parent, DataSourceRequest.LeafMappingParametersGenerator request) { + private Map stringSubField(FieldType parent, DataSourceRequest.LeafMappingParametersGenerator request) { /** * text -> keyword, wildcard * match_only_text -> keyword, wildcard @@ -272,25 +271,22 @@ private Supplier> stringSubField(FieldType parent, DataSourc * wildcard -> keyword, text, match_only_text, patterned_text * */ - return () -> { - var subFields = new HashMap>>(); - subFields.put(FieldType.KEYWORD, () -> { - var mapping = keywordMapping(true, request).get(); - mapping.remove("copy_to"); - return mapping; - }); - subFields.put(FieldType.TEXT, () -> wildcardMapping(true, request).get()); - subFields.put(FieldType.MATCH_ONLY_TEXT, () -> matchOnlyTextMapping(true, request).get()); - subFields.put(FieldType.WILDCARD, () -> wildcardMapping(true, request).get()); - subFields.put(FieldType.PATTERNED_TEXT, () -> matchOnlyTextMapping(true, request).get()); - - var options = subFields.entrySet().stream().filter(e -> e.getKey().equals(parent) == false).toList(); - var child = ESTestCase.randomFrom(options); - FieldType childType = child.getKey(); - var childValue = child.getValue().get(); - childValue.put("type", childType.toString()); - return Map.of("subfield_" + childType, childValue); - }; + var subFields = new HashMap>>(); + subFields.put(FieldType.KEYWORD, () -> { + var mapping = keywordMapping(true, request).get(); + mapping.remove("copy_to"); + return mapping; + }); + subFields.put(FieldType.TEXT, () -> textMapping(true, request).get()); + subFields.put(FieldType.MATCH_ONLY_TEXT, () -> matchOnlyTextMapping(true, request).get()); + subFields.put(FieldType.WILDCARD, () -> wildcardMapping(true, request).get()); + + var options = subFields.entrySet().stream().filter(e -> e.getKey().equals(parent) == false).toList(); + var child = ESTestCase.randomFrom(options); + FieldType childType = child.getKey(); + var childValue = child.getValue().get(); + childValue.put("type", childType.toString()); + return Map.of("subfield_" + childType, childValue); } private Supplier> matchOnlyTextMapping(boolean hasParent, DataSourceRequest.LeafMappingParametersGenerator request) { @@ -303,16 +299,6 @@ private Supplier> matchOnlyTextMapping(boolean hasParent, Da }; } - private Supplier> patternedTextMapping(boolean hasParent, DataSourceRequest.LeafMappingParametersGenerator request) { - return () -> { - var mapping = new HashMap(); - if (hasParent == false && ESTestCase.randomDouble() <= 0.2) { - mapping.put("fields", stringSubField(FieldType.PATTERNED_TEXT, request)); - } - return mapping; - }; - } - public static HashMap commonMappingParameters() { var map = new HashMap(); map.put("store", ESTestCase.randomBoolean()); diff --git a/test/framework/src/main/java/org/elasticsearch/datageneration/fields/leaf/PatternedTextFieldDataGenerator.java b/test/framework/src/main/java/org/elasticsearch/datageneration/fields/leaf/PatternedTextFieldDataGenerator.java deleted file mode 100644 index a181e1a0d65b8..0000000000000 --- a/test/framework/src/main/java/org/elasticsearch/datageneration/fields/leaf/PatternedTextFieldDataGenerator.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -package org.elasticsearch.datageneration.fields.leaf; - -import org.elasticsearch.datageneration.FieldDataGenerator; -import org.elasticsearch.datageneration.datasource.DataSource; - -import java.util.Map; - -public class PatternedTextFieldDataGenerator implements FieldDataGenerator { - private final FieldDataGenerator textGenerator; - - public PatternedTextFieldDataGenerator(DataSource dataSource) { - this.textGenerator = new TextFieldDataGenerator(dataSource); - } - - @Override - public Object generateValue(Map fieldMapping) { - return textGenerator.generateValue(fieldMapping); - } -} From be07bd791f89b0b393e57fdebc85879f596d9918 Mon Sep 17 00:00:00 2001 From: Parker Timmins Date: Tue, 22 Jul 2025 17:03:40 -0500 Subject: [PATCH 3/7] Add match_only_text matcher --- .../DefaultMappingParametersHandler.java | 8 -------- .../matchers/source/FieldSpecificMatcher.java | 15 ++++++++++----- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/test/framework/src/main/java/org/elasticsearch/datageneration/datasource/DefaultMappingParametersHandler.java b/test/framework/src/main/java/org/elasticsearch/datageneration/datasource/DefaultMappingParametersHandler.java index cc7a8d9782426..cf27ec8fad951 100644 --- a/test/framework/src/main/java/org/elasticsearch/datageneration/datasource/DefaultMappingParametersHandler.java +++ b/test/framework/src/main/java/org/elasticsearch/datageneration/datasource/DefaultMappingParametersHandler.java @@ -263,14 +263,6 @@ private Supplier> wildcardMapping(boolean hasParent, DataSou } private Map stringSubField(FieldType parent, DataSourceRequest.LeafMappingParametersGenerator request) { - /** - * text -> keyword, wildcard - * match_only_text -> keyword, wildcard - * patterned_text -> keyword, wildcard - * keyword -> text, match_only_text, patterned_tet, wildcard - * wildcard -> keyword, text, match_only_text, patterned_text - * - */ var subFields = new HashMap>>(); subFields.put(FieldType.KEYWORD, () -> { var mapping = keywordMapping(true, request).get(); diff --git a/test/framework/src/main/java/org/elasticsearch/datageneration/matchers/source/FieldSpecificMatcher.java b/test/framework/src/main/java/org/elasticsearch/datageneration/matchers/source/FieldSpecificMatcher.java index 7adf98ef9d6ee..99b29297fa4d1 100644 --- a/test/framework/src/main/java/org/elasticsearch/datageneration/matchers/source/FieldSpecificMatcher.java +++ b/test/framework/src/main/java/org/elasticsearch/datageneration/matchers/source/FieldSpecificMatcher.java @@ -62,7 +62,8 @@ static Map matchers( put("geo_shape", new ExactMatcher("geo_shape", actualMappings, actualSettings, expectedMappings, expectedSettings)); put("shape", new ExactMatcher("shape", actualMappings, actualSettings, expectedMappings, expectedSettings)); put("geo_point", new GeoPointMatcher(actualMappings, actualSettings, expectedMappings, expectedSettings)); - put("text", new TextMatcher(actualMappings, actualSettings, expectedMappings, expectedSettings)); + put("text", new TextMatcher(actualMappings, actualSettings, expectedMappings, expectedSettings, false)); + put("match_only_text", new TextMatcher(actualMappings, actualSettings, expectedMappings, expectedSettings, true)); put("ip", new IpMatcher(actualMappings, actualSettings, expectedMappings, expectedSettings)); put("constant_keyword", new ConstantKeywordMatcher(actualMappings, actualSettings, expectedMappings, expectedSettings)); put("wildcard", new WildcardMatcher(actualMappings, actualSettings, expectedMappings, expectedSettings)); @@ -608,17 +609,20 @@ class TextMatcher implements FieldSpecificMatcher { private final Settings.Builder actualSettings; private final XContentBuilder expectedMappings; private final Settings.Builder expectedSettings; + private final boolean isMatchOnlyText; TextMatcher( XContentBuilder actualMappings, Settings.Builder actualSettings, XContentBuilder expectedMappings, - Settings.Builder expectedSettings + Settings.Builder expectedSettings, + boolean isMatchOnlyText ) { this.actualMappings = actualMappings; this.actualSettings = actualSettings; this.expectedMappings = expectedMappings; this.expectedSettings = expectedSettings; + this.isMatchOnlyText = isMatchOnlyText; } @Override @@ -640,23 +644,24 @@ public MatchResult match( // In some cases synthetic source for text fields is synthesized using the keyword multi field. // So in this case it's appropriate to match it using keyword matching logic (mainly to cover `null_value`). var multiFields = (Map) getMappingParameter("fields", actualMapping, expectedMapping); - if (multiFields != null) { + if (multiFields != null && multiFields.containsKey("subfield_keyword")) { var keywordMatcher = new KeywordMatcher(actualMappings, actualSettings, expectedMappings, expectedSettings); - var keywordFieldMapping = (Map) multiFields.get("kwd"); + var keywordFieldMapping = (Map) multiFields.get("subfield_keyword"); var keywordMatchResult = keywordMatcher.match(actual, expected, keywordFieldMapping, keywordFieldMapping); if (keywordMatchResult.isMatch()) { return MatchResult.match(); } } + var typeName = isMatchOnlyText ? "match_only_text" : "text"; return MatchResult.noMatch( formatErrorMessage( actualMappings, actualSettings, expectedMappings, expectedSettings, - "Values of type [text] don't match, " + prettyPrintCollections(actual, expected) + "Values of type [" + typeName + "] don't match, " + prettyPrintCollections(actual, expected) ) ); } From 6588aef24782617e33ce78eadecef06256e90996 Mon Sep 17 00:00:00 2001 From: Parker Timmins Date: Tue, 22 Jul 2025 17:05:54 -0500 Subject: [PATCH 4/7] Remove references to patterned_text type --- .../main/java/org/elasticsearch/datageneration/FieldType.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/framework/src/main/java/org/elasticsearch/datageneration/FieldType.java b/test/framework/src/main/java/org/elasticsearch/datageneration/FieldType.java index 488359d71764b..ef6cc21e90d8a 100644 --- a/test/framework/src/main/java/org/elasticsearch/datageneration/FieldType.java +++ b/test/framework/src/main/java/org/elasticsearch/datageneration/FieldType.java @@ -53,7 +53,6 @@ public enum FieldType { CONSTANT_KEYWORD("constant_keyword"), WILDCARD("wildcard"), MATCH_ONLY_TEXT("match_only_text"); -// PATTERNED_TEXT("patterned_text"); private final String name; @@ -82,7 +81,6 @@ public FieldDataGenerator generator(String fieldName, DataSource dataSource) { case CONSTANT_KEYWORD -> new ConstantKeywordFieldDataGenerator(); case WILDCARD -> new WildcardFieldDataGenerator(dataSource); case MATCH_ONLY_TEXT -> new MatchOnlyTextFieldDataGenerator(dataSource); -// case PATTERNED_TEXT -> new PatternedTextFieldDataGenerator(dataSource); }; } @@ -107,7 +105,6 @@ public static FieldType tryParse(String name) { case "constant_keyword" -> FieldType.CONSTANT_KEYWORD; case "wildcard" -> FieldType.WILDCARD; case "match_only_text" -> FieldType.MATCH_ONLY_TEXT; -// case "patterned_text" -> FieldType.PATTERNED_TEXT; default -> null; }; } From 1084c7be83633120e59729c327f04a0ec347f6ce Mon Sep 17 00:00:00 2001 From: elasticsearchmachine Date: Tue, 22 Jul 2025 22:15:05 +0000 Subject: [PATCH 5/7] [CI] Auto commit changes from spotless --- .../datasource/DefaultMappingParametersHandler.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/framework/src/main/java/org/elasticsearch/datageneration/datasource/DefaultMappingParametersHandler.java b/test/framework/src/main/java/org/elasticsearch/datageneration/datasource/DefaultMappingParametersHandler.java index cf27ec8fad951..7e06d582c7cd7 100644 --- a/test/framework/src/main/java/org/elasticsearch/datageneration/datasource/DefaultMappingParametersHandler.java +++ b/test/framework/src/main/java/org/elasticsearch/datageneration/datasource/DefaultMappingParametersHandler.java @@ -15,7 +15,6 @@ import org.elasticsearch.geometry.utils.WellKnownText; import org.elasticsearch.index.mapper.Mapper; import org.elasticsearch.index.mapper.ObjectMapper; -import org.elasticsearch.script.field.Field; import org.elasticsearch.test.ESTestCase; import java.time.Instant; @@ -23,7 +22,6 @@ import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; import java.util.HashMap; -import java.util.List; import java.util.Locale; import java.util.Map; import java.util.function.Supplier; @@ -281,7 +279,10 @@ private Map stringSubField(FieldType parent, DataSourceRequest.L return Map.of("subfield_" + childType, childValue); } - private Supplier> matchOnlyTextMapping(boolean hasParent, DataSourceRequest.LeafMappingParametersGenerator request) { + private Supplier> matchOnlyTextMapping( + boolean hasParent, + DataSourceRequest.LeafMappingParametersGenerator request + ) { return () -> { var mapping = new HashMap(); if (hasParent == false && ESTestCase.randomDouble() <= 0.2) { From 360054ac59b587437c636b3f275a312b4ca9e7ee Mon Sep 17 00:00:00 2001 From: Parker Timmins Date: Tue, 22 Jul 2025 17:26:42 -0500 Subject: [PATCH 6/7] Refactor subfield type --- .../DefaultMappingParametersHandler.java | 45 +++++++++---------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/test/framework/src/main/java/org/elasticsearch/datageneration/datasource/DefaultMappingParametersHandler.java b/test/framework/src/main/java/org/elasticsearch/datageneration/datasource/DefaultMappingParametersHandler.java index 7e06d582c7cd7..46019d53bd90e 100644 --- a/test/framework/src/main/java/org/elasticsearch/datageneration/datasource/DefaultMappingParametersHandler.java +++ b/test/framework/src/main/java/org/elasticsearch/datageneration/datasource/DefaultMappingParametersHandler.java @@ -22,6 +22,7 @@ import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; import java.util.HashMap; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.function.Supplier; @@ -260,29 +261,7 @@ private Supplier> wildcardMapping(boolean hasParent, DataSou }; } - private Map stringSubField(FieldType parent, DataSourceRequest.LeafMappingParametersGenerator request) { - var subFields = new HashMap>>(); - subFields.put(FieldType.KEYWORD, () -> { - var mapping = keywordMapping(true, request).get(); - mapping.remove("copy_to"); - return mapping; - }); - subFields.put(FieldType.TEXT, () -> textMapping(true, request).get()); - subFields.put(FieldType.MATCH_ONLY_TEXT, () -> matchOnlyTextMapping(true, request).get()); - subFields.put(FieldType.WILDCARD, () -> wildcardMapping(true, request).get()); - - var options = subFields.entrySet().stream().filter(e -> e.getKey().equals(parent) == false).toList(); - var child = ESTestCase.randomFrom(options); - FieldType childType = child.getKey(); - var childValue = child.getValue().get(); - childValue.put("type", childType.toString()); - return Map.of("subfield_" + childType, childValue); - } - - private Supplier> matchOnlyTextMapping( - boolean hasParent, - DataSourceRequest.LeafMappingParametersGenerator request - ) { + private Supplier> matchOnlyTextMapping(boolean hasParent, DataSourceRequest.LeafMappingParametersGenerator request) { return () -> { var mapping = new HashMap(); if (hasParent == false && ESTestCase.randomDouble() <= 0.2) { @@ -292,6 +271,26 @@ private Supplier> matchOnlyTextMapping( }; } + private Map stringSubField(FieldType parent, DataSourceRequest.LeafMappingParametersGenerator request) { + + List stringTypes = List.of(FieldType.TEXT, FieldType.MATCH_ONLY_TEXT, FieldType.KEYWORD, FieldType.WILDCARD); + var childType = ESTestCase.randomValueOtherThan(parent, () -> ESTestCase.randomFrom(stringTypes)); + var child = switch (childType) { + case TEXT -> textMapping(true, request).get(); + case MATCH_ONLY_TEXT -> matchOnlyTextMapping(true, request).get(); + case WILDCARD -> wildcardMapping(true, request).get(); + case KEYWORD -> { + var mapping = keywordMapping(true, request).get(); + mapping.remove("copy_to"); + yield mapping; + } + default -> throw new AssertionError("unreachable"); + }; + + child.put("type", childType.toString()); + return Map.of("subfield_" + childType, child); + } + public static HashMap commonMappingParameters() { var map = new HashMap(); map.put("store", ESTestCase.randomBoolean()); From d67bc1c8a1f8c0192e16cdea2f70e04e74b94c86 Mon Sep 17 00:00:00 2001 From: elasticsearchmachine Date: Tue, 22 Jul 2025 22:35:23 +0000 Subject: [PATCH 7/7] [CI] Auto commit changes from spotless --- .../datasource/DefaultMappingParametersHandler.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/framework/src/main/java/org/elasticsearch/datageneration/datasource/DefaultMappingParametersHandler.java b/test/framework/src/main/java/org/elasticsearch/datageneration/datasource/DefaultMappingParametersHandler.java index 46019d53bd90e..324f1f56e25f8 100644 --- a/test/framework/src/main/java/org/elasticsearch/datageneration/datasource/DefaultMappingParametersHandler.java +++ b/test/framework/src/main/java/org/elasticsearch/datageneration/datasource/DefaultMappingParametersHandler.java @@ -261,7 +261,10 @@ private Supplier> wildcardMapping(boolean hasParent, DataSou }; } - private Supplier> matchOnlyTextMapping(boolean hasParent, DataSourceRequest.LeafMappingParametersGenerator request) { + private Supplier> matchOnlyTextMapping( + boolean hasParent, + DataSourceRequest.LeafMappingParametersGenerator request + ) { return () -> { var mapping = new HashMap(); if (hasParent == false && ESTestCase.randomDouble() <= 0.2) {