Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
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.ScaledFloatFieldDataGenerator;
import org.elasticsearch.datageneration.fields.leaf.ShortFieldDataGenerator;
import org.elasticsearch.datageneration.fields.leaf.TextFieldDataGenerator;
Expand Down Expand Up @@ -50,7 +51,8 @@ public enum FieldType {
TEXT("text"),
IP("ip"),
CONSTANT_KEYWORD("constant_keyword"),
WILDCARD("wildcard");
WILDCARD("wildcard"),
MATCH_ONLY_TEXT("match_only_text");

private final String name;

Expand Down Expand Up @@ -78,6 +80,7 @@ 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);
};
}

Expand All @@ -101,6 +104,7 @@ 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;
default -> null;
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -37,17 +38,18 @@ 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);
});
}

Expand Down Expand Up @@ -77,7 +79,7 @@ private Supplier<Map<String, Object>> numberMapping(FieldType fieldType) {
};
}

private Supplier<Map<String, Object>> keywordMapping(DataSourceRequest.LeafMappingParametersGenerator request) {
private Supplier<Map<String, Object>> keywordMapping(boolean hasParent, DataSourceRequest.LeafMappingParametersGenerator request) {
return () -> {
var mapping = commonMappingParameters();

Expand All @@ -96,12 +98,15 @@ private Supplier<Map<String, Object>> 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;
};
Expand Down Expand Up @@ -196,19 +201,15 @@ private Supplier<Map<String, Object>> geoPointMapping() {
};
}

private Supplier<Map<String, Object>> textMapping(DataSourceRequest.LeafMappingParametersGenerator request) {
private Supplier<Map<String, Object>> textMapping(boolean hasParent, DataSourceRequest.LeafMappingParametersGenerator request) {
return () -> {
var mapping = new HashMap<String, Object>();

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;
Expand Down Expand Up @@ -243,21 +244,56 @@ private Supplier<Map<String, Object>> constantKeywordMapping() {
};
}

private Supplier<Map<String, Object>> wildcardMapping() {
private Supplier<Map<String, Object>> wildcardMapping(boolean hasParent, DataSourceRequest.LeafMappingParametersGenerator request) {
return () -> {
var mapping = new HashMap<String, Object>();

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.WILDCARD, request));
}
return mapping;
};
}

private Supplier<Map<String, Object>> matchOnlyTextMapping(
boolean hasParent,
DataSourceRequest.LeafMappingParametersGenerator request
) {
return () -> {
var mapping = new HashMap<String, Object>();
if (hasParent == false && ESTestCase.randomDouble() <= 0.2) {
mapping.put("fields", stringSubField(FieldType.MATCH_ONLY_TEXT, request));
}
return mapping;
};
}

private Map<String, Object> stringSubField(FieldType parent, DataSourceRequest.LeafMappingParametersGenerator request) {

List<FieldType> 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<String, Object> commonMappingParameters() {
var map = new HashMap<String, Object>();
map.put("store", ESTestCase.randomBoolean());
Expand Down
Original file line number Diff line number Diff line change
@@ -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<String, Object> fieldMapping) {
return textGenerator.generateValue(fieldMapping);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ static Map<String, FieldSpecificMatcher> 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));
Expand Down Expand Up @@ -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
Expand All @@ -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<String, Object>) 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<String, Object>) multiFields.get("kwd");
var keywordFieldMapping = (Map<String, Object>) 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)
)
);
}
Expand Down