1
0
mirror of synced 2026-05-23 12:43:17 +00:00

Compare commits

..

11 Commits

Author SHA1 Message Date
Spring Builds c36b878cee Release version 4.4.3 (2021.2.3).
See #2221
2022-09-19 11:38:46 +00:00
Spring Builds 2efa79d469 Prepare 4.4.3 (2021.2.3).
See #2221
2022-09-19 11:36:24 +00:00
Peter-Josef Meisch 20fde914df Upgrade to Elasticsearch 7.17.6.
Original Pull Request #2289
Closes #2285
2022-09-04 12:42:14 +02:00
Peter-Josef Meisch 988736dd41 Fix NPE in RequestFactory when language in UpdateQuery is not set (4.4.x).
Original Pull Request #2288
Closes #2287
2022-09-03 07:50:01 +02:00
Peter-Josef Meisch 346c5cce58 Fix mapping of property values into a collection.
When reading from Elasticsearch into a property of type Collection<T> (List<T> or Set<T>) the MappingElasticsearchConverter now can read both from the returned JSON:

    an array of T objects - will put the objects in a corresponding collection
    a single T object will put the single object into a corrsponding colletcion

This is implemented and tested for both: entities where the properties have setters and immutable classes that only provide an all-args constructor.

Original Pull Request #2282
Closes #2280

(cherry picked from commit 86634ceb38)
2022-08-29 21:06:38 +02:00
Peter-Josef Meisch a3ebd8be78 Fix update call in reactive client (Elasticsearch 7 client)
Original Pull Request #2281
Closes #2276

(cherry picked from commit 8377f64a8a)
2022-08-26 08:12:22 +02:00
Peter-Josef Meisch 3c6d96e49f Don't try to write non-writeable properties.
Original Pull Request #2249
Closes #2230

(cherry picked from commit acf02a1dc9)

# Conflicts:
#	src/main/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverter.java
2022-08-04 12:11:22 +02:00
Peter-Josef Meisch be70a398be Fix exists query for imperative repository implementation.
Original Pull Request #2236
Closes #2162

(cherry picked from commit 373be49f97)
2022-07-22 22:01:26 +02:00
Peter-Josef Meisch e3e666fd2e Upgrade to Elasticsearch 7.17.5.
Original Pull Request #2224
Closes #2215
2022-07-16 21:30:41 +02:00
Christoph Strobl cb3d1e11d3 After release cleanups.
See #2186
2022-07-15 11:24:08 +02:00
Christoph Strobl 9e17bf3df8 Prepare next development iteration.
See #2186
2022-07-15 11:24:05 +02:00
22 changed files with 785 additions and 95 deletions
+5 -5
View File
@@ -5,12 +5,12 @@
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>4.4.2</version>
<version>4.4.3</version>
<parent>
<groupId>org.springframework.data.build</groupId>
<artifactId>spring-data-parent</artifactId>
<version>2.7.2</version>
<version>2.7.3</version>
</parent>
<name>Spring Data Elasticsearch</name>
@@ -19,12 +19,12 @@
<properties>
<!-- version of the RestHighLevelClient -->
<elasticsearch-rhlc>7.17.4</elasticsearch-rhlc>
<elasticsearch-rhlc>7.17.6</elasticsearch-rhlc>
<!-- version of the new ElasticsearchClient -->
<elasticsearch-java>7.17.4</elasticsearch-java>
<elasticsearch-java>7.17.6</elasticsearch-java>
<log4j>2.17.1</log4j>
<netty>4.1.65.Final</netty>
<springdata.commons>2.7.2</springdata.commons>
<springdata.commons>2.7.3</springdata.commons>
<testcontainers>1.16.2</testcontainers>
<blockhound-junit>1.0.6.RELEASE</blockhound-junit>
<java-module-name>spring.data.elasticsearch</java-module-name>
+4 -4
View File
@@ -29,15 +29,15 @@ Requires an installation of https://www.elastic.co/products/elasticsearch[Elasti
[[preface.versions]]
=== Versions
The following table shows the Elasticsearch versions that are used by Spring Data release trains and version of
Spring Data Elasticsearch included in that, as well as the Spring Boot versions referring to that particular Spring
Data release train. The Elasticsearch version given shows with which client libraries Spring Data Elasticsearch was
The following table shows the Elasticsearch versions that are used by Spring Data release trains and version of
Spring Data Elasticsearch included in that, as well as the Spring Boot versions referring to that particular Spring
Data release train. The Elasticsearch version given shows with which client libraries Spring Data Elasticsearch was
built and tested.
[cols="^,^,^,^,^",options="header"]
|===
| Spring Data Release Train | Spring Data Elasticsearch | Elasticsearch | Spring Framework | Spring Boot
| 2021.2 (Raj) | 4.4.x | 7.17.4 | 5.3.x | 2.7.x
| 2021.2 (Raj) | 4.4.x | 7.17.6 | 5.3.x | 2.7.x
| 2021.1 (Q) | 4.3.x | 7.15.2 | 5.3.x | 2.6.x
| 2021.0 (Pascal) | 4.2.xfootnote:oom[Out of maintenance] | 7.12.0 | 5.3.x | 2.5.x
| 2020.0 (Ockham)footnote:oom[] | 4.1.xfootnote:oom[] | 7.9.3 | 5.3.2 | 2.4.x
@@ -82,7 +82,7 @@ The dependencies for the new Elasticsearch client are still optional in Spring D
<dependency>
<groupId>co.elastic.clients</groupId>
<artifactId>elasticsearch-java</artifactId>
<version>7.17.4</version>
<version>7.17.6</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
@@ -93,7 +93,7 @@ The dependencies for the new Elasticsearch client are still optional in Spring D
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId> <!-- is Apache 2-->
<version>7.17.4</version>
<version>7.17.6</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
@@ -5,7 +5,7 @@
== New in Spring Data Elasticsearch 4.4
* Introduction of new imperative and reactive clients using the classes from the new Elasticsearch Java client
* Upgrade to Elasticsearch 7.17.4.
* Upgrade to Elasticsearch 7.17.6.
[[new-features.4-3-0]]
== New in Spring Data Elasticsearch 4.3
@@ -32,7 +32,16 @@ import co.elastic.clients.elasticsearch._types.mapping.RuntimeFieldType;
import co.elastic.clients.elasticsearch._types.mapping.TypeMapping;
import co.elastic.clients.elasticsearch._types.query_dsl.Like;
import co.elastic.clients.elasticsearch.cluster.HealthRequest;
import co.elastic.clients.elasticsearch.core.*;
import co.elastic.clients.elasticsearch.core.BulkRequest;
import co.elastic.clients.elasticsearch.core.DeleteByQueryRequest;
import co.elastic.clients.elasticsearch.core.DeleteRequest;
import co.elastic.clients.elasticsearch.core.GetRequest;
import co.elastic.clients.elasticsearch.core.IndexRequest;
import co.elastic.clients.elasticsearch.core.MgetRequest;
import co.elastic.clients.elasticsearch.core.MsearchRequest;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.UpdateByQueryRequest;
import co.elastic.clients.elasticsearch.core.UpdateRequest;
import co.elastic.clients.elasticsearch.core.bulk.BulkOperation;
import co.elastic.clients.elasticsearch.core.bulk.CreateOperation;
import co.elastic.clients.elasticsearch.core.bulk.IndexOperation;
@@ -42,7 +51,6 @@ import co.elastic.clients.elasticsearch.core.search.Highlight;
import co.elastic.clients.elasticsearch.core.search.Rescore;
import co.elastic.clients.elasticsearch.core.search.SourceConfig;
import co.elastic.clients.elasticsearch.indices.*;
import co.elastic.clients.elasticsearch.indices.ExistsRequest;
import co.elastic.clients.elasticsearch.indices.update_aliases.Action;
import co.elastic.clients.json.JsonData;
import co.elastic.clients.json.JsonpDeserializer;
@@ -820,7 +828,11 @@ class RequestConverter {
.refresh(reindexRequest.getRefresh()) //
.requireAlias(reindexRequest.getRequireAlias()) //
.requestsPerSecond(reindexRequest.getRequestsPerSecond()) //
.slices(reindexRequest.getSlices());
;
if (reindexRequest.getSlices() != null) {
builder.slices(sb -> sb.value(reindexRequest.getSlices().intValue()));
}
return builder.build();
}
@@ -963,9 +975,12 @@ class RequestConverter {
.pipeline(updateQuery.getPipeline()) //
.requestsPerSecond(
updateQuery.getRequestsPerSecond() != null ? updateQuery.getRequestsPerSecond().longValue() : null) //
.slices(updateQuery.getSlices() != null ? Long.valueOf(updateQuery.getSlices()) : null) //
;
if (updateQuery.getSlices() != null) {
ub.slices(sb -> sb.value(updateQuery.getSlices() != null ? updateQuery.getSlices() : null));
}
if (updateQuery.getAbortOnVersionConflict() != null) {
ub.conflicts(updateQuery.getAbortOnVersionConflict() ? Conflicts.Abort : Conflicts.Proceed);
}
@@ -336,8 +336,13 @@ public class RequestConverters {
public static Request index(IndexRequest indexRequest) {
String method = Strings.hasLength(indexRequest.id()) ? HttpMethod.PUT.name() : HttpMethod.POST.name();
boolean isCreate = (indexRequest.opType() == DocWriteRequest.OpType.CREATE);
String endpoint = endpoint(indexRequest.index(), indexRequest.type(), indexRequest.id(),
isCreate ? "_create" : null);
String endpoint;
if (indexRequest.opType() == DocWriteRequest.OpType.CREATE) {
endpoint = indexRequest.type().equals("_doc") ? endpoint(indexRequest.index(), "_create", indexRequest.id())
: endpoint(indexRequest.index(), indexRequest.type(), indexRequest.id(), "_create");
} else {
endpoint = endpoint(indexRequest.index(), indexRequest.type(), indexRequest.id());
}
Request request = new Request(method, endpoint);
Params parameters = new Params(request);
@@ -362,7 +367,9 @@ public class RequestConverters {
}
public static Request update(UpdateRequest updateRequest) {
String endpoint = endpoint(updateRequest.index(), updateRequest.type(), updateRequest.id(), "_update");
String endpoint = updateRequest.type().equals("_doc")
? endpoint(updateRequest.index(), "_update", updateRequest.id())
: endpoint(updateRequest.index(), updateRequest.type(), updateRequest.id(), "_update");
Request request = new Request(HttpMethod.POST.name(), endpoint);
Params parameters = new Params(request);
@@ -500,8 +507,11 @@ public class RequestConverters {
}
public static Request explain(ExplainRequest explainRequest) {
String endpoint = explainRequest.type().equals("_doc")
? endpoint(explainRequest.index(), "_explain", explainRequest.id())
: endpoint(explainRequest.index(), explainRequest.type(), explainRequest.id(), "_explain");
Request request = new Request(HttpMethod.GET.name(),
endpoint(explainRequest.index(), explainRequest.type(), explainRequest.id(), "_explain"));
endpoint(explainRequest.index(), explainRequest.type(), explainRequest.id(), endpoint));
Params params = new Params(request);
params.withStoredFields(explainRequest.storedFields());
@@ -478,7 +478,7 @@ public abstract class AbstractElasticsearchTemplate implements ElasticsearchOper
ElasticsearchPersistentProperty idProperty = persistentEntity.getIdProperty();
// Only deal with text because ES generated Ids are strings!
if (indexedObjectInformation.getId() != null && idProperty != null
if (indexedObjectInformation.getId() != null && idProperty != null && idProperty.isWritable()
&& idProperty.getType().isAssignableFrom(String.class)) {
propertyAccessor.setProperty(idProperty, indexedObjectInformation.getId());
}
@@ -259,7 +259,7 @@ abstract public class AbstractReactiveElasticsearchTemplate
ElasticsearchPersistentProperty idProperty = persistentEntity.getIdProperty();
// Only deal with text because ES generated Ids are strings!
if (indexedObjectInformation.getId() != null && idProperty != null
if (indexedObjectInformation.getId() != null && idProperty != null && idProperty.isWritable()
&& idProperty.getType().isAssignableFrom(String.class)) {
propertyAccessor.setProperty(idProperty, indexedObjectInformation.getId());
}
@@ -613,7 +613,7 @@ class RequestFactory {
Object queryObject = query.getObject();
if (queryObject != null) {
String id = StringUtils.isEmpty(query.getId()) ? getPersistentEntityId(queryObject) : query.getId();
String id = StringUtils.hasText(query.getId()) ? query.getId() : getPersistentEntityId(queryObject);
// If we have a query id and a document id, do not ask ES to generate one.
if (id != null) {
indexRequest = new IndexRequest(indexName).id(id);
@@ -1027,7 +1027,14 @@ class RequestFactory {
if (params == null) {
params = new HashMap<>();
}
Script script = new Script(getScriptType(query.getScriptType()), query.getLang(), query.getScript(), params);
org.elasticsearch.script.ScriptType scriptType = getScriptType(query.getScriptType());
String lang = query.getLang();
if (scriptType == org.elasticsearch.script.ScriptType.INLINE && lang == null) {
lang = "painless";
}
Script script = new Script(scriptType, lang, query.getScript(), params);
updateRequest.script(script);
}
@@ -192,7 +192,7 @@ public class MappingElasticsearchConverter
}
/**
* Class to do the actual writing. The methods originally were in the MappingElasticsearchConverter class, but are
* Class to do the actual reading. The methods originally were in the MappingElasticsearchConverter class, but are
* refactored to allow for keeping state during the conversion of an object.
*/
private static class Reader extends Base {
@@ -211,10 +211,17 @@ public class MappingElasticsearchConverter
}
@SuppressWarnings("unchecked")
/**
* Reads the given source into the given type.
*
* @param type they type to convert the given source to.
* @param source the source to create an object of the given type from.
* @return the object that was read
*/
<R> R read(Class<R> type, Document source) {
TypeInformation<R> typeHint = ClassTypeInformation.from((Class<R>) ClassUtils.getUserClass(type));
R r = read(typeHint, source);
TypeInformation<R> typeInformation = ClassTypeInformation.from((Class<R>) ClassUtils.getUserClass(type));
R r = read(typeInformation, source);
if (r == null) {
throw new ConversionException("could not convert into object of class " + type);
@@ -225,11 +232,11 @@ public class MappingElasticsearchConverter
@Nullable
@SuppressWarnings("unchecked")
private <R> R read(TypeInformation<R> type, Map<String, Object> source) {
private <R> R read(TypeInformation<R> typeInformation, Map<String, Object> source) {
Assert.notNull(source, "Source must not be null!");
TypeInformation<? extends R> typeToUse = typeMapper.readType(source, type);
TypeInformation<? extends R> typeToUse = typeMapper.readType(source, typeInformation);
Class<? extends R> rawType = typeToUse.getType();
if (conversions.hasCustomReadTarget(source.getClass(), rawType)) {
@@ -247,8 +254,8 @@ public class MappingElasticsearchConverter
if (typeToUse.equals(ClassTypeInformation.OBJECT)) {
return (R) source;
}
// Retrieve persistent entity info
// Retrieve persistent entity info
ElasticsearchPersistentEntity<?> entity = mappingContext.getPersistentEntity(typeToUse);
if (entity == null) {
@@ -333,7 +340,7 @@ public class MappingElasticsearchConverter
PersistentPropertyAccessor<R> propertyAccessor = new ConvertingPropertyAccessor<>(
targetEntity.getPropertyAccessor(result), conversionService);
// Only deal with String because ES generated Ids are strings !
if (idProperty != null && idProperty.getType().isAssignableFrom(String.class)) {
if (idProperty != null && idProperty.isWritable() && idProperty.getType().isAssignableFrom(String.class)) {
propertyAccessor.setProperty(idProperty, document.getId());
}
}
@@ -365,7 +372,6 @@ public class MappingElasticsearchConverter
}
return result;
}
private ParameterValueProvider<ElasticsearchPersistentProperty> getParameterProvider(
@@ -397,7 +403,7 @@ public class MappingElasticsearchConverter
for (ElasticsearchPersistentProperty prop : entity) {
if (entity.isConstructorArgument(prop) || !prop.isReadable()) {
if (entity.isConstructorArgument(prop) || !prop.isReadable() || !prop.isWritable()) {
continue;
}
@@ -455,12 +461,44 @@ public class MappingElasticsearchConverter
} else if (value.getClass().isArray()) {
return (T) readCollectionOrArray(type, Arrays.asList((Object[]) value));
} else if (value instanceof Map) {
TypeInformation<?> collectionComponentType = getCollectionComponentType(type);
if (collectionComponentType != null) {
Object o = read(collectionComponentType, (Map<String, Object>) value);
return getCollectionWithSingleElement(type, collectionComponentType, o);
}
return (T) read(type, (Map<String, Object>) value);
} else {
TypeInformation<?> collectionComponentType = getCollectionComponentType(type);
if (collectionComponentType != null
&& collectionComponentType.isAssignableFrom(ClassTypeInformation.from(value.getClass()))) {
Object o = getPotentiallyConvertedSimpleRead(value, collectionComponentType);
return getCollectionWithSingleElement(type, collectionComponentType, o);
}
return (T) getPotentiallyConvertedSimpleRead(value, rawType);
}
}
@SuppressWarnings("unchecked")
private static <T> T getCollectionWithSingleElement(TypeInformation<?> collectionType,
TypeInformation<?> componentType, Object element) {
Collection<Object> collection = CollectionFactory.createCollection(collectionType.getType(),
componentType.getType(), 1);
collection.add(element);
return (T) collection;
}
/**
* @param type the type to check
* @return true if type is a collectoin, null otherwise,
*/
@Nullable
TypeInformation<?> getCollectionComponentType(TypeInformation<?> type) {
return type.isCollectionLike() ? type.getComponentType() : null;
}
private Object propertyConverterRead(ElasticsearchPersistentProperty property, Object source) {
PropertyValueConverter propertyValueConverter = Objects.requireNonNull(property.getPropertyValueConverter());
@@ -649,7 +687,8 @@ public class MappingElasticsearchConverter
* @see org.springframework.data.mapping.model.SpELExpressionParameterValueProvider#potentiallyConvertSpelValue(java.lang.Object, org.springframework.data.mapping.PreferredConstructor.Parameter)
*/
@Override
protected <T> T potentiallyConvertSpelValue(Object object, Parameter<T, ElasticsearchPersistentProperty> parameter) {
protected <T> T potentiallyConvertSpelValue(Object object,
Parameter<T, ElasticsearchPersistentProperty> parameter) {
return readValue(object, parameter.getType());
}
}
@@ -1117,17 +1156,18 @@ public class MappingElasticsearchConverter
Assert.notNull(query, "query must not be null");
if (domainClass != null) {
if (domainClass == null) {
return;
}
updateFieldsAndSourceFilter(query, domainClass);
updatePropertiesInFieldsAndSourceFilter(query, domainClass);
if (query instanceof CriteriaQuery) {
updateCriteriaQuery((CriteriaQuery) query, domainClass);
}
if (query instanceof CriteriaQuery) {
updatePropertiesInCriteriaQuery((CriteriaQuery) query, domainClass);
}
}
private void updateFieldsAndSourceFilter(Query query, Class<?> domainClass) {
private void updatePropertiesInFieldsAndSourceFilter(Query query, Class<?> domainClass) {
ElasticsearchPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(domainClass);
@@ -1165,14 +1205,22 @@ public class MappingElasticsearchConverter
}
}
private List<String> updateFieldNames(List<String> fields, ElasticsearchPersistentEntity<?> persistentEntity) {
return fields.stream().map(fieldName -> {
/**
* relaces the fieldName with the property name of a property of the persistentEntity with the corresponding
* fieldname. If no such property exists, the original fieldName is kept.
*
* @param fieldNames list of fieldnames
* @param persistentEntity the persistent entity to check
* @return an updated list of field names
*/
private List<String> updateFieldNames(List<String> fieldNames, ElasticsearchPersistentEntity<?> persistentEntity) {
return fieldNames.stream().map(fieldName -> {
ElasticsearchPersistentProperty persistentProperty = persistentEntity.getPersistentProperty(fieldName);
return persistentProperty != null ? persistentProperty.getFieldName() : fieldName;
}).collect(Collectors.toList());
}
private void updateCriteriaQuery(CriteriaQuery criteriaQuery, Class<?> domainClass) {
private void updatePropertiesInCriteriaQuery(CriteriaQuery criteriaQuery, Class<?> domainClass) {
Assert.notNull(criteriaQuery, "criteriaQuery must not be null");
Assert.notNull(domainClass, "domainClass must not be null");
@@ -1181,17 +1229,17 @@ public class MappingElasticsearchConverter
if (persistentEntity != null) {
for (Criteria chainedCriteria : criteriaQuery.getCriteria().getCriteriaChain()) {
updateCriteria(chainedCriteria, persistentEntity);
updatePropertiesInCriteria(chainedCriteria, persistentEntity);
}
for (Criteria subCriteria : criteriaQuery.getCriteria().getSubCriteria()) {
for (Criteria chainedCriteria : subCriteria.getCriteriaChain()) {
updateCriteria(chainedCriteria, persistentEntity);
updatePropertiesInCriteria(chainedCriteria, persistentEntity);
}
}
}
}
private void updateCriteria(Criteria criteria, ElasticsearchPersistentEntity<?> persistentEntity) {
private void updatePropertiesInCriteria(Criteria criteria, ElasticsearchPersistentEntity<?> persistentEntity) {
Field field = criteria.getField();
@@ -128,6 +128,9 @@ public class ElasticsearchPartQuery extends AbstractElasticsearchRepositoryQuery
} else if (tree.isCountProjection()) {
result = elasticsearchOperations.count(query, clazz, index);
} else if (tree.isExistsProjection()) {
long count = elasticsearchOperations.count(query, clazz, index);
result = count > 0;
} else {
result = elasticsearchOperations.searchOne(query, clazz, index);
}
+2 -1
View File
@@ -1,4 +1,4 @@
Spring Data Elasticsearch 4.4.2 (2021.2.2)
Spring Data Elasticsearch 4.4.3 (2021.2.3)
Copyright (c) [2013-2021] Pivotal Software, Inc.
This product is licensed to you under the Apache License, Version 2.0 (the "License").
@@ -38,5 +38,6 @@ conditions of the subcomponent's license, as noted in the LICENSE file.
@@ -375,7 +375,7 @@ public class ReactiveElasticsearchClientUnitTests {
});
URI uri = hostProvider.when(HOST).captureUri();
assertThat(uri.getRawPath()).isEqualTo("/twitter/_doc/10/_create");
assertThat(uri.getRawPath()).isEqualTo("/twitter/_create/10");
}
@Test // DATAES-488
@@ -439,7 +439,7 @@ public class ReactiveElasticsearchClientUnitTests {
hostProvider.when(HOST) //
.receiveUpdateOk();
client.update(new UpdateRequest("twitter", "doc", "1").doc(Collections.singletonMap("user", "cstrobl"))).then() //
client.update(new UpdateRequest("twitter", "1").doc(Collections.singletonMap("user", "cstrobl"))).then() //
.as(StepVerifier::create) //
.verifyComplete();
@@ -449,7 +449,7 @@ public class ReactiveElasticsearchClientUnitTests {
});
URI uri = hostProvider.when(HOST).captureUri();
assertThat(uri.getRawPath()).isEqualTo("/twitter/doc/1/_update");
assertThat(uri.getRawPath()).isEqualTo("/twitter/_update/1");
}
@Test // DATAES-488
@@ -45,7 +45,9 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.data.annotation.AccessType;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.ReadOnlyProperty;
import org.springframework.data.annotation.Version;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
@@ -2783,6 +2785,7 @@ public abstract class ElasticsearchIntegrationTests implements NewElasticsearchC
assertThat(settings).doesNotContainKey("index.max_result_window");
}
@DisabledIf(value = "newElasticsearchClient", disabledReason = "ES 7.17.6 returns a null storage type that the new client cannot handle")
@Test // DATAES-709
public void shouldIncludeDefaultsOnGetIndexSettings() {
@@ -3718,6 +3721,21 @@ public abstract class ElasticsearchIntegrationTests implements NewElasticsearchC
}
}
@Test // #2230
@DisplayName("should work with readonly id")
void shouldWorkWithReadonlyId() {
ReadonlyIdEntity entity = new ReadonlyIdEntity();
entity.setPart1("foo");
entity.setPart2("bar");
operations.save(entity);
ReadonlyIdEntity readEntity = operations.get(entity.getId(), ReadonlyIdEntity.class);
assertThat(readEntity.getPart1()).isEqualTo(entity.getPart1());
assertThat(readEntity.getPart2()).isEqualTo(entity.getPart2());
}
@Document(indexName = "#{@indexNameProvider.indexName()}")
private static class SampleEntityUUIDKeyed {
@Nullable
@@ -4463,5 +4481,36 @@ public abstract class ElasticsearchIntegrationTests implements NewElasticsearchC
+ '}';
}
}
@Document(indexName = "#{@indexNameProvider.indexName()}-readonly-id")
static class ReadonlyIdEntity {
@Field(type = FieldType.Keyword) private String part1;
@Field(type = FieldType.Keyword) private String part2;
@Id
@ReadOnlyProperty
@AccessType(AccessType.Type.PROPERTY)
public String getId() {
return part1 + '-' + part2;
}
public String getPart1() {
return part1;
}
public void setPart1(String part1) {
this.part1 = part1;
}
public String getPart2() {
return part2;
}
public void setPart2(String part2) {
this.part2 = part2;
}
}
// endregion
}
@@ -49,7 +49,9 @@ import org.skyscreamer.jsonassert.JSONAssert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.data.annotation.AccessType;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.ReadOnlyProperty;
import org.springframework.data.annotation.Version;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
@@ -1156,6 +1158,23 @@ public abstract class ReactiveElasticsearchIntegrationTests {
.verifyComplete();
}
@Test // #2230
@DisplayName("should work with readonly id")
void shouldWorkWithReadonlyId() {
ReadonlyIdEntity entity = new ReadonlyIdEntity();
entity.setPart1("foo");
entity.setPart2("bar");
operations.save(entity).block();
operations.get(entity.getId(), ReadonlyIdEntity.class) //
.as(StepVerifier::create) //
.assertNext(readEntity -> { //
assertThat(readEntity.getPart1()).isEqualTo(entity.getPart1()); //
assertThat(readEntity.getPart2()).isEqualTo(entity.getPart2()); //
}).verifyComplete();
}
// endregion
// region Helper functions
@@ -1489,5 +1508,35 @@ public abstract class ReactiveElasticsearchIntegrationTests {
+ seqNoPrimaryTerm + '}';
}
}
@Document(indexName = "#{@indexNameProvider.indexName()}-readonly-id")
static class ReadonlyIdEntity {
@Field(type = FieldType.Keyword) private String part1;
@Field(type = FieldType.Keyword) private String part2;
@Id
@ReadOnlyProperty
@AccessType(AccessType.Type.PROPERTY)
public String getId() {
return part1 + '-' + part2;
}
public String getPart1() {
return part1;
}
public void setPart1(String part1) {
this.part1 = part1;
}
public String getPart2() {
return part2;
}
public void setPart2(String part2) {
this.part2 = part2;
}
}
// endregion
}
@@ -140,6 +140,18 @@ class RequestFactoryTests {
assertThat(request.upsertRequest()).isNotNull();
}
@Test // #2287
@DisplayName("should create update query when script language is not set")
void shouldCreateUpdateQueryWhenScriptTypeIsSetToNull() {
UpdateQuery updateQuery = UpdateQuery.builder("1") //
.withScript("script").build();
UpdateRequest request = requestFactory.updateRequest(updateQuery, IndexCoordinates.of("index"));
assertThat(request).isNotNull();
}
@Test // DATAES-693
public void shouldReturnSourceWhenRequested() {
// given
@@ -33,7 +33,10 @@ import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.intellij.lang.annotations.Language;
import org.json.JSONException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
@@ -623,7 +626,8 @@ public class MappingElasticsearchConverterUnitTests {
assertThat(target.address).isEqualTo(bigBunsCafe);
}
@Test // DATAES-716
@Test
// DATAES-716
void shouldWriteLocalDate() throws JSONException {
Person person = new Person();
person.setId("4711");
@@ -665,7 +669,8 @@ public class MappingElasticsearchConverterUnitTests {
assertEquals(expected, json, false);
}
@Test // DATAES-716
@Test
// DATAES-716
void shouldReadLocalDate() {
Document document = Document.create();
document.put("id", "4711");
@@ -695,7 +700,8 @@ public class MappingElasticsearchConverterUnitTests {
assertThat(entity.getDates()).hasSize(2).containsExactly(LocalDate.of(2020, 9, 15), LocalDate.of(2019, 5, 1));
}
@Test // DATAES-763
@Test
// DATAES-763
void writeEntityWithMapDataType() {
Notification notification = new Notification();
@@ -712,7 +718,8 @@ public class MappingElasticsearchConverterUnitTests {
assertThat(document).isEqualTo(notificationAsMap);
}
@Test // DATAES-763
@Test
// DATAES-763
void readEntityWithMapDataType() {
Document document = Document.create();
@@ -729,7 +736,8 @@ public class MappingElasticsearchConverterUnitTests {
assertThat(notification.params.get("content")).isNull();
}
@Test // DATAES-795
@Test
// DATAES-795
void readGenericMapWithSimpleTypes() {
Map<String, Object> mapWithSimpleValues = new HashMap<>();
mapWithSimpleValues.put("int", 1);
@@ -743,7 +751,8 @@ public class MappingElasticsearchConverterUnitTests {
assertThat(wrapper.getSchemaLessObject()).isEqualTo(mapWithSimpleValues);
}
@Test // DATAES-797
@Test
// DATAES-797
void readGenericListWithMaps() {
Map<String, Object> simpleMap = new HashMap<>();
simpleMap.put("int", 1);
@@ -761,7 +770,8 @@ public class MappingElasticsearchConverterUnitTests {
assertThat(wrapper.getSchemaLessObject()).isEqualTo(mapWithSimpleList);
}
@Test // DATAES-799
@Test
// DATAES-799
void shouldNotWriteSeqNoPrimaryTermProperty() {
EntityWithSeqNoPrimaryTerm entity = new EntityWithSeqNoPrimaryTerm();
entity.seqNoPrimaryTerm = new SeqNoPrimaryTerm(1L, 2L);
@@ -772,7 +782,8 @@ public class MappingElasticsearchConverterUnitTests {
assertThat(document).doesNotContainKey("seqNoPrimaryTerm");
}
@Test // DATAES-799
@Test
// DATAES-799
void shouldNotReadSeqNoPrimaryTermProperty() {
Document document = Document.create().append("seqNoPrimaryTerm", emptyMap());
@@ -781,7 +792,8 @@ public class MappingElasticsearchConverterUnitTests {
assertThat(entity.seqNoPrimaryTerm).isNull();
}
@Test // DATAES-845
@Test
// DATAES-845
void shouldWriteCollectionsWithNullValues() throws JSONException {
EntityWithListProperty entity = new EntityWithListProperty();
entity.setId("42");
@@ -798,7 +810,8 @@ public class MappingElasticsearchConverterUnitTests {
assertEquals(expected, json, false);
}
@Test // DATAES-857
@Test
// DATAES-857
void shouldWriteEntityWithListOfGeoPoints() throws JSONException {
GeoPointListEntity entity = new GeoPointListEntity();
@@ -827,7 +840,8 @@ public class MappingElasticsearchConverterUnitTests {
assertEquals(expected, json, false);
}
@Test // DATAES-857
@Test
// DATAES-857
void shouldReadEntityWithListOfGeoPoints() {
String json = "{\n" + //
@@ -852,7 +866,8 @@ public class MappingElasticsearchConverterUnitTests {
assertThat(entity.locations).containsExactly(new GeoPoint(12.34, 23.45), new GeoPoint(34.56, 45.67));
}
@Test // DATAES-865
@Test
// DATAES-865
void shouldWriteEntityWithMapAsObject() throws JSONException {
Map<String, Object> map = new LinkedHashMap<>();
@@ -1509,6 +1524,305 @@ public class MappingElasticsearchConverterUnitTests {
mappingElasticsearchConverter.updateQuery(query, EntityWithCustomValueConverters.class);
}
@Test // #2280
@DisplayName("should read a single String into a List property")
void shouldReadASingleStringIntoAListProperty() {
String json = "{\n" + //
" \"stringList\": \"foo\"\n" + //
"}\n"; //
Document source = Document.parse(json);
EntityWithCollections entity = mappingElasticsearchConverter.read(EntityWithCollections.class, source);
assertThat(entity.getStringList()).containsExactly("foo");
}
@Test // #2280
@DisplayName("should read a String array into a List property")
void shouldReadAStringArrayIntoAListProperty() {
String json = "{\n" + //
" \"stringList\": [\"foo\", \"bar\"]\n" + //
"}\n"; //
Document source = Document.parse(json);
EntityWithCollections entity = mappingElasticsearchConverter.read(EntityWithCollections.class, source);
assertThat(entity.getStringList()).containsExactly("foo", "bar");
}
@Test // #2280
@DisplayName("should read a single String into a Set property")
void shouldReadASingleStringIntoASetProperty() {
String json = "{\n" + //
" \"stringSet\": \"foo\"\n" + //
"}\n"; //
Document source = Document.parse(json);
EntityWithCollections entity = mappingElasticsearchConverter.read(EntityWithCollections.class, source);
assertThat(entity.getStringSet()).containsExactly("foo");
}
@Test // #2280
@DisplayName("should read a String array into a Set property")
void shouldReadAStringArrayIntoASetProperty() {
String json = "{\n" + //
" \"stringSet\": [\n" + //
" \"foo\",\n" + //
" \"bar\"\n" + //
" ]\n" + //
"}\n"; //
Document source = Document.parse(json);
EntityWithCollections entity = mappingElasticsearchConverter.read(EntityWithCollections.class, source);
assertThat(entity.getStringSet()).containsExactly("foo", "bar");
}
@Test // #2280
@DisplayName("should read a single object into a List property")
void shouldReadASingleObjectIntoAListProperty() {
String json = "{\n" + //
" \"childrenList\": {\n" + //
" \"name\": \"child\"\n" + //
" }\n" + //
"}\n"; //
Document source = Document.parse(json);
EntityWithCollections entity = mappingElasticsearchConverter.read(EntityWithCollections.class, source);
assertThat(entity.getChildrenList()).hasSize(1);
// noinspection ConstantConditions
assertThat(entity.getChildrenList().get(0).getName()).isEqualTo("child");
}
@Test // #2280
@DisplayName("should read an object array into a List property")
void shouldReadAnObjectArrayIntoAListProperty() {
String json = " {\n" + //
" \"childrenList\": [\n" + //
" {\n" + //
" \"name\": \"child1\"\n" + //
" },\n" + //
" {\n" + //
" \"name\": \"child2\"\n" + //
" }\n" + //
" ]\n" + //
" }\n"; //
Document source = Document.parse(json);
EntityWithCollections entity = mappingElasticsearchConverter.read(EntityWithCollections.class, source);
assertThat(entity.getChildrenList()).hasSize(2);
// noinspection ConstantConditions
assertThat(entity.getChildrenList().get(0).getName()).isEqualTo("child1");
assertThat(entity.getChildrenList().get(1).getName()).isEqualTo("child2");
}
@Test // #2280
@DisplayName("should read a single object into a Set property")
void shouldReadASingleObjectIntoASetProperty() {
String json = "{\n" + //
" \"childrenSet\": {\n" + //
" \"name\": \"child\"\n" + //
" }\n" + //
"}\n"; //
Document source = Document.parse(json);
EntityWithCollections entity = mappingElasticsearchConverter.read(EntityWithCollections.class, source);
assertThat(entity.getChildrenSet()).hasSize(1);
// noinspection ConstantConditions
assertThat(entity.getChildrenSet().iterator().next().getName()).isEqualTo("child");
}
@Test // #2280
@DisplayName("should read an object array into a Set property")
void shouldReadAnObjectArrayIntoASetProperty() {
String json = "{\n" + //
" \"childrenSet\": [\n" + //
" {\n" + //
" \"name\": \"child1\"\n" + //
" },\n" + //
" {\n" + //
" \"name\": \"child2\"\n" + //
" }\n" + //
" ]\n" + //
"}\n"; //
Document source = Document.parse(json);
EntityWithCollections entity = mappingElasticsearchConverter.read(EntityWithCollections.class, source);
assertThat(entity.getChildrenSet()).hasSize(2);
// noinspection ConstantConditions
List<String> names = entity.getChildrenSet().stream().map(EntityWithCollections.Child::getName)
.collect(Collectors.toList());
assertThat(names).containsExactlyInAnyOrder("child1", "child2");
}
@Test // #2280
@DisplayName("should read a single String into a List property immutable")
void shouldReadASingleStringIntoAListPropertyImmutable() {
String json = "{\n" + //
" \"stringList\": \"foo\"\n" + //
"}\n"; //
Document source = Document.parse(json);
ImmutableEntityWithCollections entity = mappingElasticsearchConverter.read(ImmutableEntityWithCollections.class,
source);
assertThat(entity.getStringList()).containsExactly("foo");
}
@Test // #2280
@DisplayName("should read a String array into a List property immutable")
void shouldReadAStringArrayIntoAListPropertyImmutable() {
String json = "{\n" + //
" \"stringList\": [\n" + //
" \"foo\",\n" + //
" \"bar\"\n" + //
" ]\n" + //
"}\n"; //
Document source = Document.parse(json);
ImmutableEntityWithCollections entity = mappingElasticsearchConverter.read(ImmutableEntityWithCollections.class,
source);
assertThat(entity.getStringList()).containsExactly("foo", "bar");
}
@Test // #2280
@DisplayName("should read a single String into a Set property immutable")
void shouldReadASingleStringIntoASetPropertyImmutable() {
String json = "{\n" + //
" \"stringSet\": \"foo\"\n" + //
"}\n"; //
Document source = Document.parse(json);
ImmutableEntityWithCollections entity = mappingElasticsearchConverter.read(ImmutableEntityWithCollections.class,
source);
assertThat(entity.getStringSet()).containsExactly("foo");
}
@Test // #2280
@DisplayName("should read a String array into a Set property immutable")
void shouldReadAStringArrayIntoASetPropertyImmutable() {
String json = "{\n" + //
" \"stringSet\": [\n" + //
" \"foo\",\n" + //
" \"bar\"\n" + //
" ]\n" + //
"}\n"; //
Document source = Document.parse(json);
ImmutableEntityWithCollections entity = mappingElasticsearchConverter.read(ImmutableEntityWithCollections.class,
source);
assertThat(entity.getStringSet()).containsExactly("foo", "bar");
}
@Test // #2280
@DisplayName("should read a single object into a List property immutable")
void shouldReadASingleObjectIntoAListPropertyImmutable() {
String json = "{\n" + //
" \"childrenList\": {\n" + //
" \"name\": \"child\"\n" + //
" }\n" + //
"}\n"; //
Document source = Document.parse(json);
ImmutableEntityWithCollections entity = mappingElasticsearchConverter.read(ImmutableEntityWithCollections.class,
source);
assertThat(entity.getChildrenList()).hasSize(1);
// noinspection ConstantConditions
assertThat(entity.getChildrenList().get(0).getName()).isEqualTo("child");
}
@Test // #2280
@DisplayName("should read an object array into a List property immutable")
void shouldReadAnObjectArrayIntoAListPropertyImmutable() {
String json = "{\n" + //
" \"childrenList\": [\n" + //
" {\n" + //
" \"name\": \"child1\"\n" + //
" },\n" + //
" {\n" + //
" \"name\": \"child2\"\n" + //
" }\n" + //
" ]\n" + //
"}\n"; //
Document source = Document.parse(json);
ImmutableEntityWithCollections entity = mappingElasticsearchConverter.read(ImmutableEntityWithCollections.class,
source);
assertThat(entity.getChildrenList()).hasSize(2);
// noinspection ConstantConditions
assertThat(entity.getChildrenList().get(0).getName()).isEqualTo("child1");
assertThat(entity.getChildrenList().get(1).getName()).isEqualTo("child2");
}
@Test // #2280
@DisplayName("should read a single object into a Set property immutable")
void shouldReadASingleObjectIntoASetPropertyImmutable() {
String json = "{\n" + //
" \"childrenSet\": {\n" + //
" \"name\": \"child\"\n" + //
" }\n" + //
"}\n"; //
Document source = Document.parse(json);
ImmutableEntityWithCollections entity = mappingElasticsearchConverter.read(ImmutableEntityWithCollections.class,
source);
assertThat(entity.getChildrenSet()).hasSize(1);
// noinspection ConstantConditions
assertThat(entity.getChildrenSet().iterator().next().getName()).isEqualTo("child");
}
@Test // #2280
@DisplayName("should read an object array into a Set property immutable")
void shouldReadAnObjectArrayIntoASetPropertyImmutable() {
String json = "{\n" + //
" \"childrenSet\": [\n" + //
" {\n" + //
" \"name\": \"child1\"\n" + //
" },\n" + //
" {\n" + //
" \"name\": \"child2\"\n" + //
" }\n" + //
" ]\n" + //
"}\n"; //
Document source = Document.parse(json);
ImmutableEntityWithCollections entity = mappingElasticsearchConverter.read(ImmutableEntityWithCollections.class,
source);
assertThat(entity.getChildrenSet()).hasSize(2);
// noinspection ConstantConditions
List<String> names = entity.getChildrenSet().stream().map(ImmutableEntityWithCollections.Child::getName)
.collect(Collectors.toList());
assertThat(names).containsExactlyInAnyOrder("child1", "child2");
}
private Map<String, Object> writeToMap(Object source) {
Document sink = Document.create();
@@ -1678,34 +1992,46 @@ public class MappingElasticsearchConverterUnitTests {
@Override
public boolean equals(Object o) {
if (this == o)
if (this == o) {
return true;
if (o == null || getClass() != o.getClass())
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Person person = (Person) o;
if (id != null ? !id.equals(person.id) : person.id != null)
if (id != null ? !id.equals(person.id) : person.id != null) {
return false;
if (name != null ? !name.equals(person.name) : person.name != null)
}
if (name != null ? !name.equals(person.name) : person.name != null) {
return false;
if (firstName != null ? !firstName.equals(person.firstName) : person.firstName != null)
}
if (firstName != null ? !firstName.equals(person.firstName) : person.firstName != null) {
return false;
if (lastName != null ? !lastName.equals(person.lastName) : person.lastName != null)
}
if (lastName != null ? !lastName.equals(person.lastName) : person.lastName != null) {
return false;
if (birthDate != null ? !birthDate.equals(person.birthDate) : person.birthDate != null)
}
if (birthDate != null ? !birthDate.equals(person.birthDate) : person.birthDate != null) {
return false;
if (gender != person.gender)
}
if (gender != person.gender) {
return false;
if (address != null ? !address.equals(person.address) : person.address != null)
}
if (address != null ? !address.equals(person.address) : person.address != null) {
return false;
if (coWorkers != null ? !coWorkers.equals(person.coWorkers) : person.coWorkers != null)
}
if (coWorkers != null ? !coWorkers.equals(person.coWorkers) : person.coWorkers != null) {
return false;
if (inventoryList != null ? !inventoryList.equals(person.inventoryList) : person.inventoryList != null)
}
if (inventoryList != null ? !inventoryList.equals(person.inventoryList) : person.inventoryList != null) {
return false;
}
if (shippingAddresses != null ? !shippingAddresses.equals(person.shippingAddresses)
: person.shippingAddresses != null)
: person.shippingAddresses != null) {
return false;
}
return inventoryMap != null ? inventoryMap.equals(person.inventoryMap) : person.inventoryMap == null;
}
@@ -1792,15 +2118,18 @@ public class MappingElasticsearchConverterUnitTests {
@Override
public boolean equals(Object o) {
if (this == o)
if (this == o) {
return true;
if (o == null || getClass() != o.getClass())
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Gun gun = (Gun) o;
if (shotsPerMagazine != gun.shotsPerMagazine)
if (shotsPerMagazine != gun.shotsPerMagazine) {
return false;
}
return label.equals(gun.label);
}
@@ -1826,10 +2155,12 @@ public class MappingElasticsearchConverterUnitTests {
@Override
public boolean equals(Object o) {
if (this == o)
if (this == o) {
return true;
if (!(o instanceof Grenade))
}
if (!(o instanceof Grenade)) {
return false;
}
Grenade grenade = (Grenade) o;
@@ -1862,17 +2193,21 @@ public class MappingElasticsearchConverterUnitTests {
@Override
public boolean equals(Object o) {
if (this == o)
if (this == o) {
return true;
if (!(o instanceof Rifle))
}
if (!(o instanceof Rifle)) {
return false;
}
Rifle rifle = (Rifle) o;
if (Double.compare(rifle.weight, weight) != 0)
if (Double.compare(rifle.weight, weight) != 0) {
return false;
if (maxShotsPerMagazine != rifle.maxShotsPerMagazine)
}
if (maxShotsPerMagazine != rifle.maxShotsPerMagazine) {
return false;
}
return label.equals(rifle.label);
}
@@ -1903,10 +2238,12 @@ public class MappingElasticsearchConverterUnitTests {
@Override
public boolean equals(Object o) {
if (this == o)
if (this == o) {
return true;
if (!(o instanceof ShotGun))
}
if (!(o instanceof ShotGun)) {
return false;
}
ShotGun shotGun = (ShotGun) o;
@@ -1953,17 +2290,21 @@ public class MappingElasticsearchConverterUnitTests {
@Override
public boolean equals(Object o) {
if (this == o)
if (this == o) {
return true;
if (!(o instanceof Address))
}
if (!(o instanceof Address)) {
return false;
}
Address address = (Address) o;
if (location != null ? !location.equals(address.location) : address.location != null)
if (location != null ? !location.equals(address.location) : address.location != null) {
return false;
if (street != null ? !street.equals(address.street) : address.street != null)
}
if (street != null ? !street.equals(address.street) : address.street != null) {
return false;
}
return city != null ? city.equals(address.city) : address.city == null;
}
@@ -1990,10 +2331,12 @@ public class MappingElasticsearchConverterUnitTests {
@Override
public boolean equals(Object o) {
if (this == o)
if (this == o) {
return true;
if (!(o instanceof Place))
}
if (!(o instanceof Place)) {
return false;
}
Place place = (Place) o;
@@ -2462,6 +2805,128 @@ public class MappingElasticsearchConverterUnitTests {
return reverse(value);
}
}
private static class EntityWithCollections {
@Field(type = FieldType.Keyword)
@Nullable private List<String> stringList;
@Field(type = FieldType.Keyword)
@Nullable private Set<String> stringSet;
@Field(type = FieldType.Object)
@Nullable private List<Child> childrenList;
@Field(type = FieldType.Object)
@Nullable private Set<Child> childrenSet;
@Nullable
public List<String> getStringList() {
return stringList;
}
public void setStringList(@Nullable List<String> stringList) {
this.stringList = stringList;
}
@Nullable
public Set<String> getStringSet() {
return stringSet;
}
public void setStringSet(@Nullable Set<String> stringSet) {
this.stringSet = stringSet;
}
@Nullable
public List<Child> getChildrenList() {
return childrenList;
}
public void setChildrenList(@Nullable List<Child> childrenList) {
this.childrenList = childrenList;
}
@Nullable
public Set<Child> getChildrenSet() {
return childrenSet;
}
public void setChildrenSet(@Nullable Set<Child> childrenSet) {
this.childrenSet = childrenSet;
}
public static class Child {
@Field(type = FieldType.Keyword)
@Nullable private String name;
@Nullable
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
private static final class ImmutableEntityWithCollections {
@Field(type = FieldType.Keyword)
@Nullable private List<String> stringList;
@Field(type = FieldType.Keyword)
@Nullable private Set<String> stringSet;
@Field(type = FieldType.Object)
@Nullable private List<Child> childrenList;
@Field(type = FieldType.Object)
@Nullable private Set<Child> childrenSet;
public ImmutableEntityWithCollections(@Nullable List<String> stringList, @Nullable Set<String> stringSet,
@Nullable List<Child> childrenList, @Nullable Set<Child> childrenSet) {
this.stringList = stringList;
this.stringSet = stringSet;
this.childrenList = childrenList;
this.childrenSet = childrenSet;
}
@Nullable
public List<String> getStringList() {
return stringList;
}
@Nullable
public Set<String> getStringSet() {
return stringSet;
}
@Nullable
public List<Child> getChildrenList() {
return childrenList;
}
@Nullable
public Set<Child> getChildrenSet() {
return childrenSet;
}
public static class Child {
@Field(type = FieldType.Keyword)
@Nullable private String name;
public Child(@Nullable String name) {
this.name = name;
}
@Nullable
public String getName() {
return name;
}
}
}
// endregion
private static String reverse(Object o) {
@@ -241,7 +241,7 @@ abstract class CallbackIntegrationTests {
@Id private String id;
@Nullable private String text;
@ReadOnlyProperty
// @ReadOnlyProperty
@Nullable private String className;
@Nullable
@@ -27,7 +27,6 @@ import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.ReadOnlyProperty;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations;
import org.springframework.data.elasticsearch.core.ReactiveIndexOperations;
@@ -119,7 +118,6 @@ public abstract class ReactiveCallbackIntegrationTests {
@Id private String id;
private String text;
@ReadOnlyProperty
@Nullable private String className;
public SampleEntity(String id, String text) {
@@ -310,6 +310,17 @@ abstract class QueryKeywordsIntegrationTests {
assertThat(searchHits.getTotalHits()).isEqualTo(5);
}
@Test // #2162
@DisplayName("should run exists query")
void shouldRunExistsQuery() {
Boolean existsCaneSugar = repository.existsByText("Cane sugar");
Boolean existsSand = repository.existsByText("Sand");
assertThat(existsCaneSugar).isTrue();
assertThat(existsSand).isFalse();
}
@SuppressWarnings("unused")
@Document(indexName = "#{@indexNameProvider.indexName()}")
static class Product {
@@ -452,6 +463,8 @@ abstract class QueryKeywordsIntegrationTests {
SearchHits<Product> findByNameEmpty();
SearchHits<Product> findByNameNotEmpty();
Boolean existsByText(String text);
}
}
@@ -19,8 +19,11 @@ import static org.assertj.core.api.Assertions.*;
import static org.springframework.data.elasticsearch.annotations.FieldType.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import java.lang.Boolean;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Order;
@@ -121,6 +124,21 @@ public abstract class ReactiveQueryKeywordsIntegrationTests {
}).verifyComplete();
}
@Test // #2162
@DisplayName("should run exists query")
void shouldRunExistsQuery() {
loadEntities();
repository.existsByMessage("message") //
.as(StepVerifier::create) //
.expectNext(true) //
.verifyComplete();
repository.existsByMessage("without") //
.as(StepVerifier::create) //
.expectNext(false) //
.verifyComplete();
}
@SuppressWarnings("SpringDataMethodInconsistencyInspection")
interface SampleRepository extends ReactiveElasticsearchRepository<SampleEntity, String> {
Flux<SearchHit<SampleEntity>> findByMessageExists();
@@ -132,6 +150,8 @@ public abstract class ReactiveQueryKeywordsIntegrationTests {
Flux<SearchHit<SampleEntity>> findByMessageIsNotEmpty();
Flux<SearchHit<SampleEntity>> findByMessageIsEmpty();
Mono<Boolean> existsByMessage(String message);
}
private void loadEntities() {
@@ -15,7 +15,7 @@
#
#
sde.testcontainers.image-name=docker.elastic.co/elasticsearch/elasticsearch
sde.testcontainers.image-version=7.17.4
sde.testcontainers.image-version=7.17.6
#
#
# needed as we do a DELETE /* at the end of the tests, will be required from 8.0 on, produces a warning since 7.13