diff --git a/CHANGELOG.md b/CHANGELOG.md index ad91e562e0..c3ad2fb6fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - Add workflow to publish snapshots via GHA ([#325](https://github.com/opensearch-project/opensearch-java/pull/325)) - Document HTTP/2 support ([#330](https://github.com/opensearch-project/opensearch-java/pull/330)) - Require two maintainers to approve release ([#383](https://github.com/opensearch-project/opensearch-java/pull/383)) +- Add support for mapping limit settings ([#382](https://github.com/opensearch-project/opensearch-java/pull/382)) ### Dependencies - Bumps `classgraph` from 4.8.149 to 4.8.154 @@ -55,4 +56,4 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ### Security -[Unreleased]: https://github.com/opensearch-project/opensearch-java/compare/2.0...HEAD \ No newline at end of file +[Unreleased]: https://github.com/opensearch-project/opensearch-java/compare/2.0...HEAD diff --git a/java-client/src/main/java/org/opensearch/client/opensearch/indices/IndexSettings.java b/java-client/src/main/java/org/opensearch/client/opensearch/indices/IndexSettings.java index 4f0480ad28..bae7d418cb 100644 --- a/java-client/src/main/java/org/opensearch/client/opensearch/indices/IndexSettings.java +++ b/java-client/src/main/java/org/opensearch/client/opensearch/indices/IndexSettings.java @@ -219,6 +219,9 @@ public class IndexSettings implements JsonpSerializable { @Nullable private final IndexSettings settings; + @Nullable + private final IndexSettingsMapping mapping; + // --------------------------------------------------------------------------------------------- private IndexSettings(Builder builder) { @@ -278,6 +281,7 @@ private IndexSettings(Builder builder) { this.topMetricsMaxSize = builder.topMetricsMaxSize; this.analysis = builder.analysis; this.settings = builder.settings; + this.mapping = builder.mapping; } @@ -724,6 +728,14 @@ public final IndexSettings settings() { return this.settings; } + /** + * API name: {@code mapping} + */ + @Nullable + public final IndexSettingsMapping mapping() { + return this.mapping; + } + /** * Serialize this object to JSON. */ @@ -1015,6 +1027,11 @@ protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { this.settings.serialize(generator, mapper); } + if (this.mapping != null) { + generator.writeKey("mapping"); + this.mapping.serialize(generator, mapper); + + } } @@ -1190,6 +1207,9 @@ public static class Builder extends ObjectBuilderBase implements ObjectBuilder> fn) { + return this.mapping(fn.apply(new IndexSettingsMapping.Builder()).build()); + } + /** * Builds a {@link IndexSettings}. * @@ -1838,6 +1873,7 @@ protected static void setupIndexSettingsDeserializer(ObjectDeserializer> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * API name: {@code total_fields} + */ + @Nullable + public final IndexSettingsMappingLimit totalFields() { + return this.totalFields; + } + + /** + * API name: {@code depth} + */ + @Nullable + public final IndexSettingsMappingLimit depth() { + return this.depth; + } + + /** + * API name: {@code nested_fields} + */ + @Nullable + public final IndexSettingsMappingLimit nestedFields() { + return this.nestedFields; + } + + /** + * API name: {@code nested_objects} + */ + @Nullable + public final IndexSettingsMappingLimit nestedObjects() { + return this.nestedObjects; + } + + /** + * API name: {@code field_name_length} + */ + @Nullable + public final IndexSettingsMappingLimit fieldNameLength() { + return this.fieldNameLength; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + if (this.totalFields != null) { + generator.writeKey("total_fields"); + this.totalFields.serialize(generator, mapper); + + } + if (this.depth != null) { + generator.writeKey("depth"); + this.depth.serialize(generator, mapper); + + } + if (this.nestedFields != null) { + generator.writeKey("nested_fields"); + this.nestedFields.serialize(generator, mapper); + + } + if (this.nestedObjects != null) { + generator.writeKey("nested_objects"); + this.nestedObjects.serialize(generator, mapper); + + } + if (this.fieldNameLength != null) { + generator.writeKey("field_name_length"); + this.fieldNameLength.serialize(generator, mapper); + + } + + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link IndexSettingsMapping}. + */ + public static class Builder extends ObjectBuilderBase implements ObjectBuilder { + @Nullable + private IndexSettingsMappingLimit totalFields; + + @Nullable + private IndexSettingsMappingLimit depth; + + @Nullable + private IndexSettingsMappingLimit nestedFields; + + @Nullable + private IndexSettingsMappingLimit nestedObjects; + + @Nullable + private IndexSettingsMappingLimit fieldNameLength; + + /** + * API name: {@code total_fields} + */ + public final Builder totalFields(@Nullable IndexSettingsMappingLimit value) { + this.totalFields = value; + return this; + } + + /** + * API name: {@code total_fields} + */ + public final Builder totalFields(Function> fn) { + return this.totalFields(fn.apply(new IndexSettingsMappingLimit.Builder()).build()); + } + + /** + * API name: {@code depth} + */ + public final Builder depth(@Nullable IndexSettingsMappingLimit value) { + this.depth = value; + return this; + } + + /** + * API name: {@code depth} + */ + public final Builder depth(Function> fn) { + return this.depth(fn.apply(new IndexSettingsMappingLimit.Builder()).build()); + } + + /** + * API name: {@code nested_fields} + */ + public final Builder nestedFields(@Nullable IndexSettingsMappingLimit value) { + this.nestedFields = value; + return this; + } + + /** + * API name: {@code nested_fields} + */ + public final Builder nestedFields(Function> fn) { + return this.nestedFields(fn.apply(new IndexSettingsMappingLimit.Builder()).build()); + } + + /** + * API name: {@code nested_objects} + */ + public final Builder nestedObjects(@Nullable IndexSettingsMappingLimit value) { + this.nestedObjects = value; + return this; + } + + /** + * API name: {@code nested_objects} + */ + public final Builder nestedObjects(Function> fn) { + return this.nestedObjects(fn.apply(new IndexSettingsMappingLimit.Builder()).build()); + } + + /** + * API name: {@code field_name_length} + */ + public final Builder fieldNameLength(@Nullable IndexSettingsMappingLimit value) { + this.fieldNameLength = value; + return this; + } + + /** + * API name: {@code field_name_length} + */ + public final Builder fieldNameLength(Function> fn) { + return this.fieldNameLength(fn.apply(new IndexSettingsMappingLimit.Builder()).build()); + } + + /** + * Builds a {@link IndexSettingsMapping}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public IndexSettingsMapping build() { + _checkSingleUse(); + + return new IndexSettingsMapping(this); + } + } + + /** + * Json deserializer for {@link IndexSettingsMapping} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer.lazy(Builder::new, + IndexSettingsMapping::setupIndexSettingsDeserializer); + + protected static void setupIndexSettingsDeserializer(ObjectDeserializer op) { + + op.add(Builder::totalFields, IndexSettingsMappingLimit._DESERIALIZER, "total_fields"); + op.add(Builder::depth, IndexSettingsMappingLimit._DESERIALIZER, "depth"); + op.add(Builder::nestedFields, IndexSettingsMappingLimit._DESERIALIZER, "nested_fields"); + op.add(Builder::nestedObjects, IndexSettingsMappingLimit._DESERIALIZER, "nested_objects"); + op.add(Builder::fieldNameLength, IndexSettingsMappingLimit._DESERIALIZER, "field_name_length"); + + } + +} diff --git a/java-client/src/main/java/org/opensearch/client/opensearch/indices/IndexSettingsMappingLimit.java b/java-client/src/main/java/org/opensearch/client/opensearch/indices/IndexSettingsMappingLimit.java new file mode 100644 index 0000000000..b20238701b --- /dev/null +++ b/java-client/src/main/java/org/opensearch/client/opensearch/indices/IndexSettingsMappingLimit.java @@ -0,0 +1,106 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.client.opensearch.indices; + +import jakarta.json.stream.JsonGenerator; +import org.opensearch.client.json.JsonpDeserializable; +import org.opensearch.client.json.JsonpDeserializer; +import org.opensearch.client.json.JsonpMapper; +import org.opensearch.client.json.JsonpSerializable; +import org.opensearch.client.json.ObjectBuilderDeserializer; +import org.opensearch.client.json.ObjectDeserializer; +import org.opensearch.client.util.ObjectBuilder; +import org.opensearch.client.util.ObjectBuilderBase; + +import javax.annotation.Nullable; +import java.util.function.Function; + +@JsonpDeserializable +public class IndexSettingsMappingLimit implements JsonpSerializable { + + @Nullable + private final Long limit; + + private IndexSettingsMappingLimit(Builder builder) { + + this.limit = builder.limit; + + } + + public static IndexSettingsMappingLimit of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * API name: {@code limit} + */ + @Nullable + public final Long limit() { + return this.limit; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator) { + + if (this.limit != null) { + generator.writeKey("limit"); + generator.write(this.limit); + } + + } + + /** + * Builder for {@link IndexSettingsMappingLimit}. + */ + public static class Builder extends ObjectBuilderBase implements ObjectBuilder { + @Nullable + private Long limit; + + /** + * API name: {@code limit} + */ + public final Builder limit(@Nullable Long value) { + this.limit = value; + return this; + } + + /** + * Builds a {@link IndexSettingsMappingLimit}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public IndexSettingsMappingLimit build() { + _checkSingleUse(); + + return new IndexSettingsMappingLimit(this); + } + } + + /** + * Json deserializer for {@link IndexSettingsMappingLimit} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer.lazy(Builder::new, + IndexSettingsMappingLimit::setupIndexSettingsMappingLimitDeserializer); + + protected static void setupIndexSettingsMappingLimitDeserializer(ObjectDeserializer op) { + + op.add(Builder::limit, JsonpDeserializer.longDeserializer(), "limit"); + + } + +} diff --git a/java-client/src/test/java/org/opensearch/client/opensearch/experiments/ParsingTests.java b/java-client/src/test/java/org/opensearch/client/opensearch/experiments/ParsingTests.java index c9dab9bdeb..6bbf1917a8 100644 --- a/java-client/src/test/java/org/opensearch/client/opensearch/experiments/ParsingTests.java +++ b/java-client/src/test/java/org/opensearch/client/opensearch/experiments/ParsingTests.java @@ -32,14 +32,15 @@ package org.opensearch.client.opensearch.experiments; -import org.opensearch.client.opensearch.experiments.api.FooRequest; -import org.opensearch.client.json.jsonb.JsonbJsonpMapper; import jakarta.json.spi.JsonProvider; import jakarta.json.stream.JsonGenerator; import jakarta.json.stream.JsonParser; import jakarta.json.stream.JsonParsingException; import org.junit.Assert; import org.junit.Test; +import org.opensearch.client.json.jsonb.JsonbJsonpMapper; +import org.opensearch.client.opensearch.experiments.api.FooRequest; +import org.opensearch.client.opensearch.indices.IndexSettingsMapping; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -55,13 +56,13 @@ public void testFoo() throws Exception { ByteArrayOutputStream baos = new ByteArrayOutputStream(); FooRequest foo = FooRequest.builder() - .name("z") - .value(1) - .indices("a", "b", "c") - .bar(b -> b - .name("Raise the bar") - ) - .build(); + .name("z") + .value(1) + .indices("a", "b", "c") + .bar(b -> b + .name("Raise the bar") + ) + .build(); JsonProvider provider = JsonProvider.provider(); JsonGenerator generator = provider.createGenerator(baos); @@ -85,4 +86,42 @@ public void testFoo() throws Exception { throw new JsonParsingException(je.getMessage() + " at " + je.getLocation(), je, je.getLocation()); } } + + @Test + public void testIndexSettingsMappingParsing() { + + try { + + var baos = new ByteArrayOutputStream(); + + var mapping = IndexSettingsMapping.of(b -> b + .totalFields(d -> d.limit(1L)) + .depth(d -> d.limit(2L)) + .nestedFields(d -> d.limit(3L)) + .nestedObjects(d -> d.limit(4L)) + .fieldNameLength(d -> d.limit(5L))); + + var provider = JsonProvider.provider(); + var generator = provider.createGenerator(baos); + mapping.serialize(generator, new JsonbJsonpMapper()); + + generator.close(); + var str = baos.toString(); + + assertEquals("{\"total_fields\":{\"limit\":1},\"depth\":{\"limit\":2},\"nested_fields\":{\"limit\":3}," + + "\"nested_objects\":{\"limit\":4},\"field_name_length\":{\"limit\":5}}", str); + + var parser = provider.createParser(new ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8))); + + var deserialized = IndexSettingsMapping._DESERIALIZER.deserialize(parser, new JsonbJsonpMapper()); + + assertEquals(mapping.totalFields().limit(), deserialized.totalFields().limit()); + assertEquals(mapping.depth().limit(), deserialized.depth().limit()); + assertEquals(mapping.nestedFields().limit(), deserialized.nestedFields().limit()); + assertEquals(mapping.nestedObjects().limit(), deserialized.nestedObjects().limit()); + assertEquals(mapping.fieldNameLength().limit(), deserialized.fieldNameLength().limit()); + } catch (JsonParsingException je) { + throw new JsonParsingException(je.getMessage() + " at " + je.getLocation(), je, je.getLocation()); + } + } } diff --git a/java-client/src/test/java/org/opensearch/client/opensearch/integTest/AbstractRequestIT.java b/java-client/src/test/java/org/opensearch/client/opensearch/integTest/AbstractRequestIT.java index 835f292934..586abd49d9 100644 --- a/java-client/src/test/java/org/opensearch/client/opensearch/integTest/AbstractRequestIT.java +++ b/java-client/src/test/java/org/opensearch/client/opensearch/integTest/AbstractRequestIT.java @@ -51,8 +51,8 @@ import org.opensearch.client.opensearch.core.IndexResponse; import org.opensearch.client.opensearch.core.InfoResponse; import org.opensearch.client.opensearch.core.MsearchResponse; -import org.opensearch.client.opensearch.core.SearchResponse; import org.opensearch.client.opensearch.core.SearchRequest; +import org.opensearch.client.opensearch.core.SearchResponse; import org.opensearch.client.opensearch.core.bulk.OperationType; import org.opensearch.client.opensearch.core.msearch.RequestItem; import org.opensearch.client.opensearch.core.search.CompletionSuggester; @@ -77,6 +77,7 @@ import java.util.concurrent.TimeUnit; public abstract class AbstractRequestIT extends OpenSearchJavaClientTestCase { + @Test public void testCount() throws Exception { @@ -106,6 +107,70 @@ public void testIndexCreation() throws Exception { assertNotNull(indices.get("my-index")); } + @Test + public void testIndexSettingsMapping() throws Exception { + var createResponse = javaClient().indices() + .create(r -> r.index("test-settings") + .settings(s -> s + .mapping(m -> m + .fieldNameLength(f -> f.limit(300L)) + .totalFields(f -> f.limit(30L)) + .nestedFields(f -> f.limit(10L)) + .depth(f -> f.limit(3L)) + .nestedObjects(f -> f.limit(9L))))); + assertTrue(createResponse.acknowledged()); + assertTrue(createResponse.shardsAcknowledged()); + + var createdSettings = javaClient().indices().getSettings(r -> r.index("test-settings")); + + var createdIndexSettings = createdSettings.get("test-settings"); + assertNotNull(createdIndexSettings); + assertNotNull(createdIndexSettings.settings()); + assertNotNull(createdIndexSettings.settings().index()); + var createdMappingSettings = createdIndexSettings.settings().index().mapping(); + assertNotNull(createdMappingSettings); + assertNotNull(createdMappingSettings.fieldNameLength()); + assertEquals(300L, (Object) createdMappingSettings.fieldNameLength().limit()); + assertNotNull(createdMappingSettings.totalFields()); + assertEquals(30L, (Object) createdMappingSettings.totalFields().limit()); + assertNotNull(createdMappingSettings.nestedFields()); + assertEquals(10L, (Object) createdMappingSettings.nestedFields().limit()); + assertNotNull(createdMappingSettings.depth()); + assertEquals(3L, (Object) createdMappingSettings.depth().limit()); + assertNotNull(createdMappingSettings.nestedObjects()); + assertEquals(9L, (Object) createdMappingSettings.nestedObjects().limit()); + + var putSettingsResponse = javaClient().indices().putSettings(r -> r + .index("test-settings") + .settings(s -> s + .mapping(m -> m + .fieldNameLength(f -> f.limit(400L)) + .totalFields(f -> f.limit(130L)) + .nestedFields(f -> f.limit(110L)) + .depth(f -> f.limit(13L)) + .nestedObjects(f -> f.limit(19L))))); + assertTrue(putSettingsResponse.acknowledged()); + + var updatedSettings = javaClient().indices().getSettings(r -> r.index("test-settings")); + + var updatedIndexSettings = updatedSettings.get("test-settings"); + assertNotNull(updatedIndexSettings); + assertNotNull(updatedIndexSettings.settings()); + assertNotNull(updatedIndexSettings.settings().index()); + var updatedMappingSettings = updatedIndexSettings.settings().index().mapping(); + assertNotNull(updatedMappingSettings); + assertNotNull(updatedMappingSettings.fieldNameLength()); + assertEquals(400L, (Object) updatedMappingSettings.fieldNameLength().limit()); + assertNotNull(updatedMappingSettings.totalFields()); + assertEquals(130L, (Object) updatedMappingSettings.totalFields().limit()); + assertNotNull(updatedMappingSettings.nestedFields()); + assertEquals(110L, (Object) updatedMappingSettings.nestedFields().limit()); + assertNotNull(updatedMappingSettings.depth()); + assertEquals(13L, (Object) updatedMappingSettings.depth().limit()); + assertNotNull(updatedMappingSettings.nestedObjects()); + assertEquals(19L, (Object) updatedMappingSettings.nestedObjects().limit()); + } + @Test public void testDataIngestion() throws Exception { @@ -208,15 +273,15 @@ public void testCatRequest() throws IOException { InfoResponse info = javaClient().info(); String version = info.version().number(); if (version.contains("SNAPSHOT")) { - version = version.split("-")[0]; + version = version.split("-")[0]; } assertEquals(1, nodes.valueBody().size()); if (Version.fromString(version).onOrAfter(Version.fromString("2.0.0"))) { - assertEquals("*", nodes.valueBody().get(0).clusterManager()); + assertEquals("*", nodes.valueBody().get(0).clusterManager()); } else { - assertEquals("*", nodes.valueBody().get(0).master()); + assertEquals("*", nodes.valueBody().get(0).master()); } - + } @Test @@ -297,7 +362,8 @@ public void testRefresh() throws IOException { assertEquals("1", ir.id()); } - @Test public void errorResponse() throws Exception { + @Test + public void errorResponse() throws Exception { BooleanResponse exists = javaClient().exists(_0 -> _0.index("doesnotexist").id("reallynot")); assertFalse(exists.value()); @@ -537,6 +603,7 @@ public void testCompletionSuggester() throws IOException { // } public static class AppData { + private int intValue; private String msg; @@ -558,10 +625,13 @@ public void setMsg(String msg) { } public static class Product { + public double price; public String color; - public Product() {} + public Product() { + } + public Product(double price) { this.price = price; } @@ -581,10 +651,12 @@ public void setPrice(double price) { } public static class Join { + public String name; public String parent; - Join() {} + Join() { + } Join(String name) { this.name = name; @@ -597,10 +669,12 @@ public static class Join { } public static class Question { + public String title; public Join join; - Question() {} + Question() { + } Question(String title) { this.title = title; @@ -609,10 +683,12 @@ public static class Question { } public static class Answer { + public String body; public Join join; - Answer() {} + Answer() { + } Answer(String body) { this.body = body; @@ -623,4 +699,4 @@ public static class Answer { this.join = new Join("answer", parent); } } -} \ No newline at end of file +}