From 89c9965cd0c95571004a09b0880cff5a7e9c240b Mon Sep 17 00:00:00 2001 From: Andriy Redko Date: Sun, 6 Apr 2025 14:20:08 -0400 Subject: [PATCH 1/3] Add test cases for dynamic_templates mappings Signed-off-by: Andriy Redko --- .../DynamicTemplatesContextBaseTests.java | 86 +++++++++++++++++++ ...DynamicTemplatesORHLCIntegrationTests.java | 29 +++++++ .../DynamicTemplatesOSCIntegrationTests.java | 29 +++++++ .../test-dynamic_templates_mappings.json | 2 +- .../test-dynamic_templates_mappings_two.json | 22 ++--- 5 files changed, 154 insertions(+), 14 deletions(-) create mode 100644 spring-data-opensearch/src/test/java/org/opensearch/data/client/core/index/DynamicTemplatesContextBaseTests.java create mode 100644 spring-data-opensearch/src/test/java/org/opensearch/data/client/core/index/DynamicTemplatesORHLCIntegrationTests.java create mode 100644 spring-data-opensearch/src/test/java/org/opensearch/data/client/core/index/DynamicTemplatesOSCIntegrationTests.java diff --git a/spring-data-opensearch/src/test/java/org/opensearch/data/client/core/index/DynamicTemplatesContextBaseTests.java b/spring-data-opensearch/src/test/java/org/opensearch/data/client/core/index/DynamicTemplatesContextBaseTests.java new file mode 100644 index 00000000..96fe03d1 --- /dev/null +++ b/spring-data-opensearch/src/test/java/org/opensearch/data/client/core/index/DynamicTemplatesContextBaseTests.java @@ -0,0 +1,86 @@ +/* + * Copyright OpenSearch Contributors + * 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.data.client.core.index; + + +import java.util.HashMap; +import java.util.Map; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.annotation.Id; +import org.springframework.data.elasticsearch.annotations.Document; +import org.springframework.data.elasticsearch.annotations.DynamicTemplates; +import org.springframework.data.elasticsearch.annotations.Field; +import org.springframework.data.elasticsearch.annotations.FieldType; +import org.springframework.data.elasticsearch.core.ElasticsearchOperations; +import org.springframework.data.elasticsearch.core.IndexOperations; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; +import org.springframework.data.elasticsearch.junit.jupiter.SpringIntegrationTest; +import org.springframework.data.elasticsearch.utils.IndexNameProvider; +import org.springframework.lang.Nullable; + +@SpringIntegrationTest +public abstract class DynamicTemplatesContextBaseTests { + @Autowired protected ElasticsearchOperations operations; + @Autowired protected IndexNameProvider indexNameProvider; + + @BeforeEach + void setUp() { + indexNameProvider.increment(); + } + + @AfterEach + void cleanup() { + operations.indexOps(IndexCoordinates.of(indexNameProvider.getPrefix() + "*")).delete(); + } + + @Test + void shouldCreateDynamicTemplateOne() { + IndexOperations indexOperations = operations.indexOps(SampleDynamicTemplatesEntity.class); + indexOperations.createWithMapping(); + } + + + @Test + void shouldCreateDynamicTemplateTwo() { + IndexOperations indexOperations = operations.indexOps(SampleDynamicTemplatesEntityTwo.class); + indexOperations.createWithMapping(); + } + + /** + * @author Petr Kukral + */ + @Document(indexName = "#{@indexNameProvider.indexName()}") + @DynamicTemplates(mappingPath = "/mappings/test-dynamic_templates_mappings.json") + static class SampleDynamicTemplatesEntity { + + @Nullable + @Id private String id; + + @Nullable + @Field(type = FieldType.Object) private final Map names = new HashMap<>(); + } + + /** + * @author Petr Kukral + */ + @Document(indexName = "#{@indexNameProvider.indexName()}") + @DynamicTemplates(mappingPath = "/mappings/test-dynamic_templates_mappings_two.json") + static class SampleDynamicTemplatesEntityTwo { + + @Nullable + @Id private String id; + + @Nullable + @Field(type = FieldType.Object) private final Map names = new HashMap<>(); + } +} diff --git a/spring-data-opensearch/src/test/java/org/opensearch/data/client/core/index/DynamicTemplatesORHLCIntegrationTests.java b/spring-data-opensearch/src/test/java/org/opensearch/data/client/core/index/DynamicTemplatesORHLCIntegrationTests.java new file mode 100644 index 00000000..92a4c211 --- /dev/null +++ b/spring-data-opensearch/src/test/java/org/opensearch/data/client/core/index/DynamicTemplatesORHLCIntegrationTests.java @@ -0,0 +1,29 @@ +/* + * Copyright OpenSearch Contributors + * 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.data.client.core.index; + +import org.opensearch.data.client.junit.jupiter.OpenSearchRestTemplateConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.data.elasticsearch.utils.IndexNameProvider; +import org.springframework.test.context.ContextConfiguration; + +@ContextConfiguration(classes = {DynamicTemplatesORHLCIntegrationTests.Config.class}) +public class DynamicTemplatesORHLCIntegrationTests extends DynamicTemplatesContextBaseTests { + @Configuration + @Import({ OpenSearchRestTemplateConfiguration.class }) + static class Config { + @Bean + IndexNameProvider indexNameProvider() { + return new IndexNameProvider("dynamic-templates-os"); + } + } +} diff --git a/spring-data-opensearch/src/test/java/org/opensearch/data/client/core/index/DynamicTemplatesOSCIntegrationTests.java b/spring-data-opensearch/src/test/java/org/opensearch/data/client/core/index/DynamicTemplatesOSCIntegrationTests.java new file mode 100644 index 00000000..4e333a3c --- /dev/null +++ b/spring-data-opensearch/src/test/java/org/opensearch/data/client/core/index/DynamicTemplatesOSCIntegrationTests.java @@ -0,0 +1,29 @@ +/* + * Copyright OpenSearch Contributors + * 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.data.client.core.index; + +import org.opensearch.data.client.junit.jupiter.OpenSearchTemplateConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.data.elasticsearch.utils.IndexNameProvider; +import org.springframework.test.context.ContextConfiguration; + +@ContextConfiguration(classes = {DynamicTemplatesOSCIntegrationTests.Config.class}) +public class DynamicTemplatesOSCIntegrationTests extends DynamicTemplatesContextBaseTests { + @Configuration + @Import({OpenSearchTemplateConfiguration.class}) + static class Config { + @Bean + IndexNameProvider indexNameProvider() { + return new IndexNameProvider("dynamic-templates-os"); + } + } +} diff --git a/spring-data-opensearch/src/test/resources/mappings/test-dynamic_templates_mappings.json b/spring-data-opensearch/src/test/resources/mappings/test-dynamic_templates_mappings.json index 61c84778..67680c13 100644 --- a/spring-data-opensearch/src/test/resources/mappings/test-dynamic_templates_mappings.json +++ b/spring-data-opensearch/src/test/resources/mappings/test-dynamic_templates_mappings.json @@ -3,7 +3,7 @@ { "with_custom_analyzer": { "mapping": { - "type": "string", + "type": "text", "analyzer": "standard_lowercase_asciifolding" }, "path_match": "names.*" diff --git a/spring-data-opensearch/src/test/resources/mappings/test-dynamic_templates_mappings_two.json b/spring-data-opensearch/src/test/resources/mappings/test-dynamic_templates_mappings_two.json index 32ffe560..7c80cf73 100644 --- a/spring-data-opensearch/src/test/resources/mappings/test-dynamic_templates_mappings_two.json +++ b/spring-data-opensearch/src/test/resources/mappings/test-dynamic_templates_mappings_two.json @@ -1,21 +1,17 @@ { "dynamic_templates": [ { - "with_custom_analyzer": { + "keywords_without_doc_values": { + "match_mapping_type": "string", "mapping": { - "type": "string", - "analyzer": "standard_lowercase_asciifolding" + "fields": { + "keyword": { + "type": "keyword", + "doc_values": false + } + } }, - "path_match": "names.*" - } - }, - { - "participantA1_with_custom_analyzer": { - "mapping": { - "type": "string", - "analyzer": "standard_lowercase_asciifolding" - }, - "path_match": "participantA1.*" + "path_match": "others.*" } } ] From 85d566ebc0f9a473e3145188229332c9e479f743 Mon Sep 17 00:00:00 2001 From: Andriy Redko Date: Mon, 7 Apr 2025 19:06:41 -0400 Subject: [PATCH 2/3] Address code review comments Signed-off-by: Andriy Redko --- .../DynamicTemplatesContextBaseTests.java | 32 ++++++++++++++++--- .../test-dynamic_templates_mappings.json | 2 +- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/spring-data-opensearch/src/test/java/org/opensearch/data/client/core/index/DynamicTemplatesContextBaseTests.java b/spring-data-opensearch/src/test/java/org/opensearch/data/client/core/index/DynamicTemplatesContextBaseTests.java index 96fe03d1..8ae7d645 100644 --- a/spring-data-opensearch/src/test/java/org/opensearch/data/client/core/index/DynamicTemplatesContextBaseTests.java +++ b/spring-data-opensearch/src/test/java/org/opensearch/data/client/core/index/DynamicTemplatesContextBaseTests.java @@ -10,6 +10,8 @@ package org.opensearch.data.client.core.index; +import static org.assertj.core.api.Assertions.assertThat; + import java.util.HashMap; import java.util.Map; import org.junit.jupiter.api.AfterEach; @@ -24,6 +26,7 @@ import org.springframework.data.elasticsearch.core.ElasticsearchOperations; import org.springframework.data.elasticsearch.core.IndexOperations; import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; +import org.springframework.data.elasticsearch.core.query.Query; import org.springframework.data.elasticsearch.junit.jupiter.SpringIntegrationTest; import org.springframework.data.elasticsearch.utils.IndexNameProvider; import org.springframework.lang.Nullable; @@ -46,14 +49,20 @@ void cleanup() { @Test void shouldCreateDynamicTemplateOne() { IndexOperations indexOperations = operations.indexOps(SampleDynamicTemplatesEntity.class); - indexOperations.createWithMapping(); + assertThat(indexOperations.createWithMapping()).isTrue(); + + operations.save(new SampleDynamicTemplatesEntity(Map.of("John", "Smith"))); + assertThat(operations.search(Query.findAll(), SampleDynamicTemplatesEntity.class).get().count()).isEqualTo(1L); } @Test void shouldCreateDynamicTemplateTwo() { IndexOperations indexOperations = operations.indexOps(SampleDynamicTemplatesEntityTwo.class); - indexOperations.createWithMapping(); + assertThat(indexOperations.createWithMapping()).isTrue(); + + operations.save(new SampleDynamicTemplatesEntityTwo("Other string")); + assertThat(operations.search(Query.findAll(), SampleDynamicTemplatesEntityTwo.class).get().count()).isEqualTo(1L); } /** @@ -67,7 +76,15 @@ static class SampleDynamicTemplatesEntity { @Id private String id; @Nullable - @Field(type = FieldType.Object) private final Map names = new HashMap<>(); + @Field(type = FieldType.Object) private final Map names; + + public SampleDynamicTemplatesEntity() { + this(new HashMap<>()); + } + + public SampleDynamicTemplatesEntity(final Map names) { + this.names = names; + } } /** @@ -81,6 +98,13 @@ static class SampleDynamicTemplatesEntityTwo { @Id private String id; @Nullable - @Field(type = FieldType.Object) private final Map names = new HashMap<>(); + @Field(type = FieldType.Text) private String others; + + public SampleDynamicTemplatesEntityTwo() { + } + + public SampleDynamicTemplatesEntityTwo(final String others) { + this.others = others; + } } } diff --git a/spring-data-opensearch/src/test/resources/mappings/test-dynamic_templates_mappings.json b/spring-data-opensearch/src/test/resources/mappings/test-dynamic_templates_mappings.json index 67680c13..e46312d9 100644 --- a/spring-data-opensearch/src/test/resources/mappings/test-dynamic_templates_mappings.json +++ b/spring-data-opensearch/src/test/resources/mappings/test-dynamic_templates_mappings.json @@ -4,7 +4,7 @@ "with_custom_analyzer": { "mapping": { "type": "text", - "analyzer": "standard_lowercase_asciifolding" + "analyzer": "standard" }, "path_match": "names.*" } From 2e41846ce3cce90ac02eba57f899abb004c31afb Mon Sep 17 00:00:00 2001 From: Andriy Redko Date: Wed, 16 Apr 2025 10:06:27 -0400 Subject: [PATCH 3/3] Adapted test case to reproduce the issue with opensearch-java (https://github.com/opensearch-project/opensearch-java/issues/1513) Signed-off-by: Andriy Redko --- .../core/index/DynamicTemplatesContextBaseTests.java | 10 +++++----- .../mappings/test-dynamic_templates_mappings_two.json | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/spring-data-opensearch/src/test/java/org/opensearch/data/client/core/index/DynamicTemplatesContextBaseTests.java b/spring-data-opensearch/src/test/java/org/opensearch/data/client/core/index/DynamicTemplatesContextBaseTests.java index 8ae7d645..d31fe7a6 100644 --- a/spring-data-opensearch/src/test/java/org/opensearch/data/client/core/index/DynamicTemplatesContextBaseTests.java +++ b/spring-data-opensearch/src/test/java/org/opensearch/data/client/core/index/DynamicTemplatesContextBaseTests.java @@ -55,13 +55,12 @@ void shouldCreateDynamicTemplateOne() { assertThat(operations.search(Query.findAll(), SampleDynamicTemplatesEntity.class).get().count()).isEqualTo(1L); } - @Test void shouldCreateDynamicTemplateTwo() { IndexOperations indexOperations = operations.indexOps(SampleDynamicTemplatesEntityTwo.class); assertThat(indexOperations.createWithMapping()).isTrue(); - operations.save(new SampleDynamicTemplatesEntityTwo("Other string")); + operations.save(new SampleDynamicTemplatesEntityTwo(Map.of("first.last", "Smith"))); assertThat(operations.search(Query.findAll(), SampleDynamicTemplatesEntityTwo.class).get().count()).isEqualTo(1L); } @@ -98,13 +97,14 @@ static class SampleDynamicTemplatesEntityTwo { @Id private String id; @Nullable - @Field(type = FieldType.Text) private String others; + @Field(type = FieldType.Object) private final Map names; public SampleDynamicTemplatesEntityTwo() { + this(new HashMap<>()); } - public SampleDynamicTemplatesEntityTwo(final String others) { - this.others = others; + public SampleDynamicTemplatesEntityTwo(final Map names) { + this.names = names; } } } diff --git a/spring-data-opensearch/src/test/resources/mappings/test-dynamic_templates_mappings_two.json b/spring-data-opensearch/src/test/resources/mappings/test-dynamic_templates_mappings_two.json index 7c80cf73..5d428712 100644 --- a/spring-data-opensearch/src/test/resources/mappings/test-dynamic_templates_mappings_two.json +++ b/spring-data-opensearch/src/test/resources/mappings/test-dynamic_templates_mappings_two.json @@ -11,7 +11,7 @@ } } }, - "path_match": "others.*" + "path_match": "names.*" } } ]