Skip to content

Commit 3269d1b

Browse files
authored
Add specific test for serializing all mapping parameter values (#61844)
This commit adds a test to MapperTestCase that explicitly checks that a mapper can serialize all its default values, and that this serialization can then be re-parsed. Note that the test is disabled for non-parametrized mappers as their serialization may in some cases output parameters that are not accepted. Gradually moving all mappers to parametrized form will address this. The commit also contains a fix to keyword mappers, which were not correctly serializing the similarity parameter; this partially addresses #61563. It also enables `null` as a value for `null_value` on `scaled_float`, as a follow-up to #61798
1 parent 76fa500 commit 3269d1b

File tree

7 files changed

+41
-4
lines changed

7 files changed

+41
-4
lines changed

modules/mapper-extras/src/main/java/org/elasticsearch/index/mapper/ScaledFloatFieldMapper.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ public static class Builder extends ParametrizedFieldMapper.Builder {
9292
}
9393
});
9494
private final Parameter<Double> nullValue = new Parameter<>("null_value", false, () -> null,
95-
(n, c, o) -> XContentMapValues.nodeDoubleValue(o), m -> toType(m).nullValue);
95+
(n, c, o) -> o == null ? null : XContentMapValues.nodeDoubleValue(o), m -> toType(m).nullValue).acceptsNull();
9696

9797
private final Parameter<Map<String, String>> meta = Parameter.metaParam();
9898

server/src/main/java/org/elasticsearch/index/mapper/KeywordFieldMapper.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,9 @@ public static class Builder extends ParametrizedFieldMapper.Builder {
9999
private final Parameter<Boolean> hasNorms
100100
= Parameter.boolParam("norms", false, m -> toType(m).fieldType.omitNorms() == false, false);
101101
private final Parameter<SimilarityProvider> similarity = new Parameter<>("similarity", false, () -> null,
102-
(n, c, o) -> TypeParsers.resolveSimilarity(c, n, o.toString()), m -> toType(m).similarity);
102+
(n, c, o) -> TypeParsers.resolveSimilarity(c, n, o), m -> toType(m).similarity)
103+
.setSerializer((b, f, v) -> b.field(f, v == null ? null : v.name()), v -> v == null ? null : v.name())
104+
.acceptsNull();
103105

104106
private final Parameter<String> normalizer
105107
= Parameter.stringParam("normalizer", false, m -> toType(m).normalizerName, "default");

server/src/main/java/org/elasticsearch/index/mapper/TypeParsers.java

+5-2
Original file line numberDiff line numberDiff line change
@@ -398,8 +398,11 @@ public static List<String> parseCopyFields(Object propNode) {
398398
return copyFields;
399399
}
400400

401-
public static SimilarityProvider resolveSimilarity(Mapper.TypeParser.ParserContext parserContext, String name, String value) {
402-
SimilarityProvider similarityProvider = parserContext.getSimilarity(value);
401+
public static SimilarityProvider resolveSimilarity(Mapper.TypeParser.ParserContext parserContext, String name, Object value) {
402+
if (value == null) {
403+
return null; // use default
404+
}
405+
SimilarityProvider similarityProvider = parserContext.getSimilarity(value.toString());
403406
if (similarityProvider == null) {
404407
throw new MapperParsingException("Unknown Similarity type [" + value + "] for field [" + name + "]");
405408
}

server/src/test/java/org/elasticsearch/index/mapper/KeywordFieldMapperTests.java

+12
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,18 @@ public void testEnableNorms() throws IOException {
250250
assertEquals(0, fieldNamesFields.length);
251251
}
252252

253+
public void testConfigureSimilarity() throws IOException {
254+
MapperService mapperService = createMapperService(
255+
fieldMapping(b -> b.field("type", "keyword").field("similarity", "boolean"))
256+
);
257+
MappedFieldType ft = mapperService.documentMapper().fieldTypes().get("field");
258+
assertEquals("boolean", ft.getTextSearchInfo().getSimilarity().name());
259+
260+
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
261+
() -> merge(mapperService, fieldMapping(b -> b.field("type", "keyword").field("similarity", "BM25"))));
262+
assertThat(e.getMessage(), containsString("Cannot update parameter [similarity] from [boolean] to [BM25]"));
263+
}
264+
253265
public void testNormalizer() throws IOException {
254266
DocumentMapper mapper = createDocumentMapper(fieldMapping(b -> b.field("type", "keyword").field("normalizer", "lowercase")));
255267
ParsedDocument doc = mapper.parse(source(b -> b.field("field", "AbC")));

test/framework/src/main/java/org/elasticsearch/index/mapper/FieldMapperTestCase2.java

+5
Original file line numberDiff line numberDiff line change
@@ -228,4 +228,9 @@ private XContentBuilder mappingsToJson(ToXContent builder, boolean includeDefaul
228228
ToXContent.Params params = includeDefaults ? new ToXContent.MapParams(Map.of("include_defaults", "true")) : ToXContent.EMPTY_PARAMS;
229229
return mapping(b -> builder.toXContent(b, params));
230230
}
231+
232+
@Override
233+
public void testMinimalToMaximal() {
234+
assumeFalse("`include_defaults` includes unsupported properties in non-parametrized mappers", false);
235+
}
231236
}

test/framework/src/main/java/org/elasticsearch/index/mapper/MapperServiceTestCase.java

+3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.elasticsearch.common.bytes.BytesReference;
3131
import org.elasticsearch.common.compress.CompressedXContent;
3232
import org.elasticsearch.common.settings.Settings;
33+
import org.elasticsearch.common.xcontent.ToXContent;
3334
import org.elasticsearch.common.xcontent.XContentBuilder;
3435
import org.elasticsearch.common.xcontent.XContentFactory;
3536
import org.elasticsearch.common.xcontent.XContentType;
@@ -63,6 +64,8 @@ public abstract class MapperServiceTestCase extends ESTestCase {
6364

6465
protected static final Settings SETTINGS = Settings.builder().put("index.version.created", Version.CURRENT).build();
6566

67+
protected static final ToXContent.Params INCLUDE_DEFAULTS = new ToXContent.MapParams(Map.of("include_defaults", "true"));
68+
6669
protected Collection<? extends Plugin> getPlugins() {
6770
return emptyList();
6871
}

test/framework/src/main/java/org/elasticsearch/index/mapper/MapperTestCase.java

+12
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,18 @@ public final void testMinimalSerializesToItself() throws IOException {
6464
assertParseMinimalWarnings();
6565
}
6666

67+
// TODO make this final once we remove FieldMapperTestCase2
68+
public void testMinimalToMaximal() throws IOException {
69+
XContentBuilder orig = JsonXContent.contentBuilder().startObject();
70+
createMapperService(fieldMapping(this::minimalMapping)).documentMapper().mapping().toXContent(orig, INCLUDE_DEFAULTS);
71+
orig.endObject();
72+
XContentBuilder parsedFromOrig = JsonXContent.contentBuilder().startObject();
73+
createMapperService(orig).documentMapper().mapping().toXContent(parsedFromOrig, INCLUDE_DEFAULTS);
74+
parsedFromOrig.endObject();
75+
assertEquals(Strings.toString(orig), Strings.toString(parsedFromOrig));
76+
assertParseMinimalWarnings();
77+
}
78+
6779
protected void assertParseMinimalWarnings() {
6880
// Most mappers don't emit any warnings
6981
}

0 commit comments

Comments
 (0)