From d3cabc6ea5e8e425b4e1d6db4592f43a2d868279 Mon Sep 17 00:00:00 2001 From: Peter-Josef Meisch Date: Sun, 28 Mar 2021 13:11:00 +0200 Subject: [PATCH] Improve Settings annotation. --- .../reference/elasticsearch-clients.adoc | 2 +- ...elasticsearch-migration-guide-4.1-4.2.adoc | 4 + .../reference/elasticsearch-misc.adoc | 52 +++- .../elasticsearch-object-mapping.adoc | 14 +- .../reference/elasticsearch-operations.adoc | 3 +- .../reference/elasticsearch-repositories.adoc | 4 +- .../ResourceFailureException.java | 31 ++ .../elasticsearch/annotations/Document.java | 16 + .../elasticsearch/annotations/Setting.java | 78 ++++- .../core/AbstractDefaultIndexOperations.java | 69 ++--- .../core/DefaultIndexOperations.java | 5 +- .../core/DefaultReactiveIndexOperations.java | 38 ++- .../core/DefaultTransportIndexOperations.java | 10 +- .../elasticsearch/core/IndexInformation.java | 9 +- .../elasticsearch/core/IndexOperations.java | 13 +- .../core/ReactiveIndexOperations.java | 13 +- .../core/ReactiveResourceUtil.java | 11 +- .../elasticsearch/core/RequestFactory.java | 17 +- .../data/elasticsearch/core/ResourceUtil.java | 20 +- .../elasticsearch/core/ResponseConverter.java | 41 +-- .../elasticsearch/core/document/Document.java | 246 +--------------- .../core/document/DocumentAdapters.java | 1 + .../core/document/MapDocument.java | 8 +- .../core/index/PutTemplateRequest.java | 14 +- .../elasticsearch/core/index/Settings.java | 50 ++++ .../core/index/TemplateData.java | 12 +- .../ElasticsearchPersistentEntity.java | 7 +- .../SimpleElasticsearchPersistentEntity.java | 214 +++++++++++--- .../support/DefaultStringObjectMap.java | 153 ++++++++++ .../support/StringObjectMap.java | 278 ++++++++++++++++++ .../data/elasticsearch/NestedObjectTests.java | 6 +- .../ComposableAnnotationsUnitTest.java | 5 +- ...eNestedElasticsearchRepositoriesTests.java | 2 +- .../EnableElasticsearchRepositoriesTests.java | 4 +- .../core/ElasticsearchRestTemplateTests.java | 2 +- .../core/ElasticsearchTemplateTests.java | 23 +- .../ElasticsearchTransportTemplateTests.java | 2 +- .../elasticsearch/core/LogEntityTests.java | 2 +- ...ElasticsearchTemplateIntegrationTests.java | 2 +- ...eactiveElasticsearchTemplateUnitTests.java | 2 +- .../core/ReactiveIndexOperationsTest.java | 16 +- .../core/ReactiveResourceUtilTest.java | 4 +- .../core/SearchAsYouTypeTests.java | 2 +- ...ElasticsearchTemplateAggregationTests.java | 2 +- .../ElasticsearchTemplateCompletionTests.java | 4 +- ...chTemplateCompletionWithContextsTests.java | 2 +- ...appingElasticsearchConverterUnitTests.java | 3 +- .../geo/ElasticsearchTemplateGeoTests.java | 4 +- .../index/MappingBuilderIntegrationTests.java | 59 ++-- .../core/index/MappingBuilderUnitTests.java | 16 +- .../SimpleDynamicTemplatesMappingTests.java | 7 +- .../SimpleElasticsearchDateMappingTests.java | 2 +- .../core/index/TemplateTests.java | 10 +- ...pleElasticsearchPersistentEntityTests.java | 249 ++++++++++------ .../query/CriteriaQueryIntegrationTests.java | 8 +- .../ElasticsearchOperationsRoutingTests.java | 4 +- ...veElasticsearchOperationsRoutingTests.java | 4 +- .../repositories/cdi/CdiRepositoryTests.java | 6 +- .../ComplexCustomMethodRepositoryTests.java | 6 +- ...stomMethodRepositoryManualWiringTests.java | 2 +- .../CustomMethodRepositoryBaseTests.java | 2 +- .../doubleid/DoubleIDRepositoryTests.java | 2 +- .../geo/SpringDataGeoRepositoryTests.java | 2 +- .../integer/IntegerIDRepositoryTests.java | 2 +- .../nestedobject/InnerObjectTests.java | 2 +- .../repositories/spel/SpELEntityTests.java | 2 +- .../UUIDElasticsearchRepositoryTests.java | 2 +- ...asticsearchRepositoriesRegistrarTests.java | 2 +- .../ElasticsearchStringQueryUnitTests.java | 4 +- ...tiveElasticsearchQueryMethodUnitTests.java | 4 +- ...tiveElasticsearchStringQueryUnitTests.java | 4 +- .../query/keywords/QueryKeywordsTests.java | 2 +- ...asticsearchRepositoryIntegrationTests.java | 2 +- ...eReactiveElasticsearchRepositoryTests.java | 2 +- 74 files changed, 1292 insertions(+), 635 deletions(-) create mode 100644 src/main/java/org/springframework/data/elasticsearch/ResourceFailureException.java create mode 100644 src/main/java/org/springframework/data/elasticsearch/core/index/Settings.java create mode 100644 src/main/java/org/springframework/data/elasticsearch/support/DefaultStringObjectMap.java create mode 100644 src/main/java/org/springframework/data/elasticsearch/support/StringObjectMap.java diff --git a/src/main/asciidoc/reference/elasticsearch-clients.adoc b/src/main/asciidoc/reference/elasticsearch-clients.adoc index 78695f489..62f5a23f8 100644 --- a/src/main/asciidoc/reference/elasticsearch-clients.adoc +++ b/src/main/asciidoc/reference/elasticsearch-clients.adoc @@ -8,7 +8,7 @@ Spring Data Elasticsearch operates upon an Elasticsearch client that is connecte [[elasticsearch.clients.transport]] == Transport Client -WARNING: The well known `TransportClient` is deprecated as of Elasticsearch 7 and will be removed in Elasticsearch 8. (https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/transport-client.html[see the Elasticsearch documentation]). Spring Data Elasticsearch will support the `TransportClient` as long as it is available in the used +WARNING: The `TransportClient` is deprecated as of Elasticsearch 7 and will be removed in Elasticsearch 8. (https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/transport-client.html[see the Elasticsearch documentation]). Spring Data Elasticsearch will support the `TransportClient` as long as it is available in the used Elasticsearch <> but has deprecated the classes using it since version 4.0. We strongly recommend to use the <> instead of the `TransportClient`. diff --git a/src/main/asciidoc/reference/elasticsearch-migration-guide-4.1-4.2.adoc b/src/main/asciidoc/reference/elasticsearch-migration-guide-4.1-4.2.adoc index 58bb48f10..860e09226 100644 --- a/src/main/asciidoc/reference/elasticsearch-migration-guide-4.1-4.2.adoc +++ b/src/main/asciidoc/reference/elasticsearch-migration-guide-4.1-4.2.adoc @@ -6,6 +6,10 @@ This section describes breaking changes from version 4.1.x to 4.2.x and how remo [[elasticsearch-migration-guide-4.1-4.2.deprecations]] == Deprecations +=== @Document parameters + +The parameters of the `@Document` annotation that are relevant for the index settings (`useServerConfiguration`, `shards`. `replicas`, `refreshIntervall` and `indexStoretype`) have been moved to the `@Setting` annotation. Use in `@Document` is still possible but deprecated. + [[elasticsearch-migration-guide-4.1-4.2.removal]] == Removals diff --git a/src/main/asciidoc/reference/elasticsearch-misc.adoc b/src/main/asciidoc/reference/elasticsearch-misc.adoc index b92cf1adf..042759e7c 100644 --- a/src/main/asciidoc/reference/elasticsearch-misc.adoc +++ b/src/main/asciidoc/reference/elasticsearch-misc.adoc @@ -4,6 +4,48 @@ This chapter covers additional support for Elasticsearch operations that cannot be directly accessed via the repository interface. It is recommended to add those operations as custom implementation as described in <> . +[[elasticsearc.misc.index.settings]] +== Index settings + +When creating Elasticsearch indices with Spring Data Elasticsearch different index settings can be defined by using the `@Setting` annotation. The following arguments are available: + +* `useServerConfiguration` does not send any settings parameters, so the Elasticsearch server configuration determines them. +* `settingPath` refers to a JSON file defining the settings that must be resolvable in the classpath +* `shards` the number of shards to use, defaults to _1_ +* `replicas` the number of replicas, defaults to _1_ +* `refreshIntervall`, defaults to _"1s"_ +* `indexStoreType`, defaults to _"fs"_ + + +It is as well possible to define https://www.elastic.co/guide/en/elasticsearch/reference/7.11/index-modules-index-sorting.html[index sorting] (check the linked Elasticsearch documentation for the possible field types and values): + +==== +[source,java] +---- +@Document(indexName = "entities") +@Setting( + sortFields = { "secondField", "firstField" }, <.> + sortModes = { Setting.SortMode.max, Setting.SortMode.min }, <.> + sortOrders = { Setting.SortOrder.desc, Setting.SortOrder.asc }, + sortMissingValues = { Setting.SortMissing._last, Setting.SortMissing._first }) +class Entity { + @Nullable + @Id private String id; + + @Nullable + @Field(name = "first_field", type = FieldType.Keyword) + private String firstField; + + @Nullable @Field(name = "second_field", type = FieldType.Keyword) + private String secondField; + + // getter and setter... +} +---- +<.> when defining sort fields, use the name of the Java property (_firstField_), not the name that might be defined for Elasticsearch (_first_field_) +<.> `sortModes`, `sortOrders` and `sortMissingValues` are optional, but if they are set, the number of entries must match the number of `sortFields` elements +==== + [[elasticsearch.misc.filter]] == Filter Builder @@ -20,7 +62,7 @@ SearchQuery searchQuery = new NativeSearchQueryBuilder() .withQuery(matchAllQuery()) .withFilter(boolFilter().must(termFilter("id", documentId))) .build(); - + Page sampleEntities = operations.searchForPage(searchQuery, SampleEntity.class, index); ---- ==== @@ -31,6 +73,7 @@ Page sampleEntities = operations.searchForPage(searchQuery, Sample Elasticsearch has a scroll API for getting big result set in chunks. This is internally used by Spring Data Elasticsearch to provide the implementations of the ` SearchHitsIterator SearchOperations.searchForStream(Query query, Class clazz, IndexCoordinates index)` method. +==== [source,java] ---- IndexCoordinates index = IndexCoordinates.of("sample-index"); @@ -50,9 +93,11 @@ while (stream.hasNext()) { stream.close(); ---- +==== There are no methods in the `SearchOperations` API to access the scroll id, if it should be necessary to access this, the following methods of the `ElasticsearchRestTemplate` can be used: +==== [source,java] ---- @@ -77,10 +122,12 @@ while (scroll.hasSearchHits()) { } template.searchScrollClear(scrollId); ---- +==== To use the Scroll API with repository methods, the return type must defined as `Stream` in the Elasticsearch Repository. The implementation of the method will then use the scroll methods from the ElasticsearchTemplate. +==== [source,java] ---- interface SampleEntityRepository extends Repository { @@ -89,6 +136,7 @@ interface SampleEntityRepository extends Repository { } ---- +==== [[elasticsearch.misc.sorts]] == Sort options @@ -97,7 +145,9 @@ In addition to the default sort options described <> @@ -71,13 +63,13 @@ The mapping metadata infrastructure is defined in a separate spring-data-commons ==== Date format mapping Properties that derive from `TemporalAccessor` or are of type `java.util.Date` must either have a `@Field` annotation -of type `FieldType.Date` or a custom converter must be registered for this type. This paragraph describes the use of +of type `FieldType.Date` or a custom converter must be registered for this type. This paragraph describes the use of `FieldType.Date`. -There are two attributes of the `@Field` annotation that define which date format information is written to the +There are two attributes of the `@Field` annotation that define which date format information is written to the mapping (also see https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-date-format.html#built-in-date-formats[Elasticsearch Built In Formats] and https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-date-format.html#custom-date-formats[Elasticsearch Custom Date Formats]) -The `format` attributes is used to define at least one of the predefined formats. If it is not defined, then a +The `format` attributes is used to define at least one of the predefined formats. If it is not defined, then a default value of __date_optional_time_ and _epoch_millis_ is used. The `pattern` attribute can be used to add additional custom format strings. If you want to use only custom date formats, you must set the `format` property to empty `{}`. diff --git a/src/main/asciidoc/reference/elasticsearch-operations.adoc b/src/main/asciidoc/reference/elasticsearch-operations.adoc index b1f55eaf1..1d213604c 100644 --- a/src/main/asciidoc/reference/elasticsearch-operations.adoc +++ b/src/main/asciidoc/reference/elasticsearch-operations.adoc @@ -21,7 +21,8 @@ The default implementations of the interfaces offer: ==== .Index management and automatic creation of indices and mappings. -The `IndexOperations` interface and the provided implementation which can be obtained from an `ElasticsearchOperations` instance - for example with a call to `operations.indexOps(clazz)`- give the user the ability to create indices, put mappings or store template and alias information in the Elasticsearch cluster. +The `IndexOperations` interface and the provided implementation which can be obtained from an `ElasticsearchOperations` instance - for example with a call to `operations.indexOps(clazz)`- give the user the ability to create indices, put mappings or store template and alias information in the Elasticsearch cluster. Details of the index that will be created +can be set by using the `@Setting` annotation, refer to <> for further information. **None of these operations are done automatically** by the implementations of `IndexOperations` or `ElasticsearchOperations`. It is the user's responsibility to call the methods. diff --git a/src/main/asciidoc/reference/elasticsearch-repositories.adoc b/src/main/asciidoc/reference/elasticsearch-repositories.adoc index 6fba3fd3a..c0b770538 100644 --- a/src/main/asciidoc/reference/elasticsearch-repositories.adoc +++ b/src/main/asciidoc/reference/elasticsearch-repositories.adoc @@ -31,7 +31,7 @@ class Book { The `@Document` annotation has an argument `createIndex`. If this argument is set to true - which is the default value - Spring Data Elasticsearch will during bootstrapping the repository support on application startup check if the index defined by the `@Document` annotation exists. -If it does not exist, the index will be created and the mappings derived from the entity's annotations (see <>) will be written to the newly created index. +If it does not exist, the index will be created and the mappings derived from the entity's annotations (see <>) will be written to the newly created index. Details of the index that will be created can be set by using the `@Setting` annotation, refer to <> for further information. include::elasticsearch-repository-queries.adoc[leveloffset=+1] @@ -131,7 +131,7 @@ class ProductService { public void setRepository(ProductRepository repository) { this.repository = repository; } -} +} ---- <1> Create a component by using the same calls as are used in the <> chapter. <2> Let the CDI framework inject the Repository into your class. diff --git a/src/main/java/org/springframework/data/elasticsearch/ResourceFailureException.java b/src/main/java/org/springframework/data/elasticsearch/ResourceFailureException.java new file mode 100644 index 000000000..cd23381ba --- /dev/null +++ b/src/main/java/org/springframework/data/elasticsearch/ResourceFailureException.java @@ -0,0 +1,31 @@ +/* + * Copyright 2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.elasticsearch; + +import org.springframework.core.NestedRuntimeException; + +/** + * @author Peter-Josef Meisch + */ +public class ResourceFailureException extends NestedRuntimeException { + public ResourceFailureException(String msg) { + super(msg); + } + + public ResourceFailureException(String msg, Throwable cause) { + super(msg, cause); + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/Document.java b/src/main/java/org/springframework/data/elasticsearch/annotations/Document.java index 59458b11d..ae53f190d 100644 --- a/src/main/java/org/springframework/data/elasticsearch/annotations/Document.java +++ b/src/main/java/org/springframework/data/elasticsearch/annotations/Document.java @@ -55,29 +55,45 @@ /** * Use server-side settings when creating the index. + * + * @deprecated since 4.2, use the {@link Setting} annotation to configure settings */ + @Deprecated boolean useServerConfiguration() default false; /** * Number of shards for the index {@link #indexName()}. Used for index creation.
* With version 4.0, the default value is changed from 5 to 1 to reflect the change in the default settings of * Elasticsearch which changed to 1 as well in Elasticsearch 7.0. + * ComposableAnnotationsUnitTest.documentAnnotationShouldBeComposable:60 + * + * @deprecated since 4.2, use the {@link Setting} annotation to configure settings */ + @Deprecated short shards() default 1; /** * Number of replicas for the index {@link #indexName()}. Used for index creation. + * + * @deprecated since 4.2, use the {@link Setting} annotation to configure settings */ + @Deprecated short replicas() default 1; /** * Refresh interval for the index {@link #indexName()}. Used for index creation. + * + * @deprecated since 4.2, use the {@link Setting} annotation to configure settings */ + @Deprecated String refreshInterval() default "1s"; /** * Index storage type for the index {@link #indexName()}. Used for index creation. + * + * @deprecated since 4.2, use the {@link Setting} annotation to configure settings */ + @Deprecated String indexStoreType() default "fs"; /** diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/Setting.java b/src/main/java/org/springframework/data/elasticsearch/annotations/Setting.java index 864637550..c2b836d34 100644 --- a/src/main/java/org/springframework/data/elasticsearch/annotations/Setting.java +++ b/src/main/java/org/springframework/data/elasticsearch/annotations/Setting.java @@ -15,7 +15,11 @@ */ package org.springframework.data.elasticsearch.annotations; -import java.lang.annotation.*; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; import org.springframework.data.annotation.Persistent; @@ -23,14 +27,84 @@ * Elasticsearch Setting * * @author Mohsin Husen + * @author Peter-Josef Meisch */ @Persistent @Inherited @Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE}) +@Target({ ElementType.TYPE }) public @interface Setting { + /** + * Resource path for a settings configuration + */ String settingPath() default ""; + /** + * Use server-side settings when creating the index. + */ + boolean useServerConfiguration() default false; + + /** + * Number of shards for the index. Used for index creation.
+ * With version 4.0, the default value is changed from 5 to 1 to reflect the change in the default settings of + * Elasticsearch which changed to 1 as well in Elasticsearch 7.0. + */ + short shards() default 1; + + /** + * Number of replicas for the index. Used for index creation. + */ + short replicas() default 1; + + /** + * Refresh interval for the index. Used for index creation. + */ + String refreshInterval() default "1s"; + + /** + * Index storage type for the index. Used for index creation. + */ + String indexStoreType() default "fs"; + + /** + * fields to define an index sorting + * + * @since 4.2 + */ + String[] sortFields() default {}; + + /** + * defines the order for {@link #sortFields()}. If present, it must have the same number of elements + * + * @since 4.2 + */ + SortOrder[] sortOrders() default {}; + + /** + * defines the mode for {@link #sortFields()}. If present, it must have the same number of elements + * + * @since 4.2 + */ + SortMode[] sortModes() default {}; + + /** + * defines the missing value for {@link #sortFields()}. If present, it must have the same number of elements + * + * @since 4.2 + */ + SortMissing[] sortMissingValues() default {}; + + enum SortOrder { + asc, desc + } + + enum SortMode { + min, max + } + + enum SortMissing { + _last, _first + } } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/AbstractDefaultIndexOperations.java b/src/main/java/org/springframework/data/elasticsearch/core/AbstractDefaultIndexOperations.java index b2da38a7a..ee5e2af3a 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/AbstractDefaultIndexOperations.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/AbstractDefaultIndexOperations.java @@ -29,17 +29,16 @@ import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.elasticsearch.UncategorizedElasticsearchException; import org.springframework.data.elasticsearch.annotations.Mapping; -import org.springframework.data.elasticsearch.annotations.Setting; import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter; import org.springframework.data.elasticsearch.core.document.Document; import org.springframework.data.elasticsearch.core.index.AliasData; import org.springframework.data.elasticsearch.core.index.MappingBuilder; +import org.springframework.data.elasticsearch.core.index.Settings; import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity; import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.core.query.AliasQuery; import org.springframework.lang.Nullable; import org.springframework.util.Assert; -import org.springframework.util.StringUtils; /** * Base implementation of {@link IndexOperations} common to Transport and Rest based Implementations of IndexOperations. @@ -90,33 +89,20 @@ protected Class checkForBoundClass() { @Override public boolean create() { - Document settings = null; - - if (boundClass != null) { - settings = createSettings(boundClass); - } - + Settings settings = boundClass != null ? createSettings(boundClass) : new Settings(); return doCreate(getIndexCoordinates(), settings, null); } @Override - public Document createSettings(Class clazz) { + public Settings createSettings(Class clazz) { Assert.notNull(clazz, "clazz must not be null"); - Document settings = null; - - Setting setting = AnnotatedElementUtils.findMergedAnnotation(clazz, Setting.class); - - if (setting != null) { - settings = loadSettings(setting.settingPath()); - } - - if (settings == null) { - settings = getRequiredPersistentEntity(clazz).getDefaultSettings(); - } - - return settings; + ElasticsearchPersistentEntity persistentEntity = getRequiredPersistentEntity(clazz); + String settingPath = persistentEntity.settingPath(); + return hasText(settingPath) // + ? Settings.parse(ResourceUtil.readFileFromClasspath(settingPath)) // + : persistentEntity.getDefaultSettings(); } @Override @@ -125,16 +111,23 @@ public boolean createWithMapping() { } @Override - public boolean create(Document settings) { + public boolean create(Map settings) { + + Assert.notNull(settings, "settings must not be null"); + return doCreate(getIndexCoordinates(), settings, null); } @Override - public boolean create(Document settings, Document mapping) { + public boolean create(Map settings, Document mapping) { + + Assert.notNull(settings, "settings must not be null"); + Assert.notNull(mapping, "mapping must not be null"); + return doCreate(getIndexCoordinates(), settings, mapping); } - protected abstract boolean doCreate(IndexCoordinates index, @Nullable Document settings, @Nullable Document mapping); + protected abstract boolean doCreate(IndexCoordinates index, Map settings, @Nullable Document mapping); @Override public boolean delete() { @@ -165,16 +158,16 @@ public Map getMapping() { abstract protected Map doGetMapping(IndexCoordinates index); @Override - public Map getSettings() { + public Settings getSettings() { return getSettings(false); } @Override - public Map getSettings(boolean includeDefaults) { + public Settings getSettings(boolean includeDefaults) { return doGetSettings(getIndexCoordinates(), includeDefaults); } - protected abstract Map doGetSettings(IndexCoordinates index, boolean includeDefaults); + protected abstract Settings doGetSettings(IndexCoordinates index, boolean includeDefaults); @Override public void refresh() { @@ -244,10 +237,10 @@ protected Document buildMapping(Class clazz) { if (mappingAnnotation != null) { String mappingPath = mappingAnnotation.mappingPath(); - if (StringUtils.hasText(mappingPath)) { + if (hasText(mappingPath)) { String mappings = ResourceUtil.readFileFromClasspath(mappingPath); - if (StringUtils.hasText(mappings)) { + if (hasText(mappings)) { return Document.parse(mappings); } } else { @@ -265,7 +258,7 @@ protected Document buildMapping(Class clazz) { } @Override - public Document createSettings() { + public Settings createSettings() { return createSettings(checkForBoundClass()); } @@ -284,19 +277,5 @@ public IndexCoordinates getIndexCoordinates() { public IndexCoordinates getIndexCoordinatesFor(Class clazz) { return getRequiredPersistentEntity(clazz).getIndexCoordinates(); } - - @Nullable - private Document loadSettings(String settingPath) { - if (hasText(settingPath)) { - String settingsFile = ResourceUtil.readFileFromClasspath(settingPath); - - if (hasText(settingsFile)) { - return Document.parse(settingsFile); - } - } else { - LOGGER.info("settingPath in @Setting has to be defined. Using default instead."); - } - return null; - } // endregion } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/DefaultIndexOperations.java b/src/main/java/org/springframework/data/elasticsearch/core/DefaultIndexOperations.java index 3355aab4a..ae0121243 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/DefaultIndexOperations.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/DefaultIndexOperations.java @@ -50,6 +50,7 @@ import org.springframework.data.elasticsearch.core.index.ExistsTemplateRequest; import org.springframework.data.elasticsearch.core.index.GetTemplateRequest; import org.springframework.data.elasticsearch.core.index.PutTemplateRequest; +import org.springframework.data.elasticsearch.core.index.Settings; import org.springframework.data.elasticsearch.core.index.TemplateData; import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.core.query.AliasQuery; @@ -81,7 +82,7 @@ public DefaultIndexOperations(ElasticsearchRestTemplate restTemplate, IndexCoord } @Override - protected boolean doCreate(IndexCoordinates index, @Nullable Document settings, @Nullable Document mapping) { + protected boolean doCreate(IndexCoordinates index, Map settings, @Nullable Document mapping) { CreateIndexRequest request = requestFactory.createIndexRequest(index, settings, mapping); return restTemplate.execute(client -> client.indices().create(request, RequestOptions.DEFAULT).isAcknowledged()); } @@ -192,7 +193,7 @@ public boolean alias(AliasActions aliasActions) { } @Override - protected Map doGetSettings(IndexCoordinates index, boolean includeDefaults) { + protected Settings doGetSettings(IndexCoordinates index, boolean includeDefaults) { Assert.notNull(index, "index must not be null"); diff --git a/src/main/java/org/springframework/data/elasticsearch/core/DefaultReactiveIndexOperations.java b/src/main/java/org/springframework/data/elasticsearch/core/DefaultReactiveIndexOperations.java index 50cad41f7..a1aae3f59 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/DefaultReactiveIndexOperations.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/DefaultReactiveIndexOperations.java @@ -42,7 +42,6 @@ import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.elasticsearch.NoSuchIndexException; import org.springframework.data.elasticsearch.annotations.Mapping; -import org.springframework.data.elasticsearch.annotations.Setting; import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter; import org.springframework.data.elasticsearch.core.document.Document; import org.springframework.data.elasticsearch.core.index.AliasActions; @@ -52,6 +51,7 @@ import org.springframework.data.elasticsearch.core.index.GetTemplateRequest; import org.springframework.data.elasticsearch.core.index.MappingBuilder; import org.springframework.data.elasticsearch.core.index.PutTemplateRequest; +import org.springframework.data.elasticsearch.core.index.Settings; import org.springframework.data.elasticsearch.core.index.TemplateData; import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity; import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; @@ -106,7 +106,7 @@ public Mono create() { if (boundClass != null) { return createSettings(boundClass).flatMap(settings -> doCreate(index, settings, null)); } else { - return doCreate(index, null, null); + return doCreate(index, new Settings(), null); } } @@ -119,16 +119,23 @@ public Mono createWithMapping() { } @Override - public Mono create(Document settings) { + public Mono create(Map settings) { + + Assert.notNull(settings, "settings must not be null"); + return doCreate(getIndexCoordinates(), settings, null); } @Override - public Mono create(Document settings, Document mapping) { - throw new UnsupportedOperationException("not implemented"); + public Mono create(Map settings, Document mapping) { + + Assert.notNull(settings, "settings must not be null"); + Assert.notNull(mapping, "mapping must not be null"); + + return doCreate(getIndexCoordinates(), settings, mapping); } - private Mono doCreate(IndexCoordinates index, @Nullable Document settings, @Nullable Document mapping) { + private Mono doCreate(IndexCoordinates index, Map settings, @Nullable Document mapping) { CreateIndexRequest request = requestFactory.createIndexRequest(index, settings, mapping); return Mono.from(operations.executeWithIndicesClient(client -> client.createIndex(request))); @@ -208,24 +215,25 @@ public Mono getMapping() { // region settings @Override - public Mono createSettings() { + public Mono createSettings() { return createSettings(checkForBoundClass()); } @Override - public Mono createSettings(Class clazz) { + public Mono createSettings(Class clazz) { - Setting setting = AnnotatedElementUtils.findMergedAnnotation(clazz, Setting.class); - - if (setting != null) { - return loadDocument(setting.settingPath(), "@Setting"); - } + Assert.notNull(clazz, "clazz must not be null"); - return Mono.just(getRequiredPersistentEntity(clazz).getDefaultSettings()); + ElasticsearchPersistentEntity persistentEntity = getRequiredPersistentEntity(clazz); + String settingPath = persistentEntity.settingPath(); + return hasText(settingPath) // + ? loadDocument(settingPath, "@Setting") // + .map(Settings::new) // + : Mono.just(persistentEntity.getDefaultSettings()); } @Override - public Mono getSettings(boolean includeDefaults) { + public Mono getSettings(boolean includeDefaults) { String indexName = getIndexCoordinates().getIndexName(); GetSettingsRequest request = requestFactory.getSettingsRequest(indexName, includeDefaults); diff --git a/src/main/java/org/springframework/data/elasticsearch/core/DefaultTransportIndexOperations.java b/src/main/java/org/springframework/data/elasticsearch/core/DefaultTransportIndexOperations.java index df49ac0b7..a13924666 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/DefaultTransportIndexOperations.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/DefaultTransportIndexOperations.java @@ -46,7 +46,6 @@ import org.elasticsearch.cluster.metadata.MappingMetadata; import org.elasticsearch.common.collect.ImmutableOpenMap; import org.elasticsearch.common.compress.CompressedXContent; -import org.elasticsearch.common.settings.Settings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter; @@ -57,6 +56,7 @@ import org.springframework.data.elasticsearch.core.index.ExistsTemplateRequest; import org.springframework.data.elasticsearch.core.index.GetTemplateRequest; import org.springframework.data.elasticsearch.core.index.PutTemplateRequest; +import org.springframework.data.elasticsearch.core.index.Settings; import org.springframework.data.elasticsearch.core.index.TemplateData; import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.core.query.AliasQuery; @@ -90,7 +90,7 @@ public DefaultTransportIndexOperations(Client client, ElasticsearchConverter ela } @Override - protected boolean doCreate(IndexCoordinates index, @Nullable Document settings, @Nullable Document mapping) { + protected boolean doCreate(IndexCoordinates index, Map settings, @Nullable Document mapping) { CreateIndexRequestBuilder createIndexRequestBuilder = requestFactory.createIndexRequestBuilder(client, index, settings, mapping); return createIndexRequestBuilder.execute().actionGet().isAcknowledged(); @@ -193,7 +193,7 @@ public boolean alias(AliasActions aliasActions) { } @Override - protected Map doGetSettings(IndexCoordinates index, boolean includeDefaults) { + protected Settings doGetSettings(IndexCoordinates index, boolean includeDefaults) { Assert.notNull(index, "index must not be null"); @@ -238,8 +238,8 @@ public TemplateData getTemplate(GetTemplateRequest getTemplateRequest) { if (indexTemplateMetadata.getName().equals(getTemplateRequest.getTemplateName())) { - Document settings = Document.create(); - Settings templateSettings = indexTemplateMetadata.settings(); + Settings settings = new Settings(); + org.elasticsearch.common.settings.Settings templateSettings = indexTemplateMetadata.settings(); templateSettings.keySet().forEach(key -> settings.put(key, templateSettings.get(key))); Map aliases = new LinkedHashMap<>(); diff --git a/src/main/java/org/springframework/data/elasticsearch/core/IndexInformation.java b/src/main/java/org/springframework/data/elasticsearch/core/IndexInformation.java index f10c824bc..1dca1d323 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/IndexInformation.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/IndexInformation.java @@ -20,6 +20,7 @@ import org.springframework.data.elasticsearch.core.document.Document; import org.springframework.data.elasticsearch.core.index.AliasData; +import org.springframework.data.elasticsearch.core.index.Settings; import org.springframework.lang.Nullable; /** @@ -31,16 +32,16 @@ */ public class IndexInformation { private final String name; - @Nullable private final Document settings; + @Nullable private final Settings settings; @Nullable private final Document mapping; @Nullable private final List aliases; - public static IndexInformation of(String name, @Nullable Document settings, @Nullable Document mapping, + public static IndexInformation of(String name, @Nullable Settings settings, @Nullable Document mapping, @Nullable List aliases) { return new IndexInformation(name, settings, mapping, aliases); } - private IndexInformation(String name, @Nullable Document settings, @Nullable Document mapping, + private IndexInformation(String name, @Nullable Settings settings, @Nullable Document mapping, @Nullable List aliases) { this.name = name; this.settings = settings; @@ -58,7 +59,7 @@ public Document getMapping() { } @Nullable - public Document getSettings() { + public Settings getSettings() { return settings; } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/IndexOperations.java b/src/main/java/org/springframework/data/elasticsearch/core/IndexOperations.java index 8d28bb2db..cb1f39f19 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/IndexOperations.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/IndexOperations.java @@ -27,6 +27,7 @@ import org.springframework.data.elasticsearch.core.index.ExistsTemplateRequest; import org.springframework.data.elasticsearch.core.index.GetTemplateRequest; import org.springframework.data.elasticsearch.core.index.PutTemplateRequest; +import org.springframework.data.elasticsearch.core.index.Settings; import org.springframework.data.elasticsearch.core.index.TemplateData; import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.core.query.AliasQuery; @@ -60,7 +61,7 @@ public interface IndexOperations { * @param settings the index settings * @return {@literal true} if the index was created */ - boolean create(Document settings); + boolean create(Map settings); /** * Create an index for given settings and mapping. @@ -70,7 +71,7 @@ public interface IndexOperations { * @return {@literal true} if the index was created * @since 4.2 */ - boolean create(Document settings, Document mapping); + boolean create(Map settings, Document mapping); /** * Create an index with the settings and mapping defined for the entity this IndexOperations is bound to. @@ -161,7 +162,7 @@ default boolean putMapping(Class clazz) { * @return a settings document. * @since 4.1 */ - Document createSettings(); + Settings createSettings(); /** * Creates the index settings from the annotations on the given class @@ -170,14 +171,14 @@ default boolean putMapping(Class clazz) { * @return a settings document. * @since 4.1 */ - Document createSettings(Class clazz); + Settings createSettings(Class clazz); /** * Get the index settings. * * @return the settings */ - Map getSettings(); + Settings getSettings(); /** * Get the index settings. @@ -185,7 +186,7 @@ default boolean putMapping(Class clazz) { * @param includeDefaults whether or not to include all the default settings * @return the settings */ - Map getSettings(boolean includeDefaults); + Settings getSettings(boolean includeDefaults); // endregion // region aliases diff --git a/src/main/java/org/springframework/data/elasticsearch/core/ReactiveIndexOperations.java b/src/main/java/org/springframework/data/elasticsearch/core/ReactiveIndexOperations.java index 684756203..7b4afbc67 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/ReactiveIndexOperations.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/ReactiveIndexOperations.java @@ -28,6 +28,7 @@ import org.springframework.data.elasticsearch.core.index.ExistsTemplateRequest; import org.springframework.data.elasticsearch.core.index.GetTemplateRequest; import org.springframework.data.elasticsearch.core.index.PutTemplateRequest; +import org.springframework.data.elasticsearch.core.index.Settings; import org.springframework.data.elasticsearch.core.index.TemplateData; import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; @@ -56,7 +57,7 @@ public interface ReactiveIndexOperations { * @return a {@link Mono} signalling successful operation completion or an {@link Mono#error(Throwable) error} if eg. * the index already exist. */ - Mono create(Document settings); + Mono create(Map settings); /** * Create an index for given settings and mapping. @@ -67,7 +68,7 @@ public interface ReactiveIndexOperations { * the index already exist. * @since 4.2 */ - Mono create(Document settings, Document mapping); + Mono create(Map settings, Document mapping); /** * Create an index with the settings and mapping defined for the entity this IndexOperations is bound to. @@ -159,7 +160,7 @@ default Mono putMapping(Class clazz) { * @return a settings document. * @since 4.1 */ - Mono createSettings(); + Mono createSettings(); /** * Creates the index settings from the annotations on the given class @@ -168,14 +169,14 @@ default Mono putMapping(Class clazz) { * @return a settings document. * @since 4.1 */ - Mono createSettings(Class clazz); + Mono createSettings(Class clazz); /** * get the settings for the index * * @return a {@link Mono} with a {@link Document} containing the index settings */ - default Mono getSettings() { + default Mono getSettings() { return getSettings(false); } @@ -185,7 +186,7 @@ default Mono getSettings() { * @param includeDefaults whether or not to include all the default settings * @return a {@link Mono} with a {@link Document} containing the index settings */ - Mono getSettings(boolean includeDefaults); + Mono getSettings(boolean includeDefaults); // endregion // region aliases diff --git a/src/main/java/org/springframework/data/elasticsearch/core/ReactiveResourceUtil.java b/src/main/java/org/springframework/data/elasticsearch/core/ReactiveResourceUtil.java index 9a373e101..1598b17fe 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/ReactiveResourceUtil.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/ReactiveResourceUtil.java @@ -27,6 +27,8 @@ import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.buffer.DataBufferUtils; import org.springframework.core.io.buffer.DefaultDataBufferFactory; +import org.springframework.data.elasticsearch.ResourceFailureException; +import org.springframework.util.Assert; /** * Utility to reactively read {@link org.springframework.core.io.Resource}s. @@ -47,6 +49,8 @@ public abstract class ReactiveResourceUtil { */ public static Mono readFileFromClasspath(String url) { + Assert.notNull(url, "url must not be null"); + return DataBufferUtils .join(DataBufferUtils.read(new ClassPathResource(url), new DefaultDataBufferFactory(), BUFFER_SIZE)) . handle((it, sink) -> { @@ -65,15 +69,12 @@ public static Mono readFileFromClasspath(String url) { sink.next(sb.toString()); sink.complete(); } catch (Exception e) { - LOGGER.warn(String.format("Failed to load file from url: %s: %s", url, e.getMessage())); sink.complete(); } finally { DataBufferUtils.release(it); } - }).onErrorResume(throwable -> { - LOGGER.warn(String.format("Failed to load file from url: %s: %s", url, throwable.getMessage())); - return Mono.empty(); - }); + }).onErrorResume( + throwable -> Mono.error(new ResourceFailureException("Could not load resource from " + url, throwable))); } // Utility constructor diff --git a/src/main/java/org/springframework/data/elasticsearch/core/RequestFactory.java b/src/main/java/org/springframework/data/elasticsearch/core/RequestFactory.java index f8c3145d0..ca2ca2314 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/RequestFactory.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/RequestFactory.java @@ -355,11 +355,14 @@ public BulkRequestBuilder bulkRequestBuilder(Client client, List queries, Bul // region index management - public CreateIndexRequest createIndexRequest(IndexCoordinates index, @Nullable Document settings, - @Nullable Document mapping) { + public CreateIndexRequest createIndexRequest(IndexCoordinates index, Map settings, @Nullable Document mapping) { + + Assert.notNull(index, "index must not be null"); + Assert.notNull(settings, "settings must not be null"); + CreateIndexRequest request = new CreateIndexRequest(index.getIndexName()); - if (settings != null && !settings.isEmpty()) { + if (!settings.isEmpty()) { request.settings(settings); } @@ -371,13 +374,15 @@ public CreateIndexRequest createIndexRequest(IndexCoordinates index, @Nullable D } public CreateIndexRequestBuilder createIndexRequestBuilder(Client client, IndexCoordinates index, - @Nullable Document settings, @Nullable Document mapping) { + Map settings, @Nullable Document mapping) { + + Assert.notNull(index, "index must not be null"); + Assert.notNull(settings, "settings must not be null"); String indexName = index.getIndexName(); CreateIndexRequestBuilder createIndexRequestBuilder = client.admin().indices().prepareCreate(indexName); - if (settings != null && !settings.isEmpty()) { - + if (!settings.isEmpty()) { createIndexRequestBuilder.setSettings(settings); } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/ResourceUtil.java b/src/main/java/org/springframework/data/elasticsearch/core/ResourceUtil.java index 92eeb27e8..9b92ed5bb 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/ResourceUtil.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/ResourceUtil.java @@ -18,10 +18,9 @@ import java.io.InputStream; import java.nio.charset.Charset; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.core.io.ClassPathResource; -import org.springframework.lang.Nullable; +import org.springframework.data.elasticsearch.ResourceFailureException; +import org.springframework.util.Assert; import org.springframework.util.StreamUtils; /** @@ -33,23 +32,20 @@ */ public abstract class ResourceUtil { - private static final Logger LOGGER = LoggerFactory.getLogger(ResourceUtil.class); - /** * Read a {@link ClassPathResource} into a {@link String}. * - * @param url url the file url - * @return the contents of the file or null if it could not be read + * @param url url the resource + * @return the contents of the resource */ - @Nullable public static String readFileFromClasspath(String url) { - ClassPathResource classPathResource = new ClassPathResource(url); - try (InputStream is = classPathResource.getInputStream()) { + Assert.notNull(url, "url must not be null"); + + try (InputStream is = new ClassPathResource(url).getInputStream()) { return StreamUtils.copyToString(is, Charset.defaultCharset()); } catch (Exception e) { - LOGGER.warn(String.format("Failed to load file from url: %s: %s", url, e.getMessage())); - return null; + throw new ResourceFailureException("Could not load resource from " + url, e); } } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/ResponseConverter.java b/src/main/java/org/springframework/data/elasticsearch/core/ResponseConverter.java index c2328aad2..546109602 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/ResponseConverter.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/ResponseConverter.java @@ -36,9 +36,9 @@ import org.elasticsearch.cluster.metadata.MappingMetadata; import org.elasticsearch.common.collect.ImmutableOpenMap; import org.elasticsearch.common.compress.CompressedXContent; -import org.elasticsearch.common.settings.Settings; import org.springframework.data.elasticsearch.core.document.Document; import org.springframework.data.elasticsearch.core.index.AliasData; +import org.springframework.data.elasticsearch.core.index.Settings; import org.springframework.data.elasticsearch.core.index.TemplateData; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -91,7 +91,7 @@ public static List getIndexInformations(GetIndexResponse getIn List indexInformationList = new ArrayList<>(); for (String indexName : getIndexResponse.getIndices()) { - Document settings = settingsFromGetIndexResponse(getIndexResponse, indexName); + Settings settings = settingsFromGetIndexResponse(getIndexResponse, indexName); Document mappings = mappingsFromGetIndexResponse(getIndexResponse, indexName); List aliases = aliasDataFromIndexResponse(getIndexResponse, indexName); @@ -108,18 +108,18 @@ public static List getIndexInformations(GetIndexResponse getIn * @param indexName the index name * @return a document that represents {@link Settings} */ - private static Document settingsFromGetIndexResponse(GetIndexResponse getIndexResponse, String indexName) { - Document document = Document.create(); + private static Settings settingsFromGetIndexResponse(GetIndexResponse getIndexResponse, String indexName) { + Settings settings= new Settings(); - Settings indexSettings = getIndexResponse.getSettings().get(indexName); + org.elasticsearch.common.settings.Settings indexSettings = getIndexResponse.getSettings().get(indexName); if (!indexSettings.isEmpty()) { for (String key : indexSettings.keySet()) { - document.put(key, indexSettings.get(key)); + settings.put(key, indexSettings.get(key)); } } - return document; + return settings; } /** @@ -162,7 +162,7 @@ public static List getIndexInformations( List indexInformationList = new ArrayList<>(); for (String indexName : getIndexResponse.getIndices()) { - Document settings = settingsFromGetIndexResponse(getIndexResponse, indexName); + Settings settings = settingsFromGetIndexResponse(getIndexResponse, indexName); Document mappings = mappingsFromGetIndexResponse(getIndexResponse, indexName); List aliases = aliasDataFromIndexResponse(getIndexResponse, indexName); @@ -172,19 +172,20 @@ public static List getIndexInformations( return indexInformationList; } - private static Document settingsFromGetIndexResponse( + private static Settings settingsFromGetIndexResponse( org.elasticsearch.action.admin.indices.get.GetIndexResponse getIndexResponse, String indexName) { - Document document = Document.create(); + + Settings settings = new Settings(); if (getIndexResponse.getSettings().containsKey(indexName)) { - Settings indexSettings = getIndexResponse.getSettings().get(indexName); + org.elasticsearch.common.settings.Settings indexSettings = getIndexResponse.getSettings().get(indexName); for (String key : indexSettings.keySet()) { - document.put(key, indexSettings.get(key)); + settings.put(key, indexSettings.get(key)); } } - return document; + return settings; } private static Document mappingsFromGetIndexResponse( @@ -222,8 +223,8 @@ public static TemplateData getTemplateData(GetIndexTemplatesResponse getIndexTem if (indexTemplateMetadata.name().equals(templateName)) { - Document settings = Document.create(); - Settings templateSettings = indexTemplateMetadata.settings(); + Settings settings = new Settings(); + org.elasticsearch.common.settings.Settings templateSettings = indexTemplateMetadata.settings(); templateSettings.keySet().forEach(key -> settings.put(key, templateSettings.get(key))); Map aliases = new LinkedHashMap<>(); @@ -253,21 +254,21 @@ public static TemplateData getTemplateData(GetIndexTemplatesResponse getIndexTem * * @param response the Elasticsearch response * @param indexName the index name - * @return settings as {@link Document} + * @return settings */ - public static Document fromSettingsResponse(GetSettingsResponse response, String indexName) { + public static Settings fromSettingsResponse(GetSettingsResponse response, String indexName) { - Document settings = Document.create(); + Settings settings = new Settings(); if (!response.getIndexToDefaultSettings().isEmpty()) { - Settings defaultSettings = response.getIndexToDefaultSettings().get(indexName); + org.elasticsearch.common.settings.Settings defaultSettings = response.getIndexToDefaultSettings().get(indexName); for (String key : defaultSettings.keySet()) { settings.put(key, defaultSettings.get(key)); } } if (!response.getIndexToSettings().isEmpty()) { - Settings customSettings = response.getIndexToSettings().get(indexName); + org.elasticsearch.common.settings.Settings customSettings = response.getIndexToSettings().get(indexName); for (String key : customSettings.keySet()) { settings.put(key, customSettings.get(key)); } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/document/Document.java b/src/main/java/org/springframework/data/elasticsearch/core/document/Document.java index 08dccaf6a..25af888b6 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/document/Document.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/document/Document.java @@ -25,11 +25,12 @@ import java.util.function.Supplier; import org.springframework.data.elasticsearch.core.convert.ConversionException; +import org.springframework.data.elasticsearch.support.StringObjectMap; import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** - * A representation of a Elasticsearch document as extended {@link Map} with {@link String} keys. All iterators preserve + * A representation of a Elasticsearch document as extended {@link StringObjectMap Map}. All iterators preserve * original insertion order. *

* Document does not allow {@code null} keys. It allows {@literal null} values. @@ -42,7 +43,7 @@ * @author Roman Puchkovskiy * @since 4.0 */ -public interface Document extends Map { +public interface Document extends StringObjectMap { /** * Create a new mutable {@link Document}. @@ -80,25 +81,19 @@ static Document parse(String json) { Assert.notNull(json, "JSON must not be null"); + return new MapDocument().fromJson(json); + } + + @Override + default Document fromJson(String json) { + Assert.notNull(json, "JSON must not be null"); + + clear(); try { - return new MapDocument(MapDocument.OBJECT_MAPPER.readerFor(Map.class).readValue(json)); + putAll(MapDocument.OBJECT_MAPPER.readerFor(Map.class).readValue(json)); } catch (IOException e) { throw new ConversionException("Cannot parse JSON", e); } - } - - /** - * {@link #put(Object, Object)} the {@code key}/{@code value} tuple and return {@code this} {@link Document}. - * - * @param key key with which the specified value is to be associated. must not be {@literal null}. - * @param value value to be associated with the specified key. - * @return {@code this} {@link Document}. - */ - default Document append(String key, Object value) { - - Assert.notNull(key, "Key must not be null"); - - put(key, value); return this; } @@ -122,7 +117,7 @@ default String getIndex() { /** * Sets the index name for this document - * + * * @param index index name *

* The default implementation throws {@link UnsupportedOperationException}. @@ -251,212 +246,6 @@ default void setPrimaryTerm(long primaryTerm) { throw new UnsupportedOperationException(); } - /** - * Returns the value to which the specified {@code key} is mapped, or {@literal null} if this document contains no - * mapping for the key. The value is casted within the method which makes it useful for calling code as it does not - * require casting on the calling side. If the value type is not assignable to {@code type}, then this method throws - * {@link ClassCastException}. - * - * @param key the key whose associated value is to be returned - * @param type the expected return value type. - * @param expected return type. - * @return the value to which the specified key is mapped, or {@literal null} if this document contains no mapping for - * the key. - * @throws ClassCastException if the value of the given key is not of {@code type T}. - */ - @Nullable - default T get(Object key, Class type) { - - Assert.notNull(key, "Key must not be null"); - Assert.notNull(type, "Type must not be null"); - - return type.cast(get(key)); - } - - /** - * Returns the value to which the specified {@code key} is mapped, or {@literal null} if this document contains no - * mapping for the key. If the value type is not a {@link Boolean}, then this method throws - * {@link ClassCastException}. - * - * @param key the key whose associated value is to be returned - * @return the value to which the specified key is mapped, or {@literal null} if this document contains no mapping for - * the key. - * @throws ClassCastException if the value of the given key is not a {@link Boolean}. - */ - @Nullable - default Boolean getBoolean(String key) { - return get(key, Boolean.class); - } - - /** - * Returns the value to which the specified {@code key} is mapped or {@code defaultValue} if this document contains no - * mapping for the key. If the value type is not a {@link Boolean}, then this method throws - * {@link ClassCastException}. - * - * @param key the key whose associated value is to be returned - * @return the value to which the specified key is mapped or {@code defaultValue} if this document contains no mapping - * for the key. - * @throws ClassCastException if the value of the given key is not a {@link Boolean}. - */ - default boolean getBooleanOrDefault(String key, boolean defaultValue) { - return getBooleanOrDefault(key, () -> defaultValue); - } - - /** - * Returns the value to which the specified {@code key} is mapped or the value from {@code defaultValue} if this - * document contains no mapping for the key. If the value type is not a {@link Boolean}, then this method throws - * {@link ClassCastException}. - * - * @param key the key whose associated value is to be returned - * @return the value to which the specified key is mapped or the value from {@code defaultValue} if this document - * contains no mapping for the key. - * @throws ClassCastException if the value of the given key is not a {@link Boolean}. - * @see BooleanSupplier - */ - default boolean getBooleanOrDefault(String key, BooleanSupplier defaultValue) { - - Boolean value = getBoolean(key); - - return value == null ? defaultValue.getAsBoolean() : value; - } - - /** - * Returns the value to which the specified {@code key} is mapped, or {@literal null} if this document contains no - * mapping for the key. If the value type is not a {@link Integer}, then this method throws - * {@link ClassCastException}. - * - * @param key the key whose associated value is to be returned - * @return the value to which the specified key is mapped, or {@literal null} if this document contains no mapping for - * the key. - * @throws ClassCastException if the value of the given key is not a {@link Integer}. - */ - @Nullable - default Integer getInt(String key) { - return get(key, Integer.class); - } - - /** - * Returns the value to which the specified {@code key} is mapped or {@code defaultValue} if this document contains no - * mapping for the key. If the value type is not a {@link Integer}, then this method throws - * {@link ClassCastException}. - * - * @param key the key whose associated value is to be returned - * @return the value to which the specified key is mapped or {@code defaultValue} if this document contains no mapping - * for the key. - * @throws ClassCastException if the value of the given key is not a {@link Integer}. - */ - default int getIntOrDefault(String key, int defaultValue) { - return getIntOrDefault(key, () -> defaultValue); - } - - /** - * Returns the value to which the specified {@code key} is mapped or the value from {@code defaultValue} if this - * document contains no mapping for the key. If the value type is not a {@link Integer}, then this method throws - * {@link ClassCastException}. - * - * @param key the key whose associated value is to be returned - * @return the value to which the specified key is mapped or the value from {@code defaultValue} if this document - * contains no mapping for the key. - * @throws ClassCastException if the value of the given key is not a {@link Integer}. - * @see IntSupplier - */ - default int getIntOrDefault(String key, IntSupplier defaultValue) { - - Integer value = getInt(key); - - return value == null ? defaultValue.getAsInt() : value; - } - - /** - * Returns the value to which the specified {@code key} is mapped, or {@literal null} if this document contains no - * mapping for the key. If the value type is not a {@link Long}, then this method throws {@link ClassCastException}. - * - * @param key the key whose associated value is to be returned - * @return the value to which the specified key is mapped, or {@literal null} if this document contains no mapping for - * the key. - * @throws ClassCastException if the value of the given key is not a {@link Long}. - */ - @Nullable - default Long getLong(String key) { - return get(key, Long.class); - } - - /** - * Returns the value to which the specified {@code key} is mapped or {@code defaultValue} if this document contains no - * mapping for the key. If the value type is not a {@link Long}, then this method throws {@link ClassCastException}. - * - * @param key the key whose associated value is to be returned - * @return the value to which the specified key is mapped or {@code defaultValue} if this document contains no mapping - * for the key. - * @throws ClassCastException if the value of the given key is not a {@link Long}. - */ - default long getLongOrDefault(String key, long defaultValue) { - return getLongOrDefault(key, () -> defaultValue); - } - - /** - * Returns the value to which the specified {@code key} is mapped or the value from {@code defaultValue} if this - * document contains no mapping for the key. If the value type is not a {@link Long}, then this method throws - * {@link ClassCastException}. - * - * @param key the key whose associated value is to be returned - * @return the value to which the specified key is mapped or the value from {@code defaultValue} if this document - * contains no mapping for the key. - * @throws ClassCastException if the value of the given key is not a {@link Long}. - * @see LongSupplier - */ - default long getLongOrDefault(String key, LongSupplier defaultValue) { - - Long value = getLong(key); - - return value == null ? defaultValue.getAsLong() : value; - } - - /** - * Returns the value to which the specified {@code key} is mapped, or {@literal null} if this document contains no - * mapping for the key. If the value type is not a {@link String}, then this method throws {@link ClassCastException}. - * - * @param key the key whose associated value is to be returned - * @return the value to which the specified key is mapped, or {@literal null} if this document contains no mapping for - * the key. - * @throws ClassCastException if the value of the given key is not a {@link String}. - */ - @Nullable - default String getString(String key) { - return get(key, String.class); - } - - /** - * Returns the value to which the specified {@code key} is mapped or {@code defaultValue} if this document contains no - * mapping for the key. If the value type is not a {@link String}, then this method throws {@link ClassCastException}. - * - * @param key the key whose associated value is to be returned - * @return the value to which the specified key is mapped or {@code defaultValue} if this document contains no mapping - * for the key. - * @throws ClassCastException if the value of the given key is not a {@link String}. - */ - default String getStringOrDefault(String key, String defaultValue) { - return getStringOrDefault(key, () -> defaultValue); - } - - /** - * Returns the value to which the specified {@code key} is mapped or the value from {@code defaultValue} if this - * document contains no mapping for the key. If the value type is not a {@link String}, then this method throws - * {@link ClassCastException}. - * - * @param key the key whose associated value is to be returned - * @return the value to which the specified key is mapped or the value from {@code defaultValue} if this document - * contains no mapping for the key. - * @throws ClassCastException if the value of the given key is not a {@link String}. - * @see Supplier - */ - default String getStringOrDefault(String key, Supplier defaultValue) { - - String value = getString(key); - - return value == null ? defaultValue.get() : value; - } - /** * This method allows the application of a function to {@code this} {@link Document}. The function should expect a * single {@link Document} argument and produce an {@code R} result. @@ -474,13 +263,4 @@ default R transform(Function transformer) { return transformer.apply(this); } - - /** - * Render this {@link Document} to JSON. Auxiliary values such as Id and version are not considered within the JSON - * representation. - * - * @return a JSON representation of this document. - */ - String toJson(); - } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/document/DocumentAdapters.java b/src/main/java/org/springframework/data/elasticsearch/core/document/DocumentAdapters.java index 11b07c774..a60be02a0 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/document/DocumentAdapters.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/document/DocumentAdapters.java @@ -458,6 +458,7 @@ public String toJson() { } } + @Override public String toString() { return getClass().getSimpleName() + '@' + this.id + '#' + this.version + ' ' + toJson(); diff --git a/src/main/java/org/springframework/data/elasticsearch/core/document/MapDocument.java b/src/main/java/org/springframework/data/elasticsearch/core/document/MapDocument.java index 12597eb39..847066717 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/document/MapDocument.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/document/MapDocument.java @@ -21,6 +21,8 @@ import java.util.Set; import java.util.function.BiConsumer; +import org.springframework.data.elasticsearch.support.DefaultStringObjectMap; +import org.springframework.data.elasticsearch.support.StringObjectMap; import org.springframework.data.mapping.MappingException; import org.springframework.lang.Nullable; @@ -38,7 +40,7 @@ class MapDocument implements Document { static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); - private final LinkedHashMap documentAsMap; + private final DefaultStringObjectMap documentAsMap; private @Nullable String index; private @Nullable String id; @@ -50,8 +52,8 @@ class MapDocument implements Document { this(new LinkedHashMap<>()); } - MapDocument(Map documentAsMap) { - this.documentAsMap = new LinkedHashMap<>(documentAsMap); + MapDocument(Map documentAsMap) { + this.documentAsMap = new DefaultStringObjectMap<>(documentAsMap); } @Override diff --git a/src/main/java/org/springframework/data/elasticsearch/core/index/PutTemplateRequest.java b/src/main/java/org/springframework/data/elasticsearch/core/index/PutTemplateRequest.java index 36a6a736d..c3c14aaeb 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/index/PutTemplateRequest.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/index/PutTemplateRequest.java @@ -19,6 +19,8 @@ import org.springframework.lang.Nullable; import org.springframework.util.Assert; +import java.util.Map; + /** * Request to create an index template. This is to create legacy templates (@see * https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-templates-v1.html) @@ -29,13 +31,13 @@ public class PutTemplateRequest { private final String name; private final String[] indexPatterns; - @Nullable final private Document settings; + @Nullable final private Settings settings; @Nullable final private Document mappings; @Nullable final AliasActions aliasActions; private final int order; @Nullable final Integer version; - private PutTemplateRequest(String name, String[] indexPatterns, @Nullable Document settings, + private PutTemplateRequest(String name, String[] indexPatterns, @Nullable Settings settings, @Nullable Document mappings, @Nullable AliasActions aliasActions, int order, @Nullable Integer version) { this.name = name; this.indexPatterns = indexPatterns; @@ -55,7 +57,7 @@ public String[] getIndexPatterns() { } @Nullable - public Document getSettings() { + public Settings getSettings() { return settings; } @@ -85,7 +87,7 @@ public static TemplateRequestBuilder builder(String name, String... indexPattern public static final class TemplateRequestBuilder { private final String name; private final String[] indexPatterns; - @Nullable private Document settings; + @Nullable private Settings settings; @Nullable private Document mappings; @Nullable AliasActions aliasActions; private int order = 0; @@ -100,8 +102,8 @@ private TemplateRequestBuilder(String name, String... indexPatterns) { this.indexPatterns = indexPatterns; } - public TemplateRequestBuilder withSettings(Document settings) { - this.settings = settings; + public TemplateRequestBuilder withSettings(Map settings) { + this.settings = new Settings(settings); return this; } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/index/Settings.java b/src/main/java/org/springframework/data/elasticsearch/core/index/Settings.java new file mode 100644 index 000000000..77b005175 --- /dev/null +++ b/src/main/java/org/springframework/data/elasticsearch/core/index/Settings.java @@ -0,0 +1,50 @@ +/* + * Copyright 2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.elasticsearch.core.index; + +import org.springframework.data.elasticsearch.support.DefaultStringObjectMap; + +import java.util.Map; + +/** + * class defining the settings for an index. + * + * @author Peter-Josef Meisch + * @since 4.2 + */ +public class Settings extends DefaultStringObjectMap { + + public Settings() { + } + + public Settings(Map map) { + super(map); + } + + /** + * Creates a {@link Settings} object from the given JSON String + * @param json must not be {@literal null} + * @return Settings object + */ + public static Settings parse(String json) { + return new Settings().fromJson(json); + } + + @Override + public String toString() { + return "Settings: " + toJson(); + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/index/TemplateData.java b/src/main/java/org/springframework/data/elasticsearch/core/index/TemplateData.java index 12809e2b1..98bfadcdc 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/index/TemplateData.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/index/TemplateData.java @@ -27,13 +27,13 @@ */ public class TemplateData { @Nullable private final String[] indexPatterns; - @Nullable Document settings; + @Nullable Settings settings; @Nullable Document mapping; @Nullable private final Map aliases; int order; @Nullable Integer version; - private TemplateData(@Nullable String[] indexPatterns, @Nullable Document settings, @Nullable Document mapping, + private TemplateData(@Nullable String[] indexPatterns, @Nullable Settings settings, @Nullable Document mapping, @Nullable Map aliases, int order, @Nullable Integer version) { this.indexPatterns = indexPatterns; this.settings = settings; @@ -53,7 +53,7 @@ public String[] getIndexPatterns() { } @Nullable - public Document getSettings() { + public Settings getSettings() { return settings; } @@ -77,7 +77,7 @@ public Integer getVersion() { } public static final class TemplateDataBuilder { - @Nullable Document settings; + @Nullable Settings settings; @Nullable Document mapping; int order; @Nullable Integer version; @@ -91,8 +91,8 @@ public TemplateDataBuilder withIndexPatterns(String[] indexPatterns) { return this; } - public TemplateDataBuilder withSettings(Document settings) { - this.settings = settings; + public TemplateDataBuilder withSettings(Map settings) { + this.settings = new Settings(settings); return this; } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentEntity.java b/src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentEntity.java index 6dc85e57c..28550d508 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentEntity.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentEntity.java @@ -18,6 +18,7 @@ import org.elasticsearch.index.VersionType; import org.springframework.data.elasticsearch.annotations.Field; import org.springframework.data.elasticsearch.core.document.Document; +import org.springframework.data.elasticsearch.core.index.Settings; import org.springframework.data.elasticsearch.core.join.JoinField; import org.springframework.data.elasticsearch.core.query.SeqNoPrimaryTerm; import org.springframework.data.mapping.PersistentEntity; @@ -148,14 +149,14 @@ default ElasticsearchPersistentProperty getRequiredSeqNoPrimaryTermProperty() { /** * returns the default settings for an index. * - * @return settings as {@link Document} + * @return settings * @since 4.1 */ - Document getDefaultSettings(); + Settings getDefaultSettings(); /** * Resolves the routing for a bean. - * + * * @param bean the bean to resolve the routing for * @return routing value, may be {@literal null} */ diff --git a/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentEntity.java b/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentEntity.java index bf277e6a9..345d83819 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentEntity.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentEntity.java @@ -19,16 +19,18 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicReference; -import org.elasticsearch.common.collect.MapBuilder; import org.elasticsearch.index.VersionType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.annotation.AnnotatedElementUtils; import org.springframework.dao.InvalidDataAccessApiUsageException; +import org.springframework.data.elasticsearch.annotations.Document; +import org.springframework.data.elasticsearch.annotations.Field; +import org.springframework.data.elasticsearch.annotations.FieldType; import org.springframework.data.elasticsearch.annotations.Parent; import org.springframework.data.elasticsearch.annotations.Routing; import org.springframework.data.elasticsearch.annotations.Setting; -import org.springframework.data.elasticsearch.core.document.Document; +import org.springframework.data.elasticsearch.core.index.Settings; import org.springframework.data.elasticsearch.core.join.JoinField; import org.springframework.data.mapping.MappingException; import org.springframework.data.mapping.PropertyHandler; @@ -66,16 +68,11 @@ public class SimpleElasticsearchPersistentEntity extends BasicPersistentEntit private static final SpelExpressionParser PARSER = new SpelExpressionParser(); private @Nullable String indexName; - private boolean useServerConfiguration; - private short shards; - private short replicas; - private @Nullable String refreshInterval; - private @Nullable String indexStoreType; + private final Lazy settingsParameter; @Deprecated private @Nullable String parentType; @Deprecated private @Nullable ElasticsearchPersistentProperty parentIdProperty; private @Nullable ElasticsearchPersistentProperty seqNoPrimaryTermProperty; private @Nullable ElasticsearchPersistentProperty joinFieldProperty; - private @Nullable String settingPath; private @Nullable VersionType versionType; private boolean createIndexAndMapping; private final Map fieldNamePropertyCache = new ConcurrentHashMap<>(); @@ -90,27 +87,20 @@ public SimpleElasticsearchPersistentEntity(TypeInformation typeInformation) { super(typeInformation); Class clazz = typeInformation.getType(); + org.springframework.data.elasticsearch.annotations.Document document = AnnotatedElementUtils .findMergedAnnotation(clazz, org.springframework.data.elasticsearch.annotations.Document.class); + // need a Lazy here, because we need the persistent properties available + this.settingsParameter = Lazy.of(() -> buildSettingsParameter(clazz)); + if (document != null) { Assert.hasText(document.indexName(), " Unknown indexName. Make sure the indexName is defined. e.g @Document(indexName=\"foo\")"); this.indexName = document.indexName(); - this.useServerConfiguration = document.useServerConfiguration(); - this.shards = document.shards(); - this.replicas = document.replicas(); - this.refreshInterval = document.refreshInterval(); - this.indexStoreType = document.indexStoreType(); this.versionType = document.versionType(); this.createIndexAndMapping = document.createIndex(); - - Setting setting = AnnotatedElementUtils.getMergedAnnotation(clazz, Setting.class); - - if (setting != null) { - this.settingPath = setting.settingPath(); - } } Routing routingAnnotation = AnnotatedElementUtils.findMergedAnnotation(clazz, Routing.class); @@ -135,28 +125,28 @@ public IndexCoordinates getIndexCoordinates() { @Nullable @Override public String getIndexStoreType() { - return indexStoreType; + return settingsParameter.get().indexStoreType; } @Override public short getShards() { - return shards; + return settingsParameter.get().shards; } @Override public short getReplicas() { - return replicas; + return settingsParameter.get().replicas; } @Override public boolean isUseServerConfiguration() { - return useServerConfiguration; + return settingsParameter.get().useServerConfiguration; } @Nullable @Override public String getRefreshInterval() { - return refreshInterval; + return settingsParameter.get().refreshIntervall; } @Nullable @@ -179,11 +169,6 @@ public VersionType getVersionType() { return versionType; } - @Override - public String settingPath() { - return settingPath; - } - @Override public boolean isCreateIndexAndMapping() { return createIndexAndMapping; @@ -207,7 +192,10 @@ public void addPersistentProperty(ElasticsearchPersistentProperty property) { Parent parentAnnotation = property.findAnnotation(Parent.class); this.parentIdProperty = property; - this.parentType = parentAnnotation.type(); + + if (parentAnnotation != null) { + this.parentType = parentAnnotation.type(); + } } if (property.isSeqNoPrimaryTermProperty()) { @@ -407,17 +395,167 @@ public String resolveRouting(T bean) { // endregion + // region index settings + @Override + public String settingPath() { + return settingsParameter.get().settingPath; + } + @Override - public Document getDefaultSettings() { + public Settings getDefaultSettings() { + return settingsParameter.get().toSettings(); // + } + + private SettingsParameter buildSettingsParameter(Class clazz) { + + SettingsParameter settingsParameter = new SettingsParameter(); + Document documentAnnotation = AnnotatedElementUtils.findMergedAnnotation(clazz, Document.class); + Setting settingAnnotation = AnnotatedElementUtils.findMergedAnnotation(clazz, Setting.class); + + if (documentAnnotation != null) { + settingsParameter.useServerConfiguration = documentAnnotation.useServerConfiguration(); + settingsParameter.shards = documentAnnotation.shards(); + settingsParameter.replicas = documentAnnotation.replicas(); + settingsParameter.refreshIntervall = documentAnnotation.refreshInterval(); + settingsParameter.indexStoreType = documentAnnotation.indexStoreType(); + } + + if (settingAnnotation != null) { + processSettingAnnotation(settingAnnotation, settingsParameter); + } + + return settingsParameter; + } + + private void processSettingAnnotation(Setting settingAnnotation, SettingsParameter settingsParameter) { + settingsParameter.useServerConfiguration = settingAnnotation.useServerConfiguration(); + settingsParameter.settingPath = settingAnnotation.settingPath(); + settingsParameter.shards = settingAnnotation.shards(); + settingsParameter.replicas = settingAnnotation.replicas(); + settingsParameter.refreshIntervall = settingAnnotation.refreshInterval(); + settingsParameter.indexStoreType = settingAnnotation.indexStoreType(); + + String[] sortFields = settingAnnotation.sortFields(); + + if (sortFields.length > 0) { + String[] fieldNames = new String[sortFields.length]; + int index = 0; + for (String propertyName : sortFields) { + ElasticsearchPersistentProperty property = getPersistentProperty(propertyName); + + if (property == null) { + throw new IllegalArgumentException("sortField property " + propertyName + " not found"); + } + Field fieldAnnotation = property.getRequiredAnnotation(Field.class); + + FieldType fieldType = fieldAnnotation.type(); + switch (fieldType) { + case Boolean: + case Long: + case Integer: + case Short: + case Byte: + case Float: + case Half_Float: + case Scaled_Float: + case Date: + case Date_Nanos: + case Keyword: + break; + default: + throw new IllegalArgumentException("field type " + fieldType + " not allowed for sortField"); + } + + if (!fieldAnnotation.docValues()) { + throw new IllegalArgumentException("doc_values must be set to true for sortField"); + } + fieldNames[index++] = property.getFieldName(); + } + settingsParameter.sortFields = fieldNames; - if (isUseServerConfiguration()) { - return Document.create(); + Setting.SortOrder[] sortOrders = settingAnnotation.sortOrders(); + if (sortOrders.length > 0) { + + if (sortOrders.length != sortFields.length) { + throw new IllegalArgumentException("@Settings parameter sortFields and sortOrders must have the same size"); + } + settingsParameter.sortOrders = sortOrders; + } + + Setting.SortMode[] sortModes = settingAnnotation.sortModes(); + if (sortModes.length > 0) { + + if (sortModes.length != sortFields.length) { + throw new IllegalArgumentException("@Settings parameter sortFields and sortModes must have the same size"); + } + settingsParameter.sortModes = sortModes; + } + + Setting.SortMissing[] sortMissingValues = settingAnnotation.sortMissingValues(); + if (sortMissingValues.length > 0) { + + if (sortMissingValues.length != sortFields.length) { + throw new IllegalArgumentException( + "@Settings parameter sortFields and sortMissingValues must have the same size"); + } + settingsParameter.sortMissingValues = sortMissingValues; + } } + } + + /** + * internal class to collect settings values from the {@link Document} and {@link Setting} annotations- + */ + private static class SettingsParameter { + boolean useServerConfiguration = false; + @Nullable String settingPath; + short shards; + short replicas; + @Nullable String refreshIntervall; + @Nullable String indexStoreType; + @Nullable private String[] sortFields; + @Nullable private Setting.SortOrder[] sortOrders; + @Nullable private Setting.SortMode[] sortModes; + @Nullable private Setting.SortMissing[] sortMissingValues; + + Settings toSettings() { + + if (useServerConfiguration) { + return new Settings(); + } + + Settings settings = new Settings() // + .append("index.number_of_shards", String.valueOf(shards)) + .append("index.number_of_replicas", String.valueOf(replicas)); - Map map = new MapBuilder() - .put("index.number_of_shards", String.valueOf(getShards())) - .put("index.number_of_replicas", String.valueOf(getReplicas())) - .put("index.refresh_interval", getRefreshInterval()).put("index.store.type", getIndexStoreType()).map(); - return Document.from(map); + if (refreshIntervall != null) { + settings.append("index.refresh_interval", refreshIntervall); + } + + if (indexStoreType != null) { + settings.append("index.store.type", indexStoreType); + } + + if (sortFields != null && sortFields.length > 0) { + settings.append("index.sort.field", sortFields); + + if (sortOrders != null && sortOrders.length > 0) { + settings.append("index.sort.order", sortOrders); + } + + if (sortModes != null && sortModes.length > 0) { + settings.append("index.sort.mode", sortModes); + } + + if (sortMissingValues != null && sortMissingValues.length > 0) { + settings.append("index.sort.missing", sortMissingValues); + } + } + + return settings; // + + } } + + // endregion } diff --git a/src/main/java/org/springframework/data/elasticsearch/support/DefaultStringObjectMap.java b/src/main/java/org/springframework/data/elasticsearch/support/DefaultStringObjectMap.java new file mode 100644 index 000000000..f467d4763 --- /dev/null +++ b/src/main/java/org/springframework/data/elasticsearch/support/DefaultStringObjectMap.java @@ -0,0 +1,153 @@ +/* + * Copyright 2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.elasticsearch.support; + +import java.io.IOException; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; +import java.util.function.BiConsumer; + +import org.springframework.util.Assert; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * @author Peter-Josef Meisch + */ +public class DefaultStringObjectMap> implements StringObjectMap { + + static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + private final LinkedHashMap delegate; + + public DefaultStringObjectMap() { + this(new LinkedHashMap<>()); + } + + public DefaultStringObjectMap(Map map) { + this.delegate = new LinkedHashMap<>(map); + } + + @Override + public String toJson() { + try { + return OBJECT_MAPPER.writeValueAsString(this); + } catch (JsonProcessingException e) { + throw new IllegalArgumentException("Cannot render document to JSON", e); + } + } + + @Override + public T fromJson(String json) { + + Assert.notNull(json, "JSON must not be null"); + + delegate.clear(); + try { + delegate.putAll(OBJECT_MAPPER.readerFor(Map.class).readValue(json)); + } catch (IOException e) { + throw new IllegalArgumentException("Cannot parse JSON", e); + } + return (T) this; + } + + @Override + public int size() { + return delegate.size(); + } + + @Override + public boolean isEmpty() { + return delegate.isEmpty(); + } + + @Override + public boolean containsKey(Object key) { + return delegate.containsKey(key); + } + + @Override + public boolean containsValue(Object value) { + return delegate.containsValue(value); + } + + @Override + public Object get(Object key) { + return delegate.get(key); + } + + @Override + public Object getOrDefault(Object key, Object defaultValue) { + return delegate.getOrDefault(key, defaultValue); + } + + @Override + public Object put(String key, Object value) { + return delegate.put(key, value); + } + + @Override + public Object remove(Object key) { + return delegate.remove(key); + } + + @Override + public void putAll(Map m) { + delegate.putAll(m); + } + + @Override + public void clear() { + delegate.clear(); + } + + @Override + public Set keySet() { + return delegate.keySet(); + } + + @Override + public Collection values() { + return delegate.values(); + } + + @Override + public Set> entrySet() { + return delegate.entrySet(); + } + + @Override + public boolean equals(Object o) { + return delegate.equals(o); + } + + @Override + public int hashCode() { + return delegate.hashCode(); + } + + @Override + public void forEach(BiConsumer action) { + delegate.forEach(action); + } + + @Override + public String toString() { + return "DefaultStringObjectMap: " + toJson(); + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/support/StringObjectMap.java b/src/main/java/org/springframework/data/elasticsearch/support/StringObjectMap.java new file mode 100644 index 000000000..0636369d4 --- /dev/null +++ b/src/main/java/org/springframework/data/elasticsearch/support/StringObjectMap.java @@ -0,0 +1,278 @@ +/* + * Copyright 2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.elasticsearch.support; + +import java.util.Map; +import java.util.function.BooleanSupplier; +import java.util.function.IntSupplier; +import java.util.function.LongSupplier; +import java.util.function.Supplier; + +import org.springframework.data.elasticsearch.core.document.Document; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; + +/** + * Defines an interface for a Map<String, Object> with additional convenience methods. All iterators must preserve + * original insertion order. + *

+ * StringObjectMap does not allow {@code null} keys. It allows {@literal null} values. + *

+ * Implementing classes can bei either mutable or immutable. In case a subclass is immutable, its methods may throw + * {@link UnsupportedOperationException} when calling modifying methods. * + * + * @param the type extending this interface + * @author Peter-Josef Meisch + * @since 4.2 + */ +public interface StringObjectMap> extends Map { + /** + * {@link #put(Object, Object)} the {@code key}/{@code value} tuple and return {@code this} object. + * + * @param key key with which the specified value is to be associated. must not be {@literal null}. + * @param value value to be associated with the specified key. + * @return {@code this} object. + */ + default M append(String key, Object value) { + + Assert.notNull(key, "Key must not be null"); + + put(key, value); + // noinspection unchecked + return (M) this; + } + + /** + * Returns the value to which the specified {@code key} is mapped, or {@literal null} if this document contains no + * mapping for the key. The value is casted within the method which makes it useful for calling code as it does not + * require casting on the calling side. If the value type is not assignable to {@code type}, then this method throws + * {@link ClassCastException}. + * + * @param key the key whose associated value is to be returned + * @param type the expected return value type. + * @param expected return type. + * @return the value to which the specified key is mapped, or {@literal null} if this document contains no mapping for + * the key. + * @throws ClassCastException if the value of the given key is not of {@code type T}. + */ + @Nullable + default T get(Object key, Class type) { + + Assert.notNull(key, "Key must not be null"); + Assert.notNull(type, "Type must not be null"); + + return type.cast(get(key)); + } + + /** + * Returns the value to which the specified {@code key} is mapped, or {@literal null} if this document contains no + * mapping for the key. If the value type is not a {@link Boolean}, then this method throws + * {@link ClassCastException}. + * + * @param key the key whose associated value is to be returned + * @return the value to which the specified key is mapped, or {@literal null} if this document contains no mapping for + * the key. + * @throws ClassCastException if the value of the given key is not a {@link Boolean}. + */ + @Nullable + default Boolean getBoolean(String key) { + return get(key, Boolean.class); + } + + /** + * Returns the value to which the specified {@code key} is mapped or {@code defaultValue} if this document contains no + * mapping for the key. If the value type is not a {@link Boolean}, then this method throws + * {@link ClassCastException}. + * + * @param key the key whose associated value is to be returned + * @return the value to which the specified key is mapped or {@code defaultValue} if this document contains no mapping + * for the key. + * @throws ClassCastException if the value of the given key is not a {@link Boolean}. + */ + default boolean getBooleanOrDefault(String key, boolean defaultValue) { + return getBooleanOrDefault(key, () -> defaultValue); + } + + /** + * Returns the value to which the specified {@code key} is mapped or the value from {@code defaultValue} if this + * document contains no mapping for the key. If the value type is not a {@link Boolean}, then this method throws + * {@link ClassCastException}. + * + * @param key the key whose associated value is to be returned + * @return the value to which the specified key is mapped or the value from {@code defaultValue} if this document + * contains no mapping for the key. + * @throws ClassCastException if the value of the given key is not a {@link Boolean}. + * @see BooleanSupplier + */ + default boolean getBooleanOrDefault(String key, BooleanSupplier defaultValue) { + + Boolean value = getBoolean(key); + + return value == null ? defaultValue.getAsBoolean() : value; + } + + /** + * Returns the value to which the specified {@code key} is mapped, or {@literal null} if this document contains no + * mapping for the key. If the value type is not a {@link Integer}, then this method throws + * {@link ClassCastException}. + * + * @param key the key whose associated value is to be returned + * @return the value to which the specified key is mapped, or {@literal null} if this document contains no mapping for + * the key. + * @throws ClassCastException if the value of the given key is not a {@link Integer}. + */ + @Nullable + default Integer getInt(String key) { + return get(key, Integer.class); + } + + /** + * Returns the value to which the specified {@code key} is mapped or {@code defaultValue} if this document contains no + * mapping for the key. If the value type is not a {@link Integer}, then this method throws + * {@link ClassCastException}. + * + * @param key the key whose associated value is to be returned + * @return the value to which the specified key is mapped or {@code defaultValue} if this document contains no mapping + * for the key. + * @throws ClassCastException if the value of the given key is not a {@link Integer}. + */ + default int getIntOrDefault(String key, int defaultValue) { + return getIntOrDefault(key, () -> defaultValue); + } + + /** + * Returns the value to which the specified {@code key} is mapped or the value from {@code defaultValue} if this + * document contains no mapping for the key. If the value type is not a {@link Integer}, then this method throws + * {@link ClassCastException}. + * + * @param key the key whose associated value is to be returned + * @return the value to which the specified key is mapped or the value from {@code defaultValue} if this document + * contains no mapping for the key. + * @throws ClassCastException if the value of the given key is not a {@link Integer}. + * @see IntSupplier + */ + default int getIntOrDefault(String key, IntSupplier defaultValue) { + + Integer value = getInt(key); + + return value == null ? defaultValue.getAsInt() : value; + } + + /** + * Returns the value to which the specified {@code key} is mapped, or {@literal null} if this document contains no + * mapping for the key. If the value type is not a {@link Long}, then this method throws {@link ClassCastException}. + * + * @param key the key whose associated value is to be returned + * @return the value to which the specified key is mapped, or {@literal null} if this document contains no mapping for + * the key. + * @throws ClassCastException if the value of the given key is not a {@link Long}. + */ + @Nullable + default Long getLong(String key) { + return get(key, Long.class); + } + + /** + * Returns the value to which the specified {@code key} is mapped or {@code defaultValue} if this document contains no + * mapping for the key. If the value type is not a {@link Long}, then this method throws {@link ClassCastException}. + * + * @param key the key whose associated value is to be returned + * @return the value to which the specified key is mapped or {@code defaultValue} if this document contains no mapping + * for the key. + * @throws ClassCastException if the value of the given key is not a {@link Long}. + */ + default long getLongOrDefault(String key, long defaultValue) { + return getLongOrDefault(key, () -> defaultValue); + } + + /** + * Returns the value to which the specified {@code key} is mapped or the value from {@code defaultValue} if this + * document contains no mapping for the key. If the value type is not a {@link Long}, then this method throws + * {@link ClassCastException}. + * + * @param key the key whose associated value is to be returned + * @return the value to which the specified key is mapped or the value from {@code defaultValue} if this document + * contains no mapping for the key. + * @throws ClassCastException if the value of the given key is not a {@link Long}. + * @see LongSupplier + */ + default long getLongOrDefault(String key, LongSupplier defaultValue) { + + Long value = getLong(key); + + return value == null ? defaultValue.getAsLong() : value; + } + + /** + * Returns the value to which the specified {@code key} is mapped, or {@literal null} if this document contains no + * mapping for the key. If the value type is not a {@link String}, then this method throws {@link ClassCastException}. + * + * @param key the key whose associated value is to be returned + * @return the value to which the specified key is mapped, or {@literal null} if this document contains no mapping for + * the key. + * @throws ClassCastException if the value of the given key is not a {@link String}. + */ + @Nullable + default String getString(String key) { + return get(key, String.class); + } + + /** + * Returns the value to which the specified {@code key} is mapped or {@code defaultValue} if this document contains no + * mapping for the key. If the value type is not a {@link String}, then this method throws {@link ClassCastException}. + * + * @param key the key whose associated value is to be returned + * @return the value to which the specified key is mapped or {@code defaultValue} if this document contains no mapping + * for the key. + * @throws ClassCastException if the value of the given key is not a {@link String}. + */ + default String getStringOrDefault(String key, String defaultValue) { + return getStringOrDefault(key, () -> defaultValue); + } + + /** + * Returns the value to which the specified {@code key} is mapped or the value from {@code defaultValue} if this + * document contains no mapping for the key. If the value type is not a {@link String}, then this method throws + * {@link ClassCastException}. + * + * @param key the key whose associated value is to be returned + * @return the value to which the specified key is mapped or the value from {@code defaultValue} if this document + * contains no mapping for the key. + * @throws ClassCastException if the value of the given key is not a {@link String}. + * @see Supplier + */ + default String getStringOrDefault(String key, Supplier defaultValue) { + + String value = getString(key); + + return value == null ? defaultValue.get() : value; + } + + /** + * Render this {@link Document} to JSON. Auxiliary values such as Id and version are not considered within the JSON + * representation. + * + * @return a JSON representation of this document. + */ + String toJson(); + + /** + * initializes this object from the given JSON String. + * + * @param json must not be {@literal null} + */ + M fromJson(String json); +} diff --git a/src/test/java/org/springframework/data/elasticsearch/NestedObjectTests.java b/src/test/java/org/springframework/data/elasticsearch/NestedObjectTests.java index 6cc24ff90..4b5ca6f07 100644 --- a/src/test/java/org/springframework/data/elasticsearch/NestedObjectTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/NestedObjectTests.java @@ -381,7 +381,7 @@ public void shouldIndexAndSearchMapAsNestedType() { assertThat(books.getSearchHit(0).getContent().getId()).isEqualTo(book2.getId()); } - @Document(indexName = "test-index-book-nested-objects", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-book-nested-objects") static class Book { @Nullable @Id private String id; @@ -438,7 +438,7 @@ public void setDescription(@Nullable String description) { } } - @Document(indexName = "test-index-person", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-person") static class Person { @Nullable @Id private String id; @Nullable private String name; @@ -505,7 +505,7 @@ public void setModel(String model) { } } - @Document(indexName = "test-index-person-multiple-level-nested", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-person-multiple-level-nested") static class PersonMultipleLevelNested { @Nullable @Id private String id; @Nullable private String name; diff --git a/src/test/java/org/springframework/data/elasticsearch/annotations/ComposableAnnotationsUnitTest.java b/src/test/java/org/springframework/data/elasticsearch/annotations/ComposableAnnotationsUnitTest.java index dc468eb90..7ce4e0f1c 100644 --- a/src/test/java/org/springframework/data/elasticsearch/annotations/ComposableAnnotationsUnitTest.java +++ b/src/test/java/org/springframework/data/elasticsearch/annotations/ComposableAnnotationsUnitTest.java @@ -26,6 +26,7 @@ import java.lang.annotation.Target; import java.time.LocalDate; +import org.elasticsearch.index.VersionType; import org.json.JSONException; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -57,7 +58,7 @@ void documentAnnotationShouldBeComposable() { assertThat(entity.getIndexCoordinates()).isEqualTo(IndexCoordinates.of("test-no-create")); assertThat(entity.isCreateIndexAndMapping()).isFalse(); - assertThat(entity.getShards()).isEqualTo((short) 42); + assertThat(entity.getVersionType()).isEqualTo(VersionType.INTERNAL); } @Test // DATAES-362 @@ -105,7 +106,7 @@ void shouldUseComposedFieldAnnotationsInMappingBuilder() throws JSONException { @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.TYPE }) - @Document(indexName = "", createIndex = false, shards = 42) + @Document(indexName = "", createIndex = false, versionType = VersionType.INTERNAL) public @interface DocumentNoCreate { @AliasFor(value = "indexName", annotation = Document.class) diff --git a/src/test/java/org/springframework/data/elasticsearch/config/nested/EnableNestedElasticsearchRepositoriesTests.java b/src/test/java/org/springframework/data/elasticsearch/config/nested/EnableNestedElasticsearchRepositoriesTests.java index 47a7d73a9..aee463e31 100644 --- a/src/test/java/org/springframework/data/elasticsearch/config/nested/EnableNestedElasticsearchRepositoriesTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/config/nested/EnableNestedElasticsearchRepositoriesTests.java @@ -73,7 +73,7 @@ public void hasNestedRepository() { assertThat(nestedRepository).isNotNull(); } - @Document(indexName = "test-index-sample-config-nested", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-sample-config-nested") static class SampleEntity { @Nullable @Id private String id; @Nullable @Field(type = Text, store = true, fielddata = true) private String type; diff --git a/src/test/java/org/springframework/data/elasticsearch/config/notnested/EnableElasticsearchRepositoriesTests.java b/src/test/java/org/springframework/data/elasticsearch/config/notnested/EnableElasticsearchRepositoriesTests.java index c089210c7..35b2c799f 100644 --- a/src/test/java/org/springframework/data/elasticsearch/config/notnested/EnableElasticsearchRepositoriesTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/config/notnested/EnableElasticsearchRepositoriesTests.java @@ -120,7 +120,7 @@ public void hasNotNestedRepository() { assertThat(nestedRepository).isNull(); } - @Document(indexName = "test-index-sample-config-not-nested", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-sample-config-not-nested") static class SampleEntity { @Nullable @Id private String id; @Nullable @Field(type = Text, store = true, fielddata = true) private String type; @@ -212,7 +212,7 @@ public void setVersion(@Nullable java.lang.Long version) { } } - @Document(indexName = "test-index-uuid-keyed-config-not-nested", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-uuid-keyed-config-not-nested") static class SampleEntityUUIDKeyed { @Nullable @Id private UUID id; @Nullable private String type; diff --git a/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchRestTemplateTests.java b/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchRestTemplateTests.java index 8e8ae9701..b767fc4b0 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchRestTemplateTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchRestTemplateTests.java @@ -79,7 +79,7 @@ public void shouldThrowExceptionIfDocumentDoesNotExistWhileDoingPartialUpdate() .isInstanceOf(UncategorizedElasticsearchException.class); } - @Document(indexName = "test-index-sample-core-rest-template", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-sample-core-rest-template") static class SampleEntity { @Nullable @Id private String id; @Nullable diff --git a/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java b/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java index b05df9b71..c8ec98352 100755 --- a/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java @@ -83,6 +83,7 @@ import org.springframework.data.elasticsearch.annotations.JoinTypeRelations; import org.springframework.data.elasticsearch.annotations.MultiField; import org.springframework.data.elasticsearch.annotations.ScriptedField; +import org.springframework.data.elasticsearch.annotations.Setting; import org.springframework.data.elasticsearch.core.document.Explanation; import org.springframework.data.elasticsearch.core.geo.GeoPoint; import org.springframework.data.elasticsearch.core.index.AliasAction; @@ -3006,7 +3007,7 @@ public void shouldRemoveAlias() { assertThat(aliases).isEmpty(); } - @Document(indexName = INDEX_2_NAME, replicas = 0) + @Document(indexName = INDEX_2_NAME) class ResultAggregator { private String id; @@ -3750,7 +3751,8 @@ void shouldReturnExplanationWhenRequested() { assertThat(explanation).isNotNull(); } - @Document(indexName = INDEX_NAME_SAMPLE_ENTITY, replicas = 0, refreshInterval = "-1") + @Document(indexName = INDEX_NAME_SAMPLE_ENTITY) + @Setting(shards = 1, replicas = 0, refreshInterval = "-1") static class SampleEntity { @Nullable @Id private String id; @Nullable @Field(type = Text, store = true, fielddata = true) private String type; @@ -3928,7 +3930,7 @@ public int hashCode() { } } - @Document(indexName = "test-index-uuid-keyed-core-template", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-uuid-keyed-core-template") private static class SampleEntityUUIDKeyed { @Nullable @Id private UUID id; @Nullable private String type; @@ -4010,7 +4012,7 @@ public void setVersion(@Nullable java.lang.Long version) { } } - @Document(indexName = "test-index-book-core-template", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-book-core-template") static class Book { @Nullable @Id private String id; @Nullable private String name; @@ -4139,8 +4141,7 @@ public void setName(@Nullable String name) { } } - @Document(indexName = "test-index-version-core-template", replicas = 0, refreshInterval = "-1", - versionType = VersionType.EXTERNAL_GTE) + @Document(indexName = "test-index-version-core-template", versionType = VersionType.EXTERNAL_GTE) private static class GTEVersionEntity { @Nullable @Version private Long version; @Nullable @Id private String id; @@ -4174,7 +4175,7 @@ public void setName(@Nullable String name) { } } - @Document(indexName = "test-index-hetro1-core-template", replicas = 0) + @Document(indexName = "test-index-hetro1-core-template") static class HetroEntity1 { @Nullable @Id private String id; @Nullable private String firstName; @@ -4214,7 +4215,7 @@ public void setVersion(@Nullable java.lang.Long version) { } } - @Document(indexName = "test-index-hetro2-core-template", replicas = 0) + @Document(indexName = "test-index-hetro2-core-template") static class HetroEntity2 { @Nullable @Id private String id; @@ -4255,8 +4256,8 @@ public void setVersion(@Nullable java.lang.Long version) { } } - @Document(indexName = "test-index-server-configuration", useServerConfiguration = true, shards = 10, replicas = 10, - refreshInterval = "-1") + @Document(indexName = "test-index-server-configuration") + @Setting(useServerConfiguration = true, shards = 10, replicas = 10, refreshInterval = "-1") private static class UseServerConfigurationEntity { @Nullable @Id private String id; @@ -4281,7 +4282,7 @@ public void setVal(@Nullable String val) { } } - @Document(indexName = "test-index-sample-mapping", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-sample-mapping") static class SampleMappingEntity { @Nullable @Id private String id; diff --git a/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTransportTemplateTests.java b/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTransportTemplateTests.java index 485e00575..d95faed41 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTransportTemplateTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTransportTemplateTests.java @@ -195,7 +195,7 @@ void shouldUseAllOptionsFromUpdateByQuery() throws JSONException { assertThat(request.request().getScript().getType()).isEqualTo(org.elasticsearch.script.ScriptType.STORED); } - @Document(indexName = "test-index-sample-core-transport-template", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-sample-core-transport-template") static class SampleEntity { @Nullable @Id private String id; @Nullable @Field(type = Text, store = true, fielddata = true) private String type; diff --git a/src/test/java/org/springframework/data/elasticsearch/core/LogEntityTests.java b/src/test/java/org/springframework/data/elasticsearch/core/LogEntityTests.java index a54ca91ea..745db975f 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/LogEntityTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/LogEntityTests.java @@ -132,7 +132,7 @@ public void shouldReturnLogsForGivenIPRanges() { /** * Simple type to test facets */ - @Document(indexName = "test-index-log-core", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-log-core") static class LogEntity { private static final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); diff --git a/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplateIntegrationTests.java b/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplateIntegrationTests.java index 45e580f46..90755add8 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplateIntegrationTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplateIntegrationTests.java @@ -1257,7 +1257,7 @@ public int hashCode() { } } - @Document(indexName = DEFAULT_INDEX, replicas = 0, refreshInterval = "-1") + @Document(indexName = DEFAULT_INDEX) static class SampleEntity { @Nullable @Id private String id; @Nullable @Field(type = Text, store = true, fielddata = true) private String message; diff --git a/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplateUnitTests.java b/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplateUnitTests.java index 98eb8dc65..ddf2c984a 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplateUnitTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplateUnitTests.java @@ -250,7 +250,7 @@ public void deleteByShouldApplyIndicesOptionsIfSet() { assertThat(captor.getValue().indicesOptions()).isEqualTo(IndicesOptions.LENIENT_EXPAND_OPEN); } - @Document(indexName = "test-index-sample-core-reactive-template-Unit", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-sample-core-reactive-template-Unit") static class SampleEntity { @Nullable @Id private String id; diff --git a/src/test/java/org/springframework/data/elasticsearch/core/ReactiveIndexOperationsTest.java b/src/test/java/org/springframework/data/elasticsearch/core/ReactiveIndexOperationsTest.java index 8348b98ef..87923872a 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/ReactiveIndexOperationsTest.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/ReactiveIndexOperationsTest.java @@ -18,6 +18,7 @@ import static org.assertj.core.api.Assertions.*; import static org.skyscreamer.jsonassert.JSONAssert.*; +import org.springframework.data.elasticsearch.core.index.Settings; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; @@ -390,8 +391,7 @@ void shouldPutTemplate() { org.springframework.data.elasticsearch.core.document.Document mapping = indexOps.createMapping(TemplateClass.class) .block(); - org.springframework.data.elasticsearch.core.document.Document settings = indexOps - .createSettings(TemplateClass.class).block(); + Settings settings = indexOps .createSettings(TemplateClass.class).block(); AliasActions aliasActions = new AliasActions( new AliasAction.Add(AliasActionParameters.builderForTemplate().withAliases("alias1", "alias2").build())); @@ -423,8 +423,7 @@ void shouldGetTemplate() throws JSONException { org.springframework.data.elasticsearch.core.document.Document mapping = indexOps.createMapping(TemplateClass.class) .block(); - org.springframework.data.elasticsearch.core.document.Document settings = indexOps - .createSettings(TemplateClass.class).block(); + Settings settings = indexOps .createSettings(TemplateClass.class).block(); AliasActions aliasActions = new AliasActions( new AliasAction.Add(AliasActionParameters.builderForTemplate().withAliases("alias1", "alias2").build())); @@ -505,7 +504,8 @@ void shouldDeleteTemplate() { assertThat(exists).isFalse(); } - @Document(indexName = TESTINDEX, shards = 3, replicas = 2, refreshInterval = "4s") + @Document(indexName = TESTINDEX) + @Setting(shards = 3, replicas = 2, refreshInterval = "4s") static class Entity { @Nullable @Id private String id; @Nullable @Field(type = FieldType.Text) private String text; @@ -540,7 +540,8 @@ public void setPublicationDate(@Nullable LocalDate publicationDate) { } } - @Document(indexName = TESTINDEX, useServerConfiguration = true) + @Document(indexName = TESTINDEX) + @Setting(useServerConfiguration = true) static class EntityUseServerConfig { @Nullable @Id private String id; @@ -570,7 +571,8 @@ public void setId(@Nullable String id) { } } - @Document(indexName = "test-template", shards = 3, replicas = 2, refreshInterval = "5s") + @Document(indexName = "test-template") + @Setting(refreshInterval = "5s") static class TemplateClass { @Id @Nullable private String id; @Field(type = FieldType.Text) @Nullable private String message; diff --git a/src/test/java/org/springframework/data/elasticsearch/core/ReactiveResourceUtilTest.java b/src/test/java/org/springframework/data/elasticsearch/core/ReactiveResourceUtilTest.java index d82e3dce9..39f62e32f 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/ReactiveResourceUtilTest.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/ReactiveResourceUtilTest.java @@ -60,9 +60,9 @@ void shouldReadFromClasspath() { } @Test - void shouldReturnEmptyMonoOnNonExistingResource() { + void shouldErrorOnNonExistingResource() { ReactiveResourceUtil.readFileFromClasspath("/this/should/really/not/exist") // .as(StepVerifier::create) // - .verifyComplete(); + .verifyError(); } } diff --git a/src/test/java/org/springframework/data/elasticsearch/core/SearchAsYouTypeTests.java b/src/test/java/org/springframework/data/elasticsearch/core/SearchAsYouTypeTests.java index c04c30879..2c67efa6e 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/SearchAsYouTypeTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/SearchAsYouTypeTests.java @@ -151,7 +151,7 @@ void shouldReturnCorrectResultsForNotMatchQuery() { /** * @author Aleksei Arsenev */ - @Document(indexName = "test-index-core-search-as-you-type", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-core-search-as-you-type") static class SearchAsYouTypeEntity { public SearchAsYouTypeEntity(@Nonnull String id) { diff --git a/src/test/java/org/springframework/data/elasticsearch/core/aggregation/ElasticsearchTemplateAggregationTests.java b/src/test/java/org/springframework/data/elasticsearch/core/aggregation/ElasticsearchTemplateAggregationTests.java index c60c23bf9..86bef45bc 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/aggregation/ElasticsearchTemplateAggregationTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/aggregation/ElasticsearchTemplateAggregationTests.java @@ -130,7 +130,7 @@ public void shouldReturnAggregatedResponseForGivenSearchQuery() { assertThat(searchHits.hasSearchHits()).isFalse(); } - @Document(indexName = "test-index-articles-core-aggregation", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-articles-core-aggregation") static class ArticleEntity { @Nullable @Id private String id; diff --git a/src/test/java/org/springframework/data/elasticsearch/core/completion/ElasticsearchTemplateCompletionTests.java b/src/test/java/org/springframework/data/elasticsearch/core/completion/ElasticsearchTemplateCompletionTests.java index d683c2ddf..24275198e 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/completion/ElasticsearchTemplateCompletionTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/completion/ElasticsearchTemplateCompletionTests.java @@ -248,7 +248,7 @@ public void setSomeField2(String someField2) { /** * @author Mewes Kochheim */ - @Document(indexName = "test-index-core-completion", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-core-completion") static class CompletionEntity { @Nullable @Id private String id; @@ -334,7 +334,7 @@ public IndexQuery buildIndex() { /** * @author Mewes Kochheim */ - @Document(indexName = "test-index-annotated-completion", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-annotated-completion") static class AnnotatedCompletionEntity { @Nullable @Id private String id; diff --git a/src/test/java/org/springframework/data/elasticsearch/core/completion/ElasticsearchTemplateCompletionWithContextsTests.java b/src/test/java/org/springframework/data/elasticsearch/core/completion/ElasticsearchTemplateCompletionWithContextsTests.java index 5626661a2..d25db21e5 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/completion/ElasticsearchTemplateCompletionWithContextsTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/completion/ElasticsearchTemplateCompletionWithContextsTests.java @@ -244,7 +244,7 @@ public void setSomeField2(String someField2) { * @author Mewes Kochheim * @author Robert Gruendler */ - @Document(indexName = "test-index-context-completion", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-context-completion") static class ContextCompletionEntity { public static final String LANGUAGE_CATEGORY = "language"; diff --git a/src/test/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverterUnitTests.java b/src/test/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverterUnitTests.java index 225102876..413ade735 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverterUnitTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverterUnitTests.java @@ -1792,8 +1792,7 @@ public void setModel(@Nullable String model) { } } - @org.springframework.data.elasticsearch.annotations.Document(indexName = "test-index-geo-core-entity-mapper", - replicas = 0, refreshInterval = "-1") + @org.springframework.data.elasticsearch.annotations.Document(indexName = "test-index-geo-core-entity-mapper") static class GeoEntity { @Nullable @Id private String id; // geo shape - Spring Data diff --git a/src/test/java/org/springframework/data/elasticsearch/core/geo/ElasticsearchTemplateGeoTests.java b/src/test/java/org/springframework/data/elasticsearch/core/geo/ElasticsearchTemplateGeoTests.java index 548bc6847..d8ee328fd 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/geo/ElasticsearchTemplateGeoTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/geo/ElasticsearchTemplateGeoTests.java @@ -361,7 +361,7 @@ private IndexQuery buildIndex(LocationMarkerEntity result) { * @author Franck Marchand * @author Mohsin Husen */ - @Document(indexName = "test-index-author-marker-core-geo", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-author-marker-core-geo") static class AuthorMarkerEntity { @Nullable @Id private String id; @Nullable private String name; @@ -436,7 +436,7 @@ public IndexQuery buildIndex() { } } - @Document(indexName = "test-index-location-marker-core-geo", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-location-marker-core-geo") static class LocationMarkerEntity { @Nullable @Id private String id; @Nullable private String name; diff --git a/src/test/java/org/springframework/data/elasticsearch/core/index/MappingBuilderIntegrationTests.java b/src/test/java/org/springframework/data/elasticsearch/core/index/MappingBuilderIntegrationTests.java index 9223499ad..31b8727df 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/index/MappingBuilderIntegrationTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/index/MappingBuilderIntegrationTests.java @@ -122,9 +122,9 @@ public void shouldAddStockPriceDocumentToIndex() { IndexCoordinates index = IndexCoordinates.of("test-index-stock-mapping-builder"); StockPrice stockPrice = new StockPrice(); // - stockPrice.setId(id); - stockPrice.setSymbol(symbol); - stockPrice.setPrice(BigDecimal.valueOf(price)); + stockPrice.setId(id); + stockPrice.setSymbol(symbol); + stockPrice.setPrice(BigDecimal.valueOf(price)); operations.index(buildIndex(stockPrice), index); operations.indexOps(StockPrice.class).refresh(); @@ -384,7 +384,7 @@ static class MultiFieldEntity { } } - @Document(indexName = "test-index-book-mapping-builder", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-book-mapping-builder") static class Book { @Nullable @Id private String id; @Nullable private String name; @@ -440,7 +440,7 @@ public void setDescription(@Nullable String description) { } } - @Document(indexName = "test-index-simple-recursive-mapping-builder", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-simple-recursive-mapping-builder") static class SimpleRecursiveEntity { @Nullable @Id private String id; @Nullable @Field(type = FieldType.Object, @@ -465,7 +465,7 @@ public void setCircularObject(@Nullable SimpleRecursiveEntity circularObject) { } } - @Document(indexName = "test-copy-to-mapping-builder", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-copy-to-mapping-builder") static class CopyToEntity { @Nullable @Id private String id; @Nullable @Field(type = FieldType.Keyword, copyTo = "name") private String firstName; @@ -509,7 +509,7 @@ public void setName(@Nullable String name) { } } - @Document(indexName = "test-index-normalizer-mapping-builder", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-normalizer-mapping-builder") @Setting(settingPath = "/settings/test-normalizer.json") static class NormalizerEntity { @Nullable @Id private String id; @@ -569,7 +569,7 @@ public void setName(String name) { } } - @Document(indexName = "test-index-sample-inherited-mapping-builder", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-sample-inherited-mapping-builder") static class SampleInheritedEntity extends AbstractInheritedEntity { @Nullable @Field(type = Text, index = false, store = true, analyzer = "standard") private String message; @@ -615,7 +615,7 @@ public IndexQuery buildIndex() { } } - @Document(indexName = "test-index-stock-mapping-builder", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-stock-mapping-builder") static class StockPrice { @Nullable @Id private String id; @Nullable private String symbol; @@ -652,35 +652,41 @@ public void setPrice(@Nullable BigDecimal price) { static class AbstractInheritedEntity { @Nullable @Id private String id; @Nullable @Field(type = FieldType.Date, format = DateFormat.date_time, index = false) private Date createdDate; - @Nullable public String getId() { + + @Nullable + public String getId() { return id; } + public void setId(String id) { this.id = id; } - @Nullable public Date getCreatedDate() { + + @Nullable + public Date getCreatedDate() { return createdDate; } + public void setCreatedDate(Date createdDate) { this.createdDate = createdDate; } } - @Document(indexName = "test-index-geo-mapping-builder", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-geo-mapping-builder") static class GeoEntity { -@Nullable @Id private String id; -// geo shape - Spring Data -@Nullable private Box box; -@Nullable private Circle circle; -@Nullable private Polygon polygon; -// geo point - Custom implementation + Spring Data -@Nullable @GeoPointField private Point pointA; -@Nullable private GeoPoint pointB; -@Nullable @GeoPointField private String pointC; -@Nullable @GeoPointField private double[] pointD; - // geo shape, until e have the classes for this, us a strng -@Nullable @GeoShapeField private String shape1; -@Nullable @GeoShapeField(coerce = true, ignoreMalformed = true, ignoreZValue = false, + @Nullable @Id private String id; + // geo shape - Spring Data + @Nullable private Box box; + @Nullable private Circle circle; + @Nullable private Polygon polygon; + // geo point - Custom implementation + Spring Data + @Nullable @GeoPointField private Point pointA; + @Nullable private GeoPoint pointB; + @Nullable @GeoPointField private String pointC; + @Nullable @GeoPointField private double[] pointD; + // geo shape, until e have the classes for this, us a strng + @Nullable @GeoShapeField private String shape1; + @Nullable @GeoShapeField(coerce = true, ignoreMalformed = true, ignoreZValue = false, orientation = GeoShapeField.Orientation.clockwise) private String shape2; @Nullable @@ -890,7 +896,8 @@ static class TermVectorFieldEntity { @Nullable @Field(type = FieldType.Text, termVector = TermVector.yes) private String yes; @Nullable @Field(type = FieldType.Text, termVector = TermVector.with_positions) private String with_positions; @Nullable @Field(type = FieldType.Text, termVector = TermVector.with_offsets) private String with_offsets; - @Nullable @Field(type = FieldType.Text, termVector = TermVector.with_positions_offsets) private String with_positions_offsets; + @Nullable @Field(type = FieldType.Text, + termVector = TermVector.with_positions_offsets) private String with_positions_offsets; @Nullable @Field(type = FieldType.Text, termVector = TermVector.with_positions_payloads) private String with_positions_payloads; @Nullable @Field(type = FieldType.Text, diff --git a/src/test/java/org/springframework/data/elasticsearch/core/index/MappingBuilderUnitTests.java b/src/test/java/org/springframework/data/elasticsearch/core/index/MappingBuilderUnitTests.java index 66c1d57a0..29a58e7c9 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/index/MappingBuilderUnitTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/index/MappingBuilderUnitTests.java @@ -731,7 +731,7 @@ static class MultiFieldEntity { } } - @Document(indexName = "test-index-book-mapping-builder", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-book-mapping-builder") static class Book { @Nullable @Id private String id; @Nullable private String name; @@ -787,7 +787,7 @@ public void setDescription(@Nullable String description) { } } - @Document(indexName = "test-index-simple-recursive-mapping-builder", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-simple-recursive-mapping-builder") static class SimpleRecursiveEntity { @Nullable @Id private String id; @Nullable @Field(type = FieldType.Object, @@ -812,7 +812,7 @@ public void setCircularObject(@Nullable SimpleRecursiveEntity circularObject) { } } - @Document(indexName = "test-copy-to-mapping-builder", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-copy-to-mapping-builder") static class CopyToEntity { @Nullable @Id private String id; @Nullable @Field(type = FieldType.Keyword, copyTo = "name") private String firstName; @@ -856,7 +856,7 @@ public void setName(@Nullable String name) { } } - @Document(indexName = "test-index-normalizer-mapping-builder", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-normalizer-mapping-builder") @Setting(settingPath = "/settings/test-normalizer.json") static class NormalizerEntity { @Nullable @Id private String id; @@ -915,7 +915,7 @@ public void setName(String name) { } } - @Document(indexName = "test-index-sample-inherited-mapping-builder", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-sample-inherited-mapping-builder") static class SampleInheritedEntity extends AbstractInheritedEntity { @Nullable @Field(type = Text, index = false, store = true, analyzer = "standard") private String message; @@ -930,7 +930,7 @@ public void setMessage(String message) { } } - @Document(indexName = "test-index-stock-mapping-builder", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-stock-mapping-builder") static class StockPrice { @Nullable @Id private String id; @Nullable private String symbol; @@ -989,7 +989,7 @@ public void setCreatedDate(Date createdDate) { } } - @Document(indexName = "test-index-recursive-mapping-mapping-builder", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-recursive-mapping-mapping-builder") static class SampleTransientEntity { @Nullable @Id private String id; @@ -1040,7 +1040,7 @@ public void setSomething(Boolean something) { } } - @Document(indexName = "test-index-geo-mapping-builder", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-geo-mapping-builder") static class GeoEntity { @Nullable @Id private String id; // geo shape - Spring Data diff --git a/src/test/java/org/springframework/data/elasticsearch/core/index/SimpleDynamicTemplatesMappingTests.java b/src/test/java/org/springframework/data/elasticsearch/core/index/SimpleDynamicTemplatesMappingTests.java index d4a134ea9..c959dc7d1 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/index/SimpleDynamicTemplatesMappingTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/index/SimpleDynamicTemplatesMappingTests.java @@ -27,6 +27,7 @@ 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.annotations.Setting; import org.springframework.data.elasticsearch.core.MappingContextBaseTests; import org.springframework.lang.Nullable; @@ -66,7 +67,8 @@ public void testCorrectDynamicTemplatesMappingsTwo() throws JSONException { /** * @author Petr Kukral */ - @Document(indexName = "test-dynamictemplates", indexStoreType = "memory", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-dynamictemplates") + @Setting(indexStoreType = "memory") @DynamicTemplates(mappingPath = "/mappings/test-dynamic_templates_mappings.json") static class SampleDynamicTemplatesEntity { @@ -78,7 +80,8 @@ static class SampleDynamicTemplatesEntity { /** * @author Petr Kukral */ - @Document(indexName = "test-dynamictemplates", indexStoreType = "memory", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-dynamictemplates") + @Setting(indexStoreType = "memory") @DynamicTemplates(mappingPath = "/mappings/test-dynamic_templates_mappings_two.json") static class SampleDynamicTemplatesEntityTwo { diff --git a/src/test/java/org/springframework/data/elasticsearch/core/index/SimpleElasticsearchDateMappingTests.java b/src/test/java/org/springframework/data/elasticsearch/core/index/SimpleElasticsearchDateMappingTests.java index e974e76bd..470dfa0a4 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/index/SimpleElasticsearchDateMappingTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/index/SimpleElasticsearchDateMappingTests.java @@ -51,7 +51,7 @@ public void testCorrectDateMappings() throws JSONException { assertEquals(EXPECTED_MAPPING, mapping, false); } - @Document(indexName = "test-index-date-mapping-core", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-date-mapping-core") static class SampleDateMappingEntity { @Nullable @Id private String id; @Nullable @Field(type = Text, index = false, store = true, analyzer = "standard") private String message; diff --git a/src/test/java/org/springframework/data/elasticsearch/core/index/TemplateTests.java b/src/test/java/org/springframework/data/elasticsearch/core/index/TemplateTests.java index bb89b05a6..1cec28730 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/index/TemplateTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/index/TemplateTests.java @@ -28,6 +28,7 @@ import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.annotations.Field; import org.springframework.data.elasticsearch.annotations.FieldType; +import org.springframework.data.elasticsearch.annotations.Setting; import org.springframework.data.elasticsearch.core.ElasticsearchOperations; import org.springframework.data.elasticsearch.core.IndexOperations; import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; @@ -51,8 +52,7 @@ void shouldCreateTemplate() { IndexOperations indexOps = operations.indexOps(IndexCoordinates.of("dont-care")); org.springframework.data.elasticsearch.core.document.Document mapping = indexOps.createMapping(TemplateClass.class); - org.springframework.data.elasticsearch.core.document.Document settings = indexOps - .createSettings(TemplateClass.class); + Settings settings = indexOps.createSettings(TemplateClass.class); AliasActions aliasActions = new AliasActions( new AliasAction.Add(AliasActionParameters.builderForTemplate().withAliases("alias1", "alias2").build())); @@ -84,8 +84,7 @@ void shouldGetTemplate() throws JSONException { IndexOperations indexOps = operations.indexOps(IndexCoordinates.of("dont-care")); org.springframework.data.elasticsearch.core.document.Document mapping = indexOps.createMapping(TemplateClass.class); - org.springframework.data.elasticsearch.core.document.Document settings = indexOps - .createSettings(TemplateClass.class); + Settings settings = indexOps.createSettings(TemplateClass.class); AliasActions aliasActions = new AliasActions( new AliasAction.Add(AliasActionParameters.builderForTemplate().withAliases("alias1", "alias2").build())); @@ -166,7 +165,8 @@ void shouldDeleteTemplate() { } - @Document(indexName = "test-template", shards = 3, replicas = 2, refreshInterval = "5s") + @Document(indexName = "test-template") + @Setting(shards = 3) static class TemplateClass { @Id @Nullable private String id; @Field(type = FieldType.Text) @Nullable private String message; diff --git a/src/test/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentEntityTests.java b/src/test/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentEntityTests.java index a5d920c43..bae5f44cc 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentEntityTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentEntityTests.java @@ -16,14 +16,18 @@ package org.springframework.data.elasticsearch.core.mapping; import static org.assertj.core.api.Assertions.*; +import static org.skyscreamer.jsonassert.JSONAssert.*; +import org.json.JSONException; import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.data.annotation.Id; import org.springframework.data.annotation.Version; import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.annotations.Field; import org.springframework.data.elasticsearch.annotations.FieldType; +import org.springframework.data.elasticsearch.annotations.Setting; import org.springframework.data.elasticsearch.core.MappingContextBaseTests; import org.springframework.data.elasticsearch.core.query.SeqNoPrimaryTerm; import org.springframework.data.mapping.MappingException; @@ -44,116 +48,162 @@ */ public class SimpleElasticsearchPersistentEntityTests extends MappingContextBaseTests { - @Test - public void shouldThrowExceptionGivenVersionPropertyIsNotLong() { - // given - TypeInformation typeInformation = ClassTypeInformation.from(EntityWithWrongVersionType.class); - SimpleElasticsearchPersistentEntity entity = new SimpleElasticsearchPersistentEntity<>( - typeInformation); - // when - assertThatThrownBy(() -> { - SimpleElasticsearchPersistentProperty persistentProperty = createProperty(entity, "version"); - }).isInstanceOf(MappingException.class); - } + @Nested + @DisplayName("properties setup") + class PropertiesTests { - @Test - public void shouldThrowExceptionGivenMultipleVersionPropertiesArePresent() { - // given - TypeInformation typeInformation = ClassTypeInformation.from(EntityWithMultipleVersionField.class); - SimpleElasticsearchPersistentEntity entity = new SimpleElasticsearchPersistentEntity<>( - typeInformation); + @Test + public void shouldThrowExceptionGivenVersionPropertyIsNotLong() { - SimpleElasticsearchPersistentProperty persistentProperty1 = createProperty(entity, "version1"); + TypeInformation typeInformation = ClassTypeInformation + .from(EntityWithWrongVersionType.class); + SimpleElasticsearchPersistentEntity entity = new SimpleElasticsearchPersistentEntity<>( + typeInformation); - SimpleElasticsearchPersistentProperty persistentProperty2 = createProperty(entity, "version2"); + assertThatThrownBy(() -> createProperty(entity, "version")).isInstanceOf(MappingException.class); + } - entity.addPersistentProperty(persistentProperty1); - // when - assertThatThrownBy(() -> { - entity.addPersistentProperty(persistentProperty2); - }).isInstanceOf(MappingException.class); - } + @Test + public void shouldThrowExceptionGivenMultipleVersionPropertiesArePresent() { - @Test - void shouldFindPropertiesByMappedName() { + TypeInformation typeInformation = ClassTypeInformation + .from(EntityWithMultipleVersionField.class); + SimpleElasticsearchPersistentEntity entity = new SimpleElasticsearchPersistentEntity<>( + typeInformation); + SimpleElasticsearchPersistentProperty persistentProperty1 = createProperty(entity, "version1"); + SimpleElasticsearchPersistentProperty persistentProperty2 = createProperty(entity, "version2"); + entity.addPersistentProperty(persistentProperty1); - SimpleElasticsearchMappingContext context = new SimpleElasticsearchMappingContext(); - SimpleElasticsearchPersistentEntity persistentEntity = context - .getRequiredPersistentEntity(FieldNameEntity.class); + assertThatThrownBy(() -> entity.addPersistentProperty(persistentProperty2)).isInstanceOf(MappingException.class); + } - ElasticsearchPersistentProperty persistentProperty = persistentEntity - .getPersistentPropertyWithFieldName("renamed-field"); + @Test + void shouldFindPropertiesByMappedName() { - assertThat(persistentProperty).isNotNull(); - assertThat(persistentProperty.getName()).isEqualTo("renamedField"); - assertThat(persistentProperty.getFieldName()).isEqualTo("renamed-field"); - } + SimpleElasticsearchMappingContext context = new SimpleElasticsearchMappingContext(); + SimpleElasticsearchPersistentEntity persistentEntity = context + .getRequiredPersistentEntity(FieldNameEntity.class); - @Test // DATAES-799 - void shouldReportThatThereIsNoSeqNoPrimaryTermPropertyWhenThereIsNoSuchProperty() { - TypeInformation typeInformation = ClassTypeInformation - .from(EntityWithoutSeqNoPrimaryTerm.class); - SimpleElasticsearchPersistentEntity entity = new SimpleElasticsearchPersistentEntity<>( - typeInformation); + ElasticsearchPersistentProperty persistentProperty = persistentEntity + .getPersistentPropertyWithFieldName("renamed-field"); - assertThat(entity.hasSeqNoPrimaryTermProperty()).isFalse(); - } + assertThat(persistentProperty).isNotNull(); + assertThat(persistentProperty.getName()).isEqualTo("renamedField"); + assertThat(persistentProperty.getFieldName()).isEqualTo("renamed-field"); + } - @Test // DATAES-799 - void shouldReportThatThereIsSeqNoPrimaryTermPropertyWhenThereIsSuchProperty() { - TypeInformation typeInformation = ClassTypeInformation - .from(EntityWithSeqNoPrimaryTerm.class); - SimpleElasticsearchPersistentEntity entity = new SimpleElasticsearchPersistentEntity<>( - typeInformation); + @Test + // DATAES-799 + void shouldReportThatThereIsNoSeqNoPrimaryTermPropertyWhenThereIsNoSuchProperty() { + TypeInformation typeInformation = ClassTypeInformation + .from(EntityWithoutSeqNoPrimaryTerm.class); + SimpleElasticsearchPersistentEntity entity = new SimpleElasticsearchPersistentEntity<>( + typeInformation); - entity.addPersistentProperty(createProperty(entity, "seqNoPrimaryTerm")); + assertThat(entity.hasSeqNoPrimaryTermProperty()).isFalse(); + } - assertThat(entity.hasSeqNoPrimaryTermProperty()).isTrue(); - } + @Test + // DATAES-799 + void shouldReportThatThereIsSeqNoPrimaryTermPropertyWhenThereIsSuchProperty() { + TypeInformation typeInformation = ClassTypeInformation + .from(EntityWithSeqNoPrimaryTerm.class); + SimpleElasticsearchPersistentEntity entity = new SimpleElasticsearchPersistentEntity<>( + typeInformation); - @Test // DATAES-799 - void shouldReturnSeqNoPrimaryTermPropertyWhenThereIsSuchProperty() { - TypeInformation typeInformation = ClassTypeInformation - .from(EntityWithSeqNoPrimaryTerm.class); - SimpleElasticsearchPersistentEntity entity = new SimpleElasticsearchPersistentEntity<>( - typeInformation); - entity.addPersistentProperty(createProperty(entity, "seqNoPrimaryTerm")); - EntityWithSeqNoPrimaryTerm instance = new EntityWithSeqNoPrimaryTerm(); - SeqNoPrimaryTerm seqNoPrimaryTerm = new SeqNoPrimaryTerm(1, 2); + entity.addPersistentProperty(createProperty(entity, "seqNoPrimaryTerm")); - ElasticsearchPersistentProperty property = entity.getSeqNoPrimaryTermProperty(); - entity.getPropertyAccessor(instance).setProperty(property, seqNoPrimaryTerm); + assertThat(entity.hasSeqNoPrimaryTermProperty()).isTrue(); + } - assertThat(instance.seqNoPrimaryTerm).isSameAs(seqNoPrimaryTerm); - } + @Test + // DATAES-799 + void shouldReturnSeqNoPrimaryTermPropertyWhenThereIsSuchProperty() { + + TypeInformation typeInformation = ClassTypeInformation + .from(EntityWithSeqNoPrimaryTerm.class); + SimpleElasticsearchPersistentEntity entity = new SimpleElasticsearchPersistentEntity<>( + typeInformation); + entity.addPersistentProperty(createProperty(entity, "seqNoPrimaryTerm")); + EntityWithSeqNoPrimaryTerm instance = new EntityWithSeqNoPrimaryTerm(); + SeqNoPrimaryTerm seqNoPrimaryTerm = new SeqNoPrimaryTerm(1, 2); + + ElasticsearchPersistentProperty property = entity.getSeqNoPrimaryTermProperty(); + assertThat(property).isNotNull(); - @Test // DATAES-799 - void shouldNotAllowMoreThanOneSeqNoPrimaryTermProperties() { - TypeInformation typeInformation = ClassTypeInformation - .from(EntityWithSeqNoPrimaryTerm.class); - SimpleElasticsearchPersistentEntity entity = new SimpleElasticsearchPersistentEntity<>( - typeInformation); - entity.addPersistentProperty(createProperty(entity, "seqNoPrimaryTerm")); + entity.getPropertyAccessor(instance).setProperty(property, seqNoPrimaryTerm); + + assertThat(instance.seqNoPrimaryTerm).isSameAs(seqNoPrimaryTerm); + } + + @Test + // DATAES-799 + void shouldNotAllowMoreThanOneSeqNoPrimaryTermProperties() { + TypeInformation typeInformation = ClassTypeInformation + .from(EntityWithSeqNoPrimaryTerm.class); + SimpleElasticsearchPersistentEntity entity = new SimpleElasticsearchPersistentEntity<>( + typeInformation); + entity.addPersistentProperty(createProperty(entity, "seqNoPrimaryTerm")); + + assertThatThrownBy(() -> entity.addPersistentProperty(createProperty(entity, "seqNoPrimaryTerm2"))) + .isInstanceOf(MappingException.class); + } + + @Test // #1680 + @DisplayName("should allow fields with id property names") + void shouldAllowFieldsWithIdPropertyNames() { + elasticsearchConverter.get().getMappingContext().getRequiredPersistentEntity(EntityWithIdNameFields.class); + } - assertThatThrownBy(() -> entity.addPersistentProperty(createProperty(entity, "seqNoPrimaryTerm2"))) - .isInstanceOf(MappingException.class); } - @Test // #1680 - @DisplayName("should allow fields with id property names") - void shouldAllowFieldsWithIdPropertyNames() { - elasticsearchConverter.get().getMappingContext().getRequiredPersistentEntity(EntityWithIdNameFields.class); + @Nested + @DisplayName("index settings") + class SettingsTests { + + @Test // #1719 + @DisplayName("should error if index sorting parameters do not have the same number of arguments") + void shouldErrorIfIndexSortingParametersDoNotHaveTheSameNumberOfArguments() { + + assertThatThrownBy(() -> { + elasticsearchConverter.get().getMappingContext() + .getRequiredPersistentEntity(SettingsInvalidSortParameterSizes.class).getDefaultSettings(); + }).isInstanceOf(IllegalArgumentException.class); + } + + @Test // #1719 + @DisplayName("should write sort parameters to Settings object") + void shouldWriteSortParametersToSettingsObject() throws JSONException { + + String expected = "{\n" + // + " \"index.sort.field\": [\"second_field\", \"first_field\"],\n" + // + " \"index.sort.mode\": [\"max\", \"min\"],\n" + // + " \"index.sort.order\": [\"desc\",\"asc\"],\n" + // + " \"index.sort.missing\": [\"_last\",\"_first\"]\n" + // + "}\n"; // + + ElasticsearchPersistentEntity entity = elasticsearchConverter.get().getMappingContext() + .getRequiredPersistentEntity(SettingsValidSortParameterSizes.class); + + String json = entity.getDefaultSettings().toJson(); + assertEquals(expected, json, false); + } } + // region helper functions private static SimpleElasticsearchPersistentProperty createProperty(SimpleElasticsearchPersistentEntity entity, - String field) { + String fieldName) { TypeInformation type = entity.getTypeInformation(); - Property property = Property.of(type, ReflectionUtils.findField(entity.getType(), field)); + java.lang.reflect.Field field = ReflectionUtils.findField(entity.getType(), fieldName); + assertThat(field).isNotNull(); + Property property = Property.of(type, field); return new SimpleElasticsearchPersistentProperty(property, entity, SimpleTypeHolder.DEFAULT, null); } + // endregion + // region entities private static class EntityWithWrongVersionType { @Nullable @Version private String version; @@ -168,6 +218,7 @@ public void setVersion(String version) { } } + @SuppressWarnings("unused") private static class EntityWithMultipleVersionField { @Nullable @Version private Long version1; @@ -192,6 +243,7 @@ public void setVersion2(Long version2) { } } + @SuppressWarnings("unused") private static class FieldNameEntity { @Nullable @Id private String id; @Nullable @Field(name = "renamed-field") private String renamedField; @@ -199,15 +251,40 @@ private static class FieldNameEntity { private static class EntityWithoutSeqNoPrimaryTerm {} + @SuppressWarnings("unused") private static class EntityWithSeqNoPrimaryTerm { - private SeqNoPrimaryTerm seqNoPrimaryTerm; - private SeqNoPrimaryTerm seqNoPrimaryTerm2; + @Nullable private SeqNoPrimaryTerm seqNoPrimaryTerm; + @Nullable private SeqNoPrimaryTerm seqNoPrimaryTerm2; } + @SuppressWarnings("unused") @Document(indexName = "fieldnames") private static class EntityWithIdNameFields { - @Id private String theRealId; - @Field(type = FieldType.Text, name = "document") private String document; - @Field(name = "id") private String renamedId; + @Nullable @Id private String theRealId; + @Nullable @Field(type = FieldType.Text, name = "document") private String document; + @Nullable @Field(name = "id") private String renamedId; + } + + @Document(indexName = "dontcare") + @Setting(sortFields = { "first-field", "second-field" }, sortModes = { Setting.SortMode.max }, + sortOrders = { Setting.SortOrder.asc }, + sortMissingValues = { Setting.SortMissing._last, Setting.SortMissing._last, Setting.SortMissing._first }) + private static class SettingsInvalidSortParameterSizes { + @Nullable @Id private String id; + @Nullable @Field(name = "first-field", type = FieldType.Keyword) private String firstField; + @Nullable @Field(name = "second-field", type = FieldType.Keyword) private String secondField; } + +@Document(indexName = "dontcare") +// property names here, not field names +@Setting(sortFields = { "secondField", "firstField" }, sortModes = { Setting.SortMode.max, Setting.SortMode.min }, + sortOrders = { Setting.SortOrder.desc, Setting.SortOrder.asc }, + sortMissingValues = { Setting.SortMissing._last, Setting.SortMissing._first }) +private static class SettingsValidSortParameterSizes { + @Nullable @Id private String id; + @Nullable @Field(name = "first_field", type = FieldType.Keyword) private String firstField; + @Nullable @Field(name = "second_field", type = FieldType.Keyword) private String secondField; +} + + // endregion } diff --git a/src/test/java/org/springframework/data/elasticsearch/core/query/CriteriaQueryIntegrationTests.java b/src/test/java/org/springframework/data/elasticsearch/core/query/CriteriaQueryIntegrationTests.java index 67c0199a2..18e2527a3 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/query/CriteriaQueryIntegrationTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/query/CriteriaQueryIntegrationTests.java @@ -797,17 +797,15 @@ public void shouldEscapeValue() { assertThat(sampleEntity1).isNotNull(); } - @Document(indexName = "test-index-sample-core-query", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-sample-core-query") static class SampleEntity { - @Nullable - @Id private String id; + @Nullable @Id private String id; @Nullable @Field(type = Text, store = true, fielddata = true) private String type; @Nullable @Field(type = Text, store = true, fielddata = true) private String message; @Nullable private int rate; @Nullable @Version private Long version; - public SampleEntity() { - } + public SampleEntity() {} public SampleEntity(@Nullable String id, @Nullable String message) { this.id = id; diff --git a/src/test/java/org/springframework/data/elasticsearch/core/routing/ElasticsearchOperationsRoutingTests.java b/src/test/java/org/springframework/data/elasticsearch/core/routing/ElasticsearchOperationsRoutingTests.java index db6f99a1c..ed096ca0b 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/routing/ElasticsearchOperationsRoutingTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/routing/ElasticsearchOperationsRoutingTests.java @@ -28,6 +28,7 @@ import org.springframework.data.annotation.Id; import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.annotations.Routing; +import org.springframework.data.elasticsearch.annotations.Setting; import org.springframework.data.elasticsearch.core.ElasticsearchOperations; import org.springframework.data.elasticsearch.core.IndexOperations; import org.springframework.data.elasticsearch.core.SearchHits; @@ -117,7 +118,8 @@ void shouldStoreDataWithDifferentRoutingAndGetTheRoutingInTheSearchResult() { assertThat(searchHits.getSearchHit(0).getRouting()).isEqualTo(ID_2); } - @Document(indexName = INDEX, shards = 5) + @Document(indexName = INDEX) + @Setting(shards = 5) @Routing("routing") static class RoutingEntity { @Nullable @Id private String id; diff --git a/src/test/java/org/springframework/data/elasticsearch/core/routing/ReactiveElasticsearchOperationsRoutingTests.java b/src/test/java/org/springframework/data/elasticsearch/core/routing/ReactiveElasticsearchOperationsRoutingTests.java index 84ae0b713..c57ebf92a 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/routing/ReactiveElasticsearchOperationsRoutingTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/routing/ReactiveElasticsearchOperationsRoutingTests.java @@ -29,6 +29,7 @@ import org.springframework.data.annotation.Id; import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.annotations.Routing; +import org.springframework.data.elasticsearch.annotations.Setting; import org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations; import org.springframework.data.elasticsearch.core.ReactiveIndexOperations; import org.springframework.data.elasticsearch.core.SearchHit; @@ -115,7 +116,8 @@ void shouldStoreDataWithDifferentRoutingAndGetTheRoutingInTheSearchResult() { assertThat(searchHits.get(0).getRouting()).isEqualTo(ID_2); } - @Document(indexName = INDEX, shards = 5) + @Document(indexName = INDEX) + @Setting(shards = 5) @Routing("routing") static class RoutingEntity { @Nullable @Id private String id; diff --git a/src/test/java/org/springframework/data/elasticsearch/repositories/cdi/CdiRepositoryTests.java b/src/test/java/org/springframework/data/elasticsearch/repositories/cdi/CdiRepositoryTests.java index a2fed6d3b..321e32f1e 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repositories/cdi/CdiRepositoryTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/repositories/cdi/CdiRepositoryTests.java @@ -157,7 +157,7 @@ public void returnOneFromCustomImpl() { * @author Mohsin Husen * @author Artur Konczak */ - @Document(indexName = "test-index-product-cdi-repository", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-product-cdi-repository") static class Product { @Nullable @Id private String id; @Nullable private List title; @@ -280,7 +280,7 @@ public void setLastModified(@Nullable Date lastModified) { } } - @Document(indexName = "test-index-person-cdi-repository", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-person-cdi-repository") static class Person { @Id private String id; @@ -293,7 +293,7 @@ static class Person { } - @Document(indexName = "test-index-book-cdi-repository", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-book-cdi-repository") static class Book { @Nullable @Id private String id; @Nullable private String name; diff --git a/src/test/java/org/springframework/data/elasticsearch/repositories/complex/custommethod/autowiring/ComplexCustomMethodRepositoryTests.java b/src/test/java/org/springframework/data/elasticsearch/repositories/complex/custommethod/autowiring/ComplexCustomMethodRepositoryTests.java index b5b0015b5..df74cf0dd 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repositories/complex/custommethod/autowiring/ComplexCustomMethodRepositoryTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/repositories/complex/custommethod/autowiring/ComplexCustomMethodRepositoryTests.java @@ -79,11 +79,9 @@ public void shouldExecuteComplexCustomMethod() { assertThat(result).isEqualTo("2+2=4"); } - @Document(indexName = "test-index-sample-repositories-complex-custommethod-autowiring", replicas = 0, - refreshInterval = "-1") + @Document(indexName = "test-index-sample-repositories-complex-custommethod-autowiring") static class SampleEntity { - @Nullable - @Id private String id; + @Nullable @Id private String id; @Nullable @Field(type = Text, store = true, fielddata = true) private String type; @Nullable @Field(type = Text, store = true, fielddata = true) private String message; diff --git a/src/test/java/org/springframework/data/elasticsearch/repositories/complex/custommethod/manualwiring/ComplexCustomMethodRepositoryManualWiringTests.java b/src/test/java/org/springframework/data/elasticsearch/repositories/complex/custommethod/manualwiring/ComplexCustomMethodRepositoryManualWiringTests.java index 9a68942f0..4a535a291 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repositories/complex/custommethod/manualwiring/ComplexCustomMethodRepositoryManualWiringTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/repositories/complex/custommethod/manualwiring/ComplexCustomMethodRepositoryManualWiringTests.java @@ -77,7 +77,7 @@ public void shouldExecuteComplexCustomMethod() { assertThat(result).isEqualTo("3+3=6"); } - @Document(indexName = "test-index-sample-repository-manual-wiring", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-sample-repository-manual-wiring") static class SampleEntity { @Nullable @Id private String id; @Nullable @Field(type = Text, store = true, fielddata = true) private String type; diff --git a/src/test/java/org/springframework/data/elasticsearch/repositories/custommethod/CustomMethodRepositoryBaseTests.java b/src/test/java/org/springframework/data/elasticsearch/repositories/custommethod/CustomMethodRepositoryBaseTests.java index e8fe1d60c..4284f03ab 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repositories/custommethod/CustomMethodRepositoryBaseTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/repositories/custommethod/CustomMethodRepositoryBaseTests.java @@ -1631,7 +1631,7 @@ void shouldStreamSearchHitsWithQueryAnnotatedMethod() { assertThat(count).isEqualTo(20); } - @Document(indexName = "test-index-sample-repositories-custom-method", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-sample-repositories-custom-method") static class SampleEntity { @Nullable @Id private String id; diff --git a/src/test/java/org/springframework/data/elasticsearch/repositories/doubleid/DoubleIDRepositoryTests.java b/src/test/java/org/springframework/data/elasticsearch/repositories/doubleid/DoubleIDRepositoryTests.java index 2ccc7ba53..dc8d526f8 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repositories/doubleid/DoubleIDRepositoryTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/repositories/doubleid/DoubleIDRepositoryTests.java @@ -121,7 +121,7 @@ public void shouldSaveDocument() { * @author Mohsin Husen */ - @Document(indexName = "test-index-double-keyed-entity", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-double-keyed-entity") static class DoubleIDEntity { @Id private Double id; diff --git a/src/test/java/org/springframework/data/elasticsearch/repositories/geo/SpringDataGeoRepositoryTests.java b/src/test/java/org/springframework/data/elasticsearch/repositories/geo/SpringDataGeoRepositoryTests.java index 6bda75c78..5f7fcd1a2 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repositories/geo/SpringDataGeoRepositoryTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/repositories/geo/SpringDataGeoRepositoryTests.java @@ -110,7 +110,7 @@ private double[] toGeoArray(Point point) { return new double[] { point.getX(), point.getY() }; } - @Document(indexName = "test-index-geo-repository", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-geo-repository") static class GeoEntity { @Nullable @Id private String id; // geo shape - Spring Data diff --git a/src/test/java/org/springframework/data/elasticsearch/repositories/integer/IntegerIDRepositoryTests.java b/src/test/java/org/springframework/data/elasticsearch/repositories/integer/IntegerIDRepositoryTests.java index 3f1fb8bc4..ff1a0a923 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repositories/integer/IntegerIDRepositoryTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/repositories/integer/IntegerIDRepositoryTests.java @@ -122,7 +122,7 @@ public void shouldSaveDocument() { * @author Mohsin Husen */ - @Document(indexName = "test-index-integer-keyed-entity", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-integer-keyed-entity") static class IntegerIDEntity { @Id private Integer id; diff --git a/src/test/java/org/springframework/data/elasticsearch/repositories/nestedobject/InnerObjectTests.java b/src/test/java/org/springframework/data/elasticsearch/repositories/nestedobject/InnerObjectTests.java index 6d826c3a3..2740f99e5 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repositories/nestedobject/InnerObjectTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/repositories/nestedobject/InnerObjectTests.java @@ -96,7 +96,7 @@ public void shouldIndexInnerObject() { assertThat(bookRepository.findById(id)).isNotNull(); } - @Document(indexName = "test-index-book", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-book") static class Book { @Nullable @Id private String id; @Nullable private String name; diff --git a/src/test/java/org/springframework/data/elasticsearch/repositories/spel/SpELEntityTests.java b/src/test/java/org/springframework/data/elasticsearch/repositories/spel/SpELEntityTests.java index 4412f62fb..f9b7f0dfc 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repositories/spel/SpELEntityTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/repositories/spel/SpELEntityTests.java @@ -103,7 +103,7 @@ public void shouldSupportSpelInType() { * * @author Artur Konczak */ - @Document(indexName = "#{'test-index-abz'+'-'+'entity'}", replicas = 0, refreshInterval = "-1") + @Document(indexName = "#{'test-index-abz'+'-'+'entity'}") static class SpELEntity { @Id private String id; diff --git a/src/test/java/org/springframework/data/elasticsearch/repositories/uuidkeyed/UUIDElasticsearchRepositoryTests.java b/src/test/java/org/springframework/data/elasticsearch/repositories/uuidkeyed/UUIDElasticsearchRepositoryTests.java index 916ea2af6..f9ff406b0 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repositories/uuidkeyed/UUIDElasticsearchRepositoryTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/repositories/uuidkeyed/UUIDElasticsearchRepositoryTests.java @@ -545,7 +545,7 @@ private static List createSampleEntitiesWithMessage(Strin return sampleEntities; } - @Document(indexName = "test-index-uuid-keyed", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-uuid-keyed") static class SampleEntityUUIDKeyed { @Nullable @Id private UUID id; @Nullable private String type; diff --git a/src/test/java/org/springframework/data/elasticsearch/repository/config/ReactiveElasticsearchRepositoriesRegistrarTests.java b/src/test/java/org/springframework/data/elasticsearch/repository/config/ReactiveElasticsearchRepositoriesRegistrarTests.java index 30a0d51ac..dd025bb3d 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repository/config/ReactiveElasticsearchRepositoriesRegistrarTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/repository/config/ReactiveElasticsearchRepositoriesRegistrarTests.java @@ -58,7 +58,7 @@ public void testConfiguration() { interface ReactiveSampleEntityRepository extends ReactiveElasticsearchRepository {} - @Document(indexName = "test-index-sample-reactive-repositories-registrar", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-sample-reactive-repositories-registrar") static class SampleEntity { @Nullable @Id private String id; @Nullable @Field(type = Text, store = true, fielddata = true) private String type; diff --git a/src/test/java/org/springframework/data/elasticsearch/repository/query/ElasticsearchStringQueryUnitTests.java b/src/test/java/org/springframework/data/elasticsearch/repository/query/ElasticsearchStringQueryUnitTests.java index f12f998cb..6e63773a1 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repository/query/ElasticsearchStringQueryUnitTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/repository/query/ElasticsearchStringQueryUnitTests.java @@ -118,7 +118,7 @@ Person findWithRepeatedPlaceholder(String arg0, String arg1, String arg2, String * @author Artur Konczak */ - @Document(indexName = "test-index-person-query-unittest", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-person-query-unittest") static class Person { @Nullable @Id private String id; @@ -163,7 +163,7 @@ public void setBooks(List books) { } } - @Document(indexName = "test-index-book-query-unittest", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-book-query-unittest") static class Book { @Nullable @Id private String id; @Nullable private String name; diff --git a/src/test/java/org/springframework/data/elasticsearch/repository/query/ReactiveElasticsearchQueryMethodUnitTests.java b/src/test/java/org/springframework/data/elasticsearch/repository/query/ReactiveElasticsearchQueryMethodUnitTests.java index bc549926c..e6aa4c298 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repository/query/ReactiveElasticsearchQueryMethodUnitTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/repository/query/ReactiveElasticsearchQueryMethodUnitTests.java @@ -166,7 +166,7 @@ interface NonReactiveRepository extends Repository { * @author Artur Konczak */ - @Document(indexName = INDEX_NAME, replicas = 0, refreshInterval = "-1") + @Document(indexName = INDEX_NAME) static class Person { @Nullable @Id private String id; @@ -215,7 +215,7 @@ public void setBooks(List books) { } } - @Document(indexName = "test-index-book-reactive-repository-query", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-book-reactive-repository-query") static class Book { @Nullable @Id private String id; @Nullable private String name; diff --git a/src/test/java/org/springframework/data/elasticsearch/repository/query/ReactiveElasticsearchStringQueryUnitTests.java b/src/test/java/org/springframework/data/elasticsearch/repository/query/ReactiveElasticsearchStringQueryUnitTests.java index cb45584c7..bf17c3c39 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repository/query/ReactiveElasticsearchStringQueryUnitTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/repository/query/ReactiveElasticsearchStringQueryUnitTests.java @@ -171,7 +171,7 @@ Person findWithRepeatedPlaceholder(String arg0, String arg1, String arg2, String * @author Artur Konczak */ - @Document(indexName = "test-index-person-reactive-repository-string-query", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-person-reactive-repository-string-query") public class Person { @Nullable @Id private String id; @@ -219,7 +219,7 @@ public void setBooks(List books) { } } - @Document(indexName = "test-index-book-reactive-repository-string-query", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-book-reactive-repository-string-query") static class Book { @Nullable @Id private String id; @Nullable private String name; diff --git a/src/test/java/org/springframework/data/elasticsearch/repository/query/keywords/QueryKeywordsTests.java b/src/test/java/org/springframework/data/elasticsearch/repository/query/keywords/QueryKeywordsTests.java index 5033a2ff7..67c1c5b1e 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repository/query/keywords/QueryKeywordsTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/repository/query/keywords/QueryKeywordsTests.java @@ -273,7 +273,7 @@ void shouldReturnEmptyListOnDerivedMethodWithEmptyInputList() { assertThat(products).isEmpty(); } - @Document(indexName = "test-index-product-query-keywords", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-product-query-keywords") static class Product { @Nullable @Id private String id; @Nullable private String name; diff --git a/src/test/java/org/springframework/data/elasticsearch/repository/support/SimpleElasticsearchRepositoryIntegrationTests.java b/src/test/java/org/springframework/data/elasticsearch/repository/support/SimpleElasticsearchRepositoryIntegrationTests.java index 72bb7ff7c..6d4ae3c5e 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repository/support/SimpleElasticsearchRepositoryIntegrationTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/repository/support/SimpleElasticsearchRepositoryIntegrationTests.java @@ -677,7 +677,7 @@ private static List createSampleEntitiesWithMessage(String message return sampleEntities; } - @Document(indexName = "test-index-sample-simple-repository", replicas = 0, refreshInterval = "-1") + @Document(indexName = "test-index-sample-simple-repository") static class SampleEntity { @Nullable @Id private String id; @Nullable @Field(type = Text, store = true, fielddata = true) private String type; diff --git a/src/test/java/org/springframework/data/elasticsearch/repository/support/SimpleReactiveElasticsearchRepositoryTests.java b/src/test/java/org/springframework/data/elasticsearch/repository/support/SimpleReactiveElasticsearchRepositoryTests.java index 7076c0829..a233be31e 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repository/support/SimpleReactiveElasticsearchRepositoryTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/repository/support/SimpleReactiveElasticsearchRepositoryTests.java @@ -608,7 +608,7 @@ interface ReactiveSampleEntityRepository extends ReactiveCrudRepository retrieveCountByText(String message); } - @Document(indexName = INDEX, replicas = 0, refreshInterval = "-1") + @Document(indexName = INDEX) static class SampleEntity { @Nullable @Id private String id; @Nullable @Field(type = Text, store = true, fielddata = true) private String type;