Compare commits
36 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| de437cd7da | |||
| 5ac83f696e | |||
| 6100c2491a | |||
| d597baccd3 | |||
| dfc1be286c | |||
| 1f7fa77c15 | |||
| 699c0ef265 | |||
| 9771b9c1d6 | |||
| 437279f637 | |||
| ed1c416cd3 | |||
| a5fb7a3c76 | |||
| 7f772703d3 | |||
| 43eb40e45e | |||
| 75bf578b31 | |||
| 675b77982b | |||
| d95af9fcfa | |||
| 96985fa14a | |||
| ff1f25b0b2 | |||
| d3e95815d9 | |||
| 797dbb5a18 | |||
| a7d6b9df6d | |||
| ade90328d3 | |||
| ec77b3a082 | |||
| 63cebd7038 | |||
| e7c9bf20f6 | |||
| b4c3e25a60 | |||
| 43ab49b5fa | |||
| c9b8b1af19 | |||
| 9c80dc9ae8 | |||
| 03ffb07827 | |||
| d29cf7788b | |||
| 71e46c8277 | |||
| fc1e8d3cf6 | |||
| c84a8bbc12 | |||
| 97a9176775 | |||
| 7eff8f5dd1 |
@@ -9,8 +9,7 @@ Make sure that:
|
||||
-->
|
||||
|
||||
- [ ] You have read the [Spring Data contribution guidelines](https://github.com/spring-projects/spring-data-build/blob/master/CONTRIBUTING.adoc).
|
||||
- [ ] **There is a ticket in the bug tracker for the project in our [issue tracker](https://github.
|
||||
com/spring-projects/spring-data-elasticsearch/issues)**. Add the issue number to the _Closes #issue-number_ line below
|
||||
- [ ] **There is a ticket in the bug tracker for the project in our [issue tracker](https://github.com/spring-projects/spring-data-elasticsearch/issues)**. Add the issue number to the _Closes #issue-number_ line below
|
||||
- [ ] You use the code formatters provided [here](https://github.com/spring-projects/spring-data-build/tree/master/etc/ide) and have them applied to your changes. Don’t submit any formatting related changes.
|
||||
- [ ] You submit test cases (unit or integration tests) that back your changes.
|
||||
- [ ] You added yourself as author in the headers of the classes you touched. Amend the date range in the Apache license header if needed. For new types, add the license header (copy from another file and set the current year only).
|
||||
|
||||
@@ -24,4 +24,5 @@ target
|
||||
|
||||
|
||||
/zap.env
|
||||
/localdocker.env
|
||||
.localdocker-env
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
#Mon Jan 30 10:48:19 CET 2023
|
||||
#Thu Apr 06 16:16:37 CEST 2023
|
||||
wrapperUrl=https\://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
|
||||
distributionUrl=https\://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.7/apache-maven-3.8.7-bin.zip
|
||||
distributionUrl=https\://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.1/apache-maven-3.9.1-bin.zip
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
= Spring Data contribution guidelines
|
||||
|
||||
You find the contribution guidelines for Spring Data projects https://github.com/spring-projects/spring-data-build/blob/main/CONTRIBUTING.adoc[here].
|
||||
**Please read these carefully!**
|
||||
|
||||
Do not submit a Pull Request before having created an issue and having discussed it. This prevents you from doing work that might be rejected.
|
||||
|
||||
== Running the test locally
|
||||
|
||||
|
||||
Vendored
+43
-20
@@ -1,7 +1,7 @@
|
||||
def p = [:]
|
||||
node {
|
||||
checkout scm
|
||||
p = readProperties interpolate: true, file: 'ci/pipeline.properties'
|
||||
checkout scm
|
||||
p = readProperties interpolate: true, file: 'ci/pipeline.properties'
|
||||
}
|
||||
|
||||
pipeline {
|
||||
@@ -18,7 +18,7 @@ pipeline {
|
||||
}
|
||||
|
||||
stages {
|
||||
stage("test: baseline (Java 17)") {
|
||||
stage("test: baseline (main)") {
|
||||
when {
|
||||
beforeAgent(true)
|
||||
anyOf {
|
||||
@@ -32,17 +32,42 @@ pipeline {
|
||||
options { timeout(time: 30, unit: 'MINUTES') }
|
||||
|
||||
environment {
|
||||
DOCKER_HUB = credentials("${p['docker.credentials']}")
|
||||
ARTIFACTORY = credentials("${p['artifactory.credentials']}")
|
||||
}
|
||||
|
||||
steps {
|
||||
script {
|
||||
docker.withRegistry(p['docker.registry'], p['docker.credentials']) {
|
||||
docker.image(p['docker.java.main.image']).inside(p['docker.java.inside.docker']) {
|
||||
sh "docker login --username ${DOCKER_HUB_USR} --password ${DOCKER_HUB_PSW}"
|
||||
sh 'PROFILE=none ci/verify.sh'
|
||||
sh "ci/clean.sh"
|
||||
docker.image(p['docker.java.main.image']).inside(p['docker.java.inside.docker']) {
|
||||
sh 'PROFILE=none ci/verify.sh'
|
||||
sh "ci/clean.sh"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage("Test other configurations") {
|
||||
when {
|
||||
beforeAgent(true)
|
||||
allOf {
|
||||
branch(pattern: "main|(\\d\\.\\d\\.x)", comparator: "REGEXP")
|
||||
not { triggeredBy 'UpstreamCause' }
|
||||
}
|
||||
}
|
||||
parallel {
|
||||
stage("test: baseline (next)") {
|
||||
agent {
|
||||
label 'data'
|
||||
}
|
||||
options { timeout(time: 30, unit: 'MINUTES') }
|
||||
environment {
|
||||
ARTIFACTORY = credentials("${p['artifactory.credentials']}")
|
||||
}
|
||||
steps {
|
||||
script {
|
||||
docker.image(p['docker.java.next.image']).inside(p['docker.java.inside.docker']) {
|
||||
sh 'PROFILE=none ci/verify.sh'
|
||||
sh "ci/clean.sh"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -68,17 +93,15 @@ pipeline {
|
||||
|
||||
steps {
|
||||
script {
|
||||
docker.withRegistry(p['docker.registry'], p['docker.credentials']) {
|
||||
docker.image(p['docker.java.main.image']).inside(p['docker.java.inside.basic']) {
|
||||
sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -s settings.xml -Pci,artifactory -Dmaven.repo.local=/tmp/jenkins-home/.m2/spring-data-elasticsearch-non-root ' +
|
||||
'-Dartifactory.server=https://repo.spring.io ' +
|
||||
"-Dartifactory.username=${ARTIFACTORY_USR} " +
|
||||
"-Dartifactory.password=${ARTIFACTORY_PSW} " +
|
||||
"-Dartifactory.staging-repository=libs-snapshot-local " +
|
||||
"-Dartifactory.build-name=spring-data-elasticsearch " +
|
||||
"-Dartifactory.build-number=${BUILD_NUMBER} " +
|
||||
'-Dmaven.test.skip=true clean deploy -U -B'
|
||||
}
|
||||
docker.image(p['docker.java.main.image']).inside(p['docker.java.inside.basic']) {
|
||||
sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -s settings.xml -Pci,artifactory -Dmaven.repo.local=/tmp/jenkins-home/.m2/spring-data-elasticsearch-non-root ' +
|
||||
'-Dartifactory.server=https://repo.spring.io ' +
|
||||
"-Dartifactory.username=${ARTIFACTORY_USR} " +
|
||||
"-Dartifactory.password=${ARTIFACTORY_PSW} " +
|
||||
"-Dartifactory.staging-repository=libs-snapshot-local " +
|
||||
"-Dartifactory.build-name=spring-data-elasticsearch " +
|
||||
"-Dartifactory.build-number=${BUILD_NUMBER} " +
|
||||
'-Dmaven.test.skip=true clean deploy -U -B'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
# Java versions
|
||||
java.main.tag=17.0.6_10-jdk-focal
|
||||
java.next.tag=20-jdk-jammy
|
||||
|
||||
# Docker container images - standard
|
||||
docker.java.main.image=harbor-repo.vmware.com/dockerhub-proxy-cache/library/eclipse-temurin:${java.main.tag}
|
||||
docker.java.next.image=harbor-repo.vmware.com/dockerhub-proxy-cache/library/eclipse-temurin:${java.next.tag}
|
||||
|
||||
# Supported versions of MongoDB
|
||||
docker.mongodb.4.4.version=4.4.18
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-elasticsearch</artifactId>
|
||||
<version>5.1.0-M1</version>
|
||||
<version>5.1.0-RC1</version>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.data.build</groupId>
|
||||
<artifactId>spring-data-parent</artifactId>
|
||||
<version>3.1.0-M1</version>
|
||||
<version>3.1.0-RC1</version>
|
||||
</parent>
|
||||
|
||||
<name>Spring Data Elasticsearch</name>
|
||||
@@ -18,17 +18,17 @@
|
||||
<url>https://github.com/spring-projects/spring-data-elasticsearch</url>
|
||||
|
||||
<properties>
|
||||
<springdata.commons>3.1.0-M1</springdata.commons>
|
||||
<springdata.commons>3.1.0-RC1</springdata.commons>
|
||||
|
||||
<!-- version of the RestHighLevelClient -->
|
||||
<elasticsearch-rhlc>7.17.9</elasticsearch-rhlc>
|
||||
<!-- version of the new ElasticsearchClient -->
|
||||
<elasticsearch-java>8.6.1</elasticsearch-java>
|
||||
<elasticsearch-java>8.7.0</elasticsearch-java>
|
||||
|
||||
<log4j>2.18.0</log4j>
|
||||
<netty>4.1.65.Final</netty>
|
||||
|
||||
<blockhound-junit>1.0.6.RELEASE</blockhound-junit>
|
||||
<blockhound-junit>1.0.7.RELEASE</blockhound-junit>
|
||||
<hoverfly>0.14.3</hoverfly>
|
||||
<jsonassert>1.5.1</jsonassert>
|
||||
<testcontainers>1.17.3</testcontainers>
|
||||
@@ -43,7 +43,6 @@
|
||||
-->
|
||||
<mvn.unit-test.goal>test</mvn.unit-test.goal>
|
||||
<mvn.integration-test-elasticsearch.goal>integration-test</mvn.integration-test-elasticsearch.goal>
|
||||
<mvn.integration-test-opensearch.goal>none</mvn.integration-test-opensearch.goal>
|
||||
</properties>
|
||||
|
||||
<developers>
|
||||
@@ -279,24 +278,6 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!--
|
||||
we don't use lombok in Spring Data Elasticsearch anymore. But the dependency is set in the parent project, and so the
|
||||
lombok compiler stuff is executed regardless of the fact that we don't need it.
|
||||
On AdoptOpenJdk 16.0.0 this leads to an error, so the project does not build.
|
||||
Therefore we replace lombok with a jar - that just contains an empty file - that lives in a local maven repository in
|
||||
src/test/resources/local-maven-repo/
|
||||
It was installed with
|
||||
mvn deploy:deploy-file -DgroupId=org.projectlombok -DartifactId=lombok -Dversion=999999 -Durl=file:./src/test/resources/local-maven-repo/ -DrepositoryId=local-maven-repo -DupdateReleaseInfo=true -Dfile=path/to/empty.jar
|
||||
-->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<!--suppress MavenPackageUpdate -->
|
||||
<version>999999</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.skyscreamer</groupId>
|
||||
<artifactId>jsonassert</artifactId>
|
||||
@@ -419,20 +400,6 @@
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</execution>
|
||||
<!-- execution to run the integration tests against Opensearch -->
|
||||
<execution>
|
||||
<id>integration-test-opensearch</id>
|
||||
<phase>${mvn.integration-test-opensearch.goal}</phase>
|
||||
<goals>
|
||||
<goal>test</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<groups>integration-test</groups>
|
||||
<systemPropertyVariables>
|
||||
<sde.integration-test.environment>opensearch</sde.integration-test.environment>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
|
||||
@@ -37,7 +37,7 @@ built and tested.
|
||||
[cols="^,^,^,^,^",options="header"]
|
||||
|===
|
||||
| Spring Data Release Train | Spring Data Elasticsearch | Elasticsearch | Spring Framework | Spring Boot
|
||||
| 2022.1 | 5.1.x | 8.6.1 | 6.0.x | 3.0.x
|
||||
| 2022.1 | 5.1.x | 8.7.0 | 6.0.x | 3.0.x
|
||||
| 2022.0 (Turing) | 5.0.x | 8.5.3 | 6.0.x | 3.0.x
|
||||
| 2021.2 (Raj) | 4.4.x | 7.17.3 | 5.3.x | 2.7.x
|
||||
| 2021.1 (Q) | 4.3.x | 7.15.2 | 5.3.x | 2.6.x
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
[[new-features.5-1-0]]
|
||||
== New in Spring Data Elasticsearch 5.1
|
||||
|
||||
* Upgrade to Elasticsearch 8.6.1
|
||||
* Upgrade to Elasticsearch 8.7.0
|
||||
|
||||
[[new-features.5-0-0]]
|
||||
== New in Spring Data Elasticsearch 5.0
|
||||
|
||||
@@ -85,6 +85,14 @@ public @interface Document {
|
||||
*/
|
||||
boolean storeIdInSource() default true;
|
||||
|
||||
/**
|
||||
* Specifies if the version property should also be stored in the Elasticsearch document source. Default value is
|
||||
* true.
|
||||
*
|
||||
* @since 5.1
|
||||
*/
|
||||
boolean storeVersionInSource() default true;
|
||||
|
||||
/**
|
||||
* @since 4.3
|
||||
*/
|
||||
|
||||
@@ -210,4 +210,12 @@ public @interface Field {
|
||||
* @since 4.3
|
||||
*/
|
||||
boolean excludeFromSource() default false;
|
||||
|
||||
/**
|
||||
* when this field is a {{@link String}}, a {{@link java.util.Collection}} or a {{@link java.util.Map}} that is empty
|
||||
* this property controlls whether the empty value is sent to Elasticsearch.
|
||||
*
|
||||
* @since 5.1
|
||||
*/
|
||||
boolean storeEmptyValue() default true;
|
||||
}
|
||||
|
||||
@@ -163,11 +163,6 @@ public interface ClientConfiguration {
|
||||
*/
|
||||
Optional<String> getProxy();
|
||||
|
||||
/**
|
||||
* @return the function for configuring a WebClient.
|
||||
*/
|
||||
Function<WebClient, WebClient> getWebClientConfigurer();
|
||||
|
||||
/**
|
||||
* @return the client configuration callbacks
|
||||
* @since 4.3
|
||||
|
||||
+1
-2
@@ -59,7 +59,6 @@ class ClientConfigurationBuilder
|
||||
private @Nullable String password;
|
||||
private @Nullable String pathPrefix;
|
||||
private @Nullable String proxy;
|
||||
private final Function<WebClient, WebClient> webClientConfigurer = Function.identity();
|
||||
private Supplier<HttpHeaders> headersSupplier = HttpHeaders::new;
|
||||
@Deprecated private final HttpClientConfigCallback httpClientConfigurer = httpClientBuilder -> httpClientBuilder;
|
||||
private final List<ClientConfiguration.ClientConfigurationCallback<?>> clientConfigurers = new ArrayList<>();
|
||||
@@ -230,7 +229,7 @@ class ClientConfigurationBuilder
|
||||
}
|
||||
|
||||
return new DefaultClientConfiguration(hosts, headers, useSsl, sslContext, soTimeout, connectTimeout, pathPrefix,
|
||||
hostnameVerifier, proxy, webClientConfigurer, httpClientConfigurer, clientConfigurers, headersSupplier);
|
||||
hostnameVerifier, proxy, httpClientConfigurer, clientConfigurers, headersSupplier);
|
||||
}
|
||||
|
||||
private static InetSocketAddress parse(String hostAndPort) {
|
||||
|
||||
+2
-11
@@ -19,7 +19,6 @@ import java.net.InetSocketAddress;
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
@@ -28,7 +27,6 @@ import javax.net.ssl.SSLContext;
|
||||
import org.elasticsearch.client.RestClientBuilder.HttpClientConfigCallback;
|
||||
import org.springframework.data.elasticsearch.support.HttpHeaders;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
/**
|
||||
* Default {@link ClientConfiguration} implementation.
|
||||
@@ -50,7 +48,6 @@ class DefaultClientConfiguration implements ClientConfiguration {
|
||||
private final @Nullable String pathPrefix;
|
||||
private final @Nullable HostnameVerifier hostnameVerifier;
|
||||
private final @Nullable String proxy;
|
||||
private final Function<WebClient, WebClient> webClientConfigurer;
|
||||
private final HttpClientConfigCallback httpClientConfigurer;
|
||||
private final Supplier<HttpHeaders> headersSupplier;
|
||||
private final List<ClientConfigurationCallback<?>> clientConfigurers;
|
||||
@@ -58,8 +55,8 @@ class DefaultClientConfiguration implements ClientConfiguration {
|
||||
DefaultClientConfiguration(List<InetSocketAddress> hosts, HttpHeaders headers, boolean useSsl,
|
||||
@Nullable SSLContext sslContext, Duration soTimeout, Duration connectTimeout, @Nullable String pathPrefix,
|
||||
@Nullable HostnameVerifier hostnameVerifier, @Nullable String proxy,
|
||||
Function<WebClient, WebClient> webClientConfigurer, HttpClientConfigCallback httpClientConfigurer,
|
||||
List<ClientConfigurationCallback<?>> clientConfigurers, Supplier<HttpHeaders> headersSupplier) {
|
||||
HttpClientConfigCallback httpClientConfigurer, List<ClientConfigurationCallback<?>> clientConfigurers,
|
||||
Supplier<HttpHeaders> headersSupplier) {
|
||||
|
||||
this.hosts = List.copyOf(hosts);
|
||||
this.headers = headers;
|
||||
@@ -70,7 +67,6 @@ class DefaultClientConfiguration implements ClientConfiguration {
|
||||
this.pathPrefix = pathPrefix;
|
||||
this.hostnameVerifier = hostnameVerifier;
|
||||
this.proxy = proxy;
|
||||
this.webClientConfigurer = webClientConfigurer;
|
||||
this.httpClientConfigurer = httpClientConfigurer;
|
||||
this.clientConfigurers = clientConfigurers;
|
||||
this.headersSupplier = headersSupplier;
|
||||
@@ -122,11 +118,6 @@ class DefaultClientConfiguration implements ClientConfiguration {
|
||||
return Optional.ofNullable(proxy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function<WebClient, WebClient> getWebClientConfigurer() {
|
||||
return webClientConfigurer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<ClientConfigurationCallback<?>> getClientConfigurers() {
|
||||
return clientConfigurers;
|
||||
|
||||
+11
-7
@@ -174,8 +174,8 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate {
|
||||
|
||||
Assert.notNull(query, "query must not be null");
|
||||
|
||||
DeleteByQueryRequest request = requestConverter.documentDeleteByQueryRequest(query, clazz, index,
|
||||
getRefreshPolicy());
|
||||
DeleteByQueryRequest request = requestConverter.documentDeleteByQueryRequest(query, routingResolver.getRouting(),
|
||||
clazz, index, getRefreshPolicy());
|
||||
|
||||
DeleteByQueryResponse response = execute(client -> client.deleteByQuery(request));
|
||||
|
||||
@@ -309,7 +309,8 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate {
|
||||
Assert.notNull(query, "query must not be null");
|
||||
Assert.notNull(index, "index must not be null");
|
||||
|
||||
SearchRequest searchRequest = requestConverter.searchRequest(query, clazz, index, true);
|
||||
SearchRequest searchRequest = requestConverter.searchRequest(query, routingResolver.getRouting(), clazz, index,
|
||||
true);
|
||||
|
||||
SearchResponse<EntityAsMap> searchResponse = execute(client -> client.search(searchRequest, EntityAsMap.class));
|
||||
|
||||
@@ -331,7 +332,8 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate {
|
||||
}
|
||||
|
||||
protected <T> SearchHits<T> doSearch(Query query, Class<T> clazz, IndexCoordinates index) {
|
||||
SearchRequest searchRequest = requestConverter.searchRequest(query, clazz, index, false);
|
||||
SearchRequest searchRequest = requestConverter.searchRequest(query, routingResolver.getRouting(), clazz, index,
|
||||
false);
|
||||
SearchResponse<EntityAsMap> searchResponse = execute(client -> client.search(searchRequest, EntityAsMap.class));
|
||||
|
||||
// noinspection DuplicatedCode
|
||||
@@ -343,7 +345,7 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate {
|
||||
}
|
||||
|
||||
protected <T> SearchHits<T> doSearch(SearchTemplateQuery query, Class<T> clazz, IndexCoordinates index) {
|
||||
var searchTemplateRequest = requestConverter.searchTemplate(query, index);
|
||||
var searchTemplateRequest = requestConverter.searchTemplate(query, routingResolver.getRouting(), index);
|
||||
var searchTemplateResponse = execute(client -> client.searchTemplate(searchTemplateRequest, EntityAsMap.class));
|
||||
|
||||
// noinspection DuplicatedCode
|
||||
@@ -374,7 +376,8 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate {
|
||||
Assert.notNull(query, "query must not be null");
|
||||
Assert.notNull(query.getPageable(), "pageable of query must not be null.");
|
||||
|
||||
SearchRequest request = requestConverter.searchRequest(query, clazz, index, false, scrollTimeInMillis);
|
||||
SearchRequest request = requestConverter.searchRequest(query, routingResolver.getRouting(), clazz, index, false,
|
||||
scrollTimeInMillis);
|
||||
SearchResponse<EntityAsMap> response = execute(client -> client.search(request, EntityAsMap.class));
|
||||
|
||||
return getSearchScrollHits(clazz, index, response);
|
||||
@@ -492,7 +495,8 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate {
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private List<SearchHits<?>> doMultiSearch(List<MultiSearchQueryParameter> multiSearchQueryParameters) {
|
||||
|
||||
MsearchRequest request = requestConverter.searchMsearchRequest(multiSearchQueryParameters);
|
||||
MsearchRequest request = requestConverter.searchMsearchRequest(multiSearchQueryParameters,
|
||||
routingResolver.getRouting());
|
||||
|
||||
MsearchResponse<EntityAsMap> msearchResponse = execute(client -> client.msearch(request, EntityAsMap.class));
|
||||
List<MultiSearchResponseItem<EntityAsMap>> responseItems = msearchResponse.responses();
|
||||
|
||||
@@ -50,7 +50,6 @@ public class NativeQuery extends BaseQuery {
|
||||
private final Map<String, Aggregation> aggregations = new LinkedHashMap<>();
|
||||
@Nullable private Suggester suggester;
|
||||
@Nullable private FieldCollapse fieldCollapse;
|
||||
private List<ScriptedField> scriptedFields = Collections.emptyList();
|
||||
private List<SortOptions> sortOptions = Collections.emptyList();
|
||||
|
||||
private Map<String, JsonData> searchExtensions = Collections.emptyMap();
|
||||
@@ -63,7 +62,6 @@ public class NativeQuery extends BaseQuery {
|
||||
this.aggregations.putAll(builder.getAggregations());
|
||||
this.suggester = builder.getSuggester();
|
||||
this.fieldCollapse = builder.getFieldCollapse();
|
||||
this.scriptedFields = builder.getScriptedFields();
|
||||
this.sortOptions = builder.getSortOptions();
|
||||
this.searchExtensions = builder.getSearchExtensions();
|
||||
|
||||
@@ -107,10 +105,6 @@ public class NativeQuery extends BaseQuery {
|
||||
return fieldCollapse;
|
||||
}
|
||||
|
||||
public List<ScriptedField> getScriptedFields() {
|
||||
return scriptedFields;
|
||||
}
|
||||
|
||||
public List<SortOptions> getSortOptions() {
|
||||
return sortOptions;
|
||||
}
|
||||
|
||||
+1
-14
@@ -32,7 +32,6 @@ import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.springframework.data.elasticsearch.core.query.BaseQueryBuilder;
|
||||
import org.springframework.data.elasticsearch.core.query.ScriptedField;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -48,7 +47,6 @@ public class NativeQueryBuilder extends BaseQueryBuilder<NativeQuery, NativeQuer
|
||||
private final Map<String, Aggregation> aggregations = new LinkedHashMap<>();
|
||||
@Nullable private Suggester suggester;
|
||||
@Nullable private FieldCollapse fieldCollapse;
|
||||
private final List<ScriptedField> scriptedFields = new ArrayList<>();
|
||||
private List<SortOptions> sortOptions = new ArrayList<>();
|
||||
private Map<String, JsonData> searchExtensions = new LinkedHashMap<>();
|
||||
|
||||
@@ -81,10 +79,6 @@ public class NativeQueryBuilder extends BaseQueryBuilder<NativeQuery, NativeQuer
|
||||
return fieldCollapse;
|
||||
}
|
||||
|
||||
public List<ScriptedField> getScriptedFields() {
|
||||
return scriptedFields;
|
||||
}
|
||||
|
||||
public List<SortOptions> getSortOptions() {
|
||||
return sortOptions;
|
||||
}
|
||||
@@ -149,17 +143,10 @@ public class NativeQueryBuilder extends BaseQueryBuilder<NativeQuery, NativeQuer
|
||||
return this;
|
||||
}
|
||||
|
||||
public NativeQueryBuilder withScriptedField(ScriptedField scriptedField) {
|
||||
|
||||
Assert.notNull(scriptedField, "scriptedField must not be null");
|
||||
|
||||
this.scriptedFields.add(scriptedField);
|
||||
return this;
|
||||
}
|
||||
|
||||
public NativeQueryBuilder withSort(List<SortOptions> values) {
|
||||
|
||||
Assert.notEmpty(values, "values must not be empty");
|
||||
|
||||
sortOptions.clear();
|
||||
sortOptions.addAll(values);
|
||||
|
||||
|
||||
+14
-10
@@ -111,8 +111,7 @@ public class ReactiveElasticsearchTemplate extends AbstractReactiveElasticsearch
|
||||
return Mono.just(entity) //
|
||||
.zipWith(//
|
||||
Mono.from(execute((ClientCallback<Publisher<IndexResponse>>) client -> client.index(indexRequest))) //
|
||||
.map(indexResponse -> new IndexResponseMetaData(
|
||||
indexResponse.id(), //
|
||||
.map(indexResponse -> new IndexResponseMetaData(indexResponse.id(), //
|
||||
indexResponse.index(), //
|
||||
indexResponse.seqNo(), //
|
||||
indexResponse.primaryTerm(), //
|
||||
@@ -171,8 +170,8 @@ public class ReactiveElasticsearchTemplate extends AbstractReactiveElasticsearch
|
||||
|
||||
Assert.notNull(query, "query must not be null");
|
||||
|
||||
DeleteByQueryRequest request = requestConverter.documentDeleteByQueryRequest(query, entityType, index,
|
||||
getRefreshPolicy());
|
||||
DeleteByQueryRequest request = requestConverter.documentDeleteByQueryRequest(query, routingResolver.getRouting(),
|
||||
entityType, index, getRefreshPolicy());
|
||||
return Mono
|
||||
.from(execute((ClientCallback<Publisher<DeleteByQueryResponse>>) client -> client.deleteByQuery(request)))
|
||||
.map(responseConverter::byQueryResponse);
|
||||
@@ -391,7 +390,8 @@ public class ReactiveElasticsearchTemplate extends AbstractReactiveElasticsearch
|
||||
|
||||
baseQuery.setPointInTime(new Query.PointInTime(psa.getPit(), pitKeepAlive));
|
||||
baseQuery.addSort(Sort.by("_shard_doc"));
|
||||
SearchRequest firstSearchRequest = requestConverter.searchRequest(baseQuery, clazz, index, false, true);
|
||||
SearchRequest firstSearchRequest = requestConverter.searchRequest(baseQuery, routingResolver.getRouting(),
|
||||
clazz, index, false, true);
|
||||
|
||||
return Mono.from(execute((ClientCallback<Publisher<ResponseBody<EntityAsMap>>>) client -> client
|
||||
.search(firstSearchRequest, EntityAsMap.class))).expand(entityAsMapSearchResponse -> {
|
||||
@@ -404,7 +404,8 @@ public class ReactiveElasticsearchTemplate extends AbstractReactiveElasticsearch
|
||||
List<Object> sortOptions = hits.get(hits.size() - 1).sort().stream().map(TypeUtils::toObject)
|
||||
.collect(Collectors.toList());
|
||||
baseQuery.setSearchAfter(sortOptions);
|
||||
SearchRequest followSearchRequest = requestConverter.searchRequest(baseQuery, clazz, index, false, true);
|
||||
SearchRequest followSearchRequest = requestConverter.searchRequest(baseQuery,
|
||||
routingResolver.getRouting(), clazz, index, false, true);
|
||||
return Mono.from(execute((ClientCallback<Publisher<ResponseBody<EntityAsMap>>>) client -> client
|
||||
.search(followSearchRequest, EntityAsMap.class)));
|
||||
});
|
||||
@@ -460,7 +461,8 @@ public class ReactiveElasticsearchTemplate extends AbstractReactiveElasticsearch
|
||||
Assert.notNull(query, "query must not be null");
|
||||
Assert.notNull(index, "index must not be null");
|
||||
|
||||
SearchRequest searchRequest = requestConverter.searchRequest(query, entityType, index, true);
|
||||
SearchRequest searchRequest = requestConverter.searchRequest(query, routingResolver.getRouting(), entityType, index,
|
||||
true);
|
||||
|
||||
return Mono
|
||||
.from(execute((ClientCallback<Publisher<ResponseBody<EntityAsMap>>>) client -> client.search(searchRequest,
|
||||
@@ -470,7 +472,8 @@ public class ReactiveElasticsearchTemplate extends AbstractReactiveElasticsearch
|
||||
|
||||
private Flux<SearchDocument> doFindBounded(Query query, Class<?> clazz, IndexCoordinates index) {
|
||||
|
||||
SearchRequest searchRequest = requestConverter.searchRequest(query, clazz, index, false, false);
|
||||
SearchRequest searchRequest = requestConverter.searchRequest(query, routingResolver.getRouting(), clazz, index,
|
||||
false, false);
|
||||
|
||||
return Mono
|
||||
.from(execute((ClientCallback<Publisher<ResponseBody<EntityAsMap>>>) client -> client.search(searchRequest,
|
||||
@@ -481,7 +484,7 @@ public class ReactiveElasticsearchTemplate extends AbstractReactiveElasticsearch
|
||||
|
||||
private Flux<SearchDocument> doSearch(SearchTemplateQuery query, Class<?> clazz, IndexCoordinates index) {
|
||||
|
||||
var request = requestConverter.searchTemplate(query, index);
|
||||
var request = requestConverter.searchTemplate(query, routingResolver.getRouting(), index);
|
||||
|
||||
return Mono
|
||||
.from(execute((ClientCallback<Publisher<SearchTemplateResponse<EntityAsMap>>>) client -> client
|
||||
@@ -496,7 +499,8 @@ public class ReactiveElasticsearchTemplate extends AbstractReactiveElasticsearch
|
||||
Assert.notNull(query, "query must not be null");
|
||||
Assert.notNull(index, "index must not be null");
|
||||
|
||||
SearchRequest searchRequest = requestConverter.searchRequest(query, clazz, index, false);
|
||||
SearchRequest searchRequest = requestConverter.searchRequest(query, routingResolver.getRouting(), clazz, index,
|
||||
false);
|
||||
|
||||
// noinspection unchecked
|
||||
SearchDocumentCallback<T> callback = new ReadSearchDocumentCallback<>((Class<T>) clazz, index);
|
||||
|
||||
+69
-78
@@ -16,21 +16,10 @@
|
||||
package org.springframework.data.elasticsearch.client.elc;
|
||||
|
||||
import static org.springframework.data.elasticsearch.client.elc.TypeUtils.*;
|
||||
import static org.springframework.util.CollectionUtils.*;
|
||||
import static org.springframework.util.CollectionUtils.isEmpty;
|
||||
|
||||
import co.elastic.clients.elasticsearch._types.Conflicts;
|
||||
import co.elastic.clients.elasticsearch._types.FieldValue;
|
||||
import co.elastic.clients.elasticsearch._types.InlineScript;
|
||||
import co.elastic.clients.elasticsearch._types.OpType;
|
||||
import co.elastic.clients.elasticsearch._types.SortOptions;
|
||||
import co.elastic.clients.elasticsearch._types.SortOrder;
|
||||
import co.elastic.clients.elasticsearch._types.VersionType;
|
||||
import co.elastic.clients.elasticsearch._types.WaitForActiveShardOptions;
|
||||
import co.elastic.clients.elasticsearch._types.mapping.FieldType;
|
||||
import co.elastic.clients.elasticsearch._types.mapping.Property;
|
||||
import co.elastic.clients.elasticsearch._types.mapping.RuntimeField;
|
||||
import co.elastic.clients.elasticsearch._types.mapping.RuntimeFieldType;
|
||||
import co.elastic.clients.elasticsearch._types.mapping.TypeMapping;
|
||||
import co.elastic.clients.elasticsearch._types.*;
|
||||
import co.elastic.clients.elasticsearch._types.mapping.*;
|
||||
import co.elastic.clients.elasticsearch._types.query_dsl.FieldAndFormat;
|
||||
import co.elastic.clients.elasticsearch._types.query_dsl.Like;
|
||||
import co.elastic.clients.elasticsearch.cluster.HealthRequest;
|
||||
@@ -55,15 +44,10 @@ import jakarta.json.stream.JsonParser;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.StringReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -73,9 +57,7 @@ import org.springframework.data.elasticsearch.core.RefreshPolicy;
|
||||
import org.springframework.data.elasticsearch.core.ScriptType;
|
||||
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
||||
import org.springframework.data.elasticsearch.core.document.Document;
|
||||
import org.springframework.data.elasticsearch.core.index.AliasAction;
|
||||
import org.springframework.data.elasticsearch.core.index.AliasActionParameters;
|
||||
import org.springframework.data.elasticsearch.core.index.AliasActions;
|
||||
import org.springframework.data.elasticsearch.core.index.*;
|
||||
import org.springframework.data.elasticsearch.core.index.DeleteTemplateRequest;
|
||||
import org.springframework.data.elasticsearch.core.index.ExistsTemplateRequest;
|
||||
import org.springframework.data.elasticsearch.core.index.GetTemplateRequest;
|
||||
@@ -144,14 +126,12 @@ class RequestConverter {
|
||||
createRequestBuilder.index(indexCoordinates.getIndexName());
|
||||
|
||||
// note: the new client does not support the index.storeType anymore
|
||||
String settingsJson = Document.from(settings).toJson();
|
||||
IndexSettings indexSettings = fromJson(settingsJson, IndexSettings._DESERIALIZER);
|
||||
createRequestBuilder.settings(indexSettings);
|
||||
createRequestBuilder.settings(IndexSettings.of(b -> b //
|
||||
.withJson(new StringReader(Document.from(settings).toJson()))));
|
||||
|
||||
if (mapping != null) {
|
||||
String mappingJson = mapping.toJson();
|
||||
TypeMapping typeMapping = fromJson(mappingJson, TypeMapping._DESERIALIZER);
|
||||
createRequestBuilder.mappings(typeMapping);
|
||||
createRequestBuilder.mappings(TypeMapping.of(b -> b //
|
||||
.withJson(new StringReader(mapping.toJson()))));
|
||||
}
|
||||
|
||||
return createRequestBuilder.build();
|
||||
@@ -243,11 +223,12 @@ class RequestConverter {
|
||||
Assert.notNull(indexCoordinates, "indexCoordinates must not be null");
|
||||
Assert.notNull(mapping, "mapping must not be null");
|
||||
|
||||
PutMappingRequest.Builder builder = new PutMappingRequest.Builder();
|
||||
builder.index(Arrays.asList(indexCoordinates.getIndexNames()));
|
||||
addPropertiesToMapping(builder, mapping);
|
||||
PutMappingRequest request = new PutMappingRequest.Builder() //
|
||||
.withJson(new StringReader(mapping.toJson())) //
|
||||
.index(Arrays.asList(indexCoordinates.getIndexNames())) //
|
||||
.build();
|
||||
|
||||
return builder.build();
|
||||
return request;
|
||||
}
|
||||
|
||||
public GetMappingRequest indicesGetMappingRequest(IndexCoordinates indexCoordinates) {
|
||||
@@ -257,23 +238,6 @@ class RequestConverter {
|
||||
return new GetMappingRequest.Builder().index(Arrays.asList(indexCoordinates.getIndexNames())).build();
|
||||
}
|
||||
|
||||
private void addPropertiesToMapping(PutMappingRequest.Builder builder, Document mapping) {
|
||||
Object properties = mapping.get("properties");
|
||||
|
||||
if (properties != null) {
|
||||
|
||||
if (properties instanceof Map) {
|
||||
Map<String, Property> propertiesMap = new HashMap<>();
|
||||
// noinspection unchecked
|
||||
((Map<String, Object>) properties).forEach((key, value) -> {
|
||||
Property property = getProperty(value);
|
||||
propertiesMap.put(key, property);
|
||||
});
|
||||
builder.properties(propertiesMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Property getProperty(Object value) {
|
||||
// noinspection SpellCheckingInspection
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
@@ -837,8 +801,8 @@ class RequestConverter {
|
||||
});
|
||||
}
|
||||
|
||||
public DeleteByQueryRequest documentDeleteByQueryRequest(Query query, Class<?> clazz, IndexCoordinates index,
|
||||
@Nullable RefreshPolicy refreshPolicy) {
|
||||
public DeleteByQueryRequest documentDeleteByQueryRequest(Query query, @Nullable String routing, Class<?> clazz,
|
||||
IndexCoordinates index, @Nullable RefreshPolicy refreshPolicy) {
|
||||
|
||||
Assert.notNull(query, "query must not be null");
|
||||
Assert.notNull(index, "index must not be null");
|
||||
@@ -857,6 +821,8 @@ class RequestConverter {
|
||||
|
||||
if (query.getRoute() != null) {
|
||||
b.routing(query.getRoute());
|
||||
} else if (StringUtils.hasText(routing)) {
|
||||
b.routing(routing);
|
||||
}
|
||||
|
||||
return b;
|
||||
@@ -998,23 +964,24 @@ class RequestConverter {
|
||||
|
||||
// region search
|
||||
|
||||
public <T> SearchRequest searchRequest(Query query, @Nullable Class<T> clazz, IndexCoordinates indexCoordinates,
|
||||
boolean forCount) {
|
||||
return searchRequest(query, clazz, indexCoordinates, forCount, false, null);
|
||||
public <T> SearchRequest searchRequest(Query query, @Nullable String routing, @Nullable Class<T> clazz,
|
||||
IndexCoordinates indexCoordinates, boolean forCount) {
|
||||
return searchRequest(query, routing, clazz, indexCoordinates, forCount, false, null);
|
||||
}
|
||||
|
||||
public <T> SearchRequest searchRequest(Query query, @Nullable Class<T> clazz, IndexCoordinates indexCoordinates,
|
||||
boolean forCount, long scrollTimeInMillis) {
|
||||
return searchRequest(query, clazz, indexCoordinates, forCount, true, scrollTimeInMillis);
|
||||
public <T> SearchRequest searchRequest(Query query, @Nullable String routing, @Nullable Class<T> clazz,
|
||||
IndexCoordinates indexCoordinates, boolean forCount, long scrollTimeInMillis) {
|
||||
return searchRequest(query, routing, clazz, indexCoordinates, forCount, true, scrollTimeInMillis);
|
||||
}
|
||||
|
||||
public <T> SearchRequest searchRequest(Query query, @Nullable Class<T> clazz, IndexCoordinates indexCoordinates,
|
||||
boolean forCount, boolean forBatchedSearch) {
|
||||
return searchRequest(query, clazz, indexCoordinates, forCount, forBatchedSearch, null);
|
||||
public <T> SearchRequest searchRequest(Query query, @Nullable String routing, @Nullable Class<T> clazz,
|
||||
IndexCoordinates indexCoordinates, boolean forCount, boolean forBatchedSearch) {
|
||||
return searchRequest(query, routing, clazz, indexCoordinates, forCount, forBatchedSearch, null);
|
||||
}
|
||||
|
||||
public <T> SearchRequest searchRequest(Query query, @Nullable Class<T> clazz, IndexCoordinates indexCoordinates,
|
||||
boolean forCount, boolean forBatchedSearch, @Nullable Long scrollTimeInMillis) {
|
||||
public <T> SearchRequest searchRequest(Query query, @Nullable String routing, @Nullable Class<T> clazz,
|
||||
IndexCoordinates indexCoordinates, boolean forCount, boolean forBatchedSearch,
|
||||
@Nullable Long scrollTimeInMillis) {
|
||||
|
||||
String[] indexNames = indexCoordinates.getIndexNames();
|
||||
Assert.notNull(query, "query must not be null");
|
||||
@@ -1022,7 +989,7 @@ class RequestConverter {
|
||||
|
||||
elasticsearchConverter.updateQuery(query, clazz);
|
||||
SearchRequest.Builder builder = new SearchRequest.Builder();
|
||||
prepareSearchRequest(query, clazz, indexCoordinates, builder, forCount, forBatchedSearch);
|
||||
prepareSearchRequest(query, routing, clazz, indexCoordinates, builder, forCount, forBatchedSearch);
|
||||
|
||||
if (scrollTimeInMillis != null) {
|
||||
builder.scroll(t -> t.time(scrollTimeInMillis + "ms"));
|
||||
@@ -1030,13 +997,20 @@ class RequestConverter {
|
||||
|
||||
builder.query(getQuery(query, clazz));
|
||||
|
||||
if (StringUtils.hasText(query.getRoute())) {
|
||||
builder.routing(query.getRoute());
|
||||
}
|
||||
if (StringUtils.hasText(routing)) {
|
||||
builder.routing(routing);
|
||||
}
|
||||
|
||||
addFilter(query, builder);
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public MsearchRequest searchMsearchRequest(
|
||||
List<ElasticsearchTemplate.MultiSearchQueryParameter> multiSearchQueryParameters) {
|
||||
List<ElasticsearchTemplate.MultiSearchQueryParameter> multiSearchQueryParameters, @Nullable String routing) {
|
||||
|
||||
// basically the same stuff as in prepareSearchRequest, but the new Elasticsearch has different builders for a
|
||||
// normal search and msearch
|
||||
@@ -1049,11 +1023,16 @@ class RequestConverter {
|
||||
.header(h -> {
|
||||
h //
|
||||
.index(Arrays.asList(param.index().getIndexNames())) //
|
||||
.routing(query.getRoute()) //
|
||||
.searchType(searchType(query.getSearchType())) //
|
||||
.requestCache(query.getRequestCache()) //
|
||||
;
|
||||
|
||||
if (StringUtils.hasText(query.getRoute())) {
|
||||
h.routing(query.getRoute());
|
||||
} else if (StringUtils.hasText(routing)) {
|
||||
h.routing(routing);
|
||||
}
|
||||
|
||||
if (query.getPreference() != null) {
|
||||
h.preference(query.getPreference());
|
||||
}
|
||||
@@ -1142,6 +1121,9 @@ class RequestConverter {
|
||||
bb.indicesBoost(boosts);
|
||||
}
|
||||
|
||||
query.getScriptedFields().forEach(scriptedField -> bb.scriptFields(scriptedField.getFieldName(),
|
||||
sf -> sf.script(getScript(scriptedField.getScriptData()))));
|
||||
|
||||
if (query instanceof NativeQuery) {
|
||||
prepareNativeSearch((NativeQuery) query, bb);
|
||||
}
|
||||
@@ -1156,8 +1138,8 @@ class RequestConverter {
|
||||
});
|
||||
}
|
||||
|
||||
private <T> void prepareSearchRequest(Query query, @Nullable Class<T> clazz, IndexCoordinates indexCoordinates,
|
||||
SearchRequest.Builder builder, boolean forCount, boolean forBatchedSearch) {
|
||||
private <T> void prepareSearchRequest(Query query, @Nullable String routing, @Nullable Class<T> clazz,
|
||||
IndexCoordinates indexCoordinates, SearchRequest.Builder builder, boolean forCount, boolean forBatchedSearch) {
|
||||
|
||||
String[] indexNames = indexCoordinates.getIndexNames();
|
||||
|
||||
@@ -1190,6 +1172,8 @@ class RequestConverter {
|
||||
|
||||
if (query.getRoute() != null) {
|
||||
builder.routing(query.getRoute());
|
||||
} else if (StringUtils.hasText(routing)) {
|
||||
builder.routing(routing);
|
||||
}
|
||||
|
||||
if (query.getPreference() != null) {
|
||||
@@ -1242,6 +1226,9 @@ class RequestConverter {
|
||||
|
||||
addHighlight(query, builder);
|
||||
|
||||
query.getScriptedFields().forEach(scriptedField -> builder.scriptFields(scriptedField.getFieldName(),
|
||||
sf -> sf.script(getScript(scriptedField.getScriptData()))));
|
||||
|
||||
if (query instanceof NativeQuery) {
|
||||
prepareNativeSearch((NativeQuery) query, builder);
|
||||
}
|
||||
@@ -1407,14 +1394,15 @@ class RequestConverter {
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
private void prepareNativeSearch(NativeQuery query, SearchRequest.Builder builder) {
|
||||
|
||||
query.getScriptedFields().forEach(scriptedField -> builder.scriptFields(scriptedField.getFieldName(),
|
||||
sf -> sf.script(getScript(scriptedField.getScriptData()))));
|
||||
|
||||
builder //
|
||||
.suggest(query.getSuggester()) //
|
||||
.collapse(query.getFieldCollapse()) //
|
||||
.sort(query.getSortOptions()) //
|
||||
.knn(query.getKnnQuery());
|
||||
;
|
||||
|
||||
if (query.getKnnQuery() != null) {
|
||||
builder.knn(query.getKnnQuery());
|
||||
}
|
||||
|
||||
if (!isEmpty(query.getAggregations())) {
|
||||
builder.aggregations(query.getAggregations());
|
||||
@@ -1428,9 +1416,6 @@ class RequestConverter {
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
private void prepareNativeSearch(NativeQuery query, MultisearchBody.Builder builder) {
|
||||
|
||||
query.getScriptedFields().forEach(scriptedField -> builder.scriptFields(scriptedField.getFieldName(),
|
||||
sf -> sf.script(getScript(scriptedField.getScriptData()))));
|
||||
|
||||
builder //
|
||||
.suggest(query.getSuggester()) //
|
||||
.collapse(query.getFieldCollapse()) //
|
||||
@@ -1559,7 +1544,8 @@ class RequestConverter {
|
||||
return ClosePointInTimeRequest.of(cpit -> cpit.id(pit));
|
||||
}
|
||||
|
||||
public SearchTemplateRequest searchTemplate(SearchTemplateQuery query, IndexCoordinates index) {
|
||||
public SearchTemplateRequest searchTemplate(SearchTemplateQuery query, @Nullable String routing,
|
||||
IndexCoordinates index) {
|
||||
|
||||
Assert.notNull(query, "query must not be null");
|
||||
|
||||
@@ -1570,10 +1556,15 @@ class RequestConverter {
|
||||
.id(query.getId()) //
|
||||
.index(Arrays.asList(index.getIndexNames())) //
|
||||
.preference(query.getPreference()) //
|
||||
.routing(query.getRoute()) //
|
||||
.searchType(searchType(query.getSearchType())).source(query.getSource()) //
|
||||
;
|
||||
|
||||
if (query.getRoute() != null) {
|
||||
builder.routing(query.getRoute());
|
||||
} else if (StringUtils.hasText(routing)) {
|
||||
builder.routing(routing);
|
||||
}
|
||||
|
||||
var expandWildcards = query.getExpandWildcards();
|
||||
if (!expandWildcards.isEmpty()) {
|
||||
builder.expandWildcards(expandWildcards(expandWildcards));
|
||||
|
||||
+10
-8
@@ -261,7 +261,8 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate {
|
||||
|
||||
@Override
|
||||
public ByQueryResponse delete(Query query, Class<?> clazz, IndexCoordinates index) {
|
||||
DeleteByQueryRequest deleteByQueryRequest = requestFactory.deleteByQueryRequest(query, clazz, index);
|
||||
DeleteByQueryRequest deleteByQueryRequest = requestFactory.deleteByQueryRequest(query, routingResolver.getRouting(),
|
||||
clazz, index);
|
||||
return ResponseConverter
|
||||
.byQueryResponseOf(execute(client -> client.deleteByQuery(deleteByQueryRequest, RequestOptions.DEFAULT)));
|
||||
}
|
||||
@@ -398,7 +399,7 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate {
|
||||
|
||||
final Boolean trackTotalHits = query.getTrackTotalHits();
|
||||
query.setTrackTotalHits(true);
|
||||
SearchRequest searchRequest = requestFactory.searchRequest(query, clazz, index);
|
||||
SearchRequest searchRequest = requestFactory.searchRequest(query, routingResolver.getRouting(), clazz, index);
|
||||
query.setTrackTotalHits(trackTotalHits);
|
||||
|
||||
searchRequest.source().size(0);
|
||||
@@ -409,7 +410,7 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate {
|
||||
|
||||
@Override
|
||||
public <T> SearchHits<T> search(Query query, Class<T> clazz, IndexCoordinates index) {
|
||||
SearchRequest searchRequest = requestFactory.searchRequest(query, clazz, index);
|
||||
SearchRequest searchRequest = requestFactory.searchRequest(query, routingResolver.getRouting(), clazz, index);
|
||||
SearchResponse response = execute(client -> client.search(searchRequest, RequestOptions.DEFAULT));
|
||||
|
||||
ReadDocumentCallback<T> documentCallback = new ReadDocumentCallback<>(elasticsearchConverter, clazz, index);
|
||||
@@ -431,7 +432,7 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate {
|
||||
|
||||
Assert.notNull(query.getPageable(), "pageable of query must not be null.");
|
||||
|
||||
SearchRequest searchRequest = requestFactory.searchRequest(query, clazz, index);
|
||||
SearchRequest searchRequest = requestFactory.searchRequest(query, routingResolver.getRouting(), clazz, index);
|
||||
searchRequest.scroll(TimeValue.timeValueMillis(scrollTimeInMillis));
|
||||
|
||||
SearchResponse response = execute(client -> client.search(searchRequest, RequestOptions.DEFAULT));
|
||||
@@ -477,7 +478,7 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate {
|
||||
public <T> List<SearchHits<T>> multiSearch(List<? extends Query> queries, Class<T> clazz, IndexCoordinates index) {
|
||||
MultiSearchRequest request = new MultiSearchRequest();
|
||||
for (Query query : queries) {
|
||||
request.add(requestFactory.searchRequest(query, clazz, index));
|
||||
request.add(requestFactory.searchRequest(query, routingResolver.getRouting(), clazz, index));
|
||||
}
|
||||
|
||||
MultiSearchResponse.Item[] items = getMultiSearchResult(request);
|
||||
@@ -504,7 +505,8 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate {
|
||||
Iterator<Class<?>> it = classes.iterator();
|
||||
for (Query query : queries) {
|
||||
Class<?> clazz = it.next();
|
||||
request.add(requestFactory.searchRequest(query, clazz, getIndexCoordinatesFor(clazz)));
|
||||
request
|
||||
.add(requestFactory.searchRequest(query, routingResolver.getRouting(), clazz, getIndexCoordinatesFor(clazz)));
|
||||
}
|
||||
|
||||
MultiSearchResponse.Item[] items = getMultiSearchResult(request);
|
||||
@@ -538,7 +540,7 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate {
|
||||
MultiSearchRequest request = new MultiSearchRequest();
|
||||
Iterator<Class<?>> it = classes.iterator();
|
||||
for (Query query : queries) {
|
||||
request.add(requestFactory.searchRequest(query, it.next(), index));
|
||||
request.add(requestFactory.searchRequest(query, routingResolver.getRouting(), it.next(), index));
|
||||
}
|
||||
|
||||
MultiSearchResponse.Item[] items = getMultiSearchResult(request);
|
||||
@@ -572,7 +574,7 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate {
|
||||
Iterator<Class<?>> it = classes.iterator();
|
||||
Iterator<IndexCoordinates> indexesIt = indexes.iterator();
|
||||
for (Query query : queries) {
|
||||
request.add(requestFactory.searchRequest(query, it.next(), indexesIt.next()));
|
||||
request.add(requestFactory.searchRequest(query, routingResolver.getRouting(), it.next(), indexesIt.next()));
|
||||
}
|
||||
|
||||
MultiSearchResponse.Item[] items = getMultiSearchResult(request);
|
||||
|
||||
+6
-5
@@ -374,7 +374,8 @@ public class ReactiveElasticsearchTemplate extends AbstractReactiveElasticsearch
|
||||
protected Mono<BulkByScrollResponse> doDeleteBy(Query query, Class<?> entityType, IndexCoordinates index) {
|
||||
|
||||
return Mono.defer(() -> {
|
||||
DeleteByQueryRequest request = requestFactory.deleteByQueryRequest(query, entityType, index);
|
||||
DeleteByQueryRequest request = requestFactory.deleteByQueryRequest(query, routingResolver.getRouting(),
|
||||
entityType, index);
|
||||
return doDeleteBy(prepareDeleteByRequest(request));
|
||||
});
|
||||
}
|
||||
@@ -505,7 +506,7 @@ public class ReactiveElasticsearchTemplate extends AbstractReactiveElasticsearch
|
||||
|
||||
return Flux.defer(() -> {
|
||||
|
||||
SearchRequest request = requestFactory.searchRequest(query, clazz, index);
|
||||
SearchRequest request = requestFactory.searchRequest(query, routingResolver.getRouting(), clazz, index);
|
||||
boolean useScroll = !(query.getPageable().isPaged() || query.isLimiting());
|
||||
request = prepareSearchRequest(request, useScroll);
|
||||
|
||||
@@ -520,7 +521,7 @@ public class ReactiveElasticsearchTemplate extends AbstractReactiveElasticsearch
|
||||
protected <T> Mono<SearchDocumentResponse> doFindForResponse(Query query, Class<?> clazz, IndexCoordinates index) {
|
||||
|
||||
return Mono.defer(() -> {
|
||||
SearchRequest request = requestFactory.searchRequest(query, clazz, index);
|
||||
SearchRequest request = requestFactory.searchRequest(query, routingResolver.getRouting(), clazz, index);
|
||||
request = prepareSearchRequest(request, false);
|
||||
|
||||
SearchDocumentCallback<?> documentCallback = new ReadSearchDocumentCallback<>(clazz, index);
|
||||
@@ -540,7 +541,7 @@ public class ReactiveElasticsearchTemplate extends AbstractReactiveElasticsearch
|
||||
Assert.notNull(index, "index must not be null");
|
||||
|
||||
return Flux.defer(() -> {
|
||||
SearchRequest request = requestFactory.searchRequest(query, entityType, index);
|
||||
SearchRequest request = requestFactory.searchRequest(query, routingResolver.getRouting(), entityType, index);
|
||||
request = prepareSearchRequest(request, false);
|
||||
return doAggregate(request);
|
||||
});
|
||||
@@ -565,7 +566,7 @@ public class ReactiveElasticsearchTemplate extends AbstractReactiveElasticsearch
|
||||
protected Mono<Long> doCount(Query query, Class<?> entityType, IndexCoordinates index) {
|
||||
return Mono.defer(() -> {
|
||||
|
||||
SearchRequest request = requestFactory.searchRequest(query, entityType, index);
|
||||
SearchRequest request = requestFactory.searchRequest(query, routingResolver.getRouting(), entityType, index);
|
||||
request = prepareSearchRequest(request, false);
|
||||
return doCount(request);
|
||||
});
|
||||
|
||||
+9
-5
@@ -525,8 +525,8 @@ class RequestFactory {
|
||||
// endregion
|
||||
|
||||
// region delete
|
||||
public DeleteByQueryRequest deleteByQueryRequest(Query query, Class<?> clazz, IndexCoordinates index) {
|
||||
SearchRequest searchRequest = searchRequest(query, clazz, index);
|
||||
public DeleteByQueryRequest deleteByQueryRequest(Query query, @Nullable String routing, Class<?> clazz, IndexCoordinates index) {
|
||||
SearchRequest searchRequest = searchRequest(query, routing, clazz, index);
|
||||
DeleteByQueryRequest deleteByQueryRequest = new DeleteByQueryRequest(index.getIndexNames()) //
|
||||
.setQuery(searchRequest.source().query()) //
|
||||
.setAbortOnVersionConflict(false) //
|
||||
@@ -544,6 +544,8 @@ class RequestFactory {
|
||||
|
||||
if (query.getRoute() != null) {
|
||||
deleteByQueryRequest.setRouting(query.getRoute());
|
||||
} else if (StringUtils.hasText(routing)) {
|
||||
deleteByQueryRequest.setRouting(routing);
|
||||
}
|
||||
|
||||
return deleteByQueryRequest;
|
||||
@@ -751,10 +753,10 @@ class RequestFactory {
|
||||
return searchRequest;
|
||||
}
|
||||
|
||||
public SearchRequest searchRequest(Query query, @Nullable Class<?> clazz, IndexCoordinates index) {
|
||||
public SearchRequest searchRequest(Query query, @Nullable String routing, @Nullable Class<?> clazz, IndexCoordinates index) {
|
||||
|
||||
elasticsearchConverter.updateQuery(query, clazz);
|
||||
SearchRequest searchRequest = prepareSearchRequest(query, clazz, index);
|
||||
SearchRequest searchRequest = prepareSearchRequest(query, routing,clazz, index);
|
||||
QueryBuilder elasticsearchQuery = getQuery(query);
|
||||
QueryBuilder elasticsearchFilter = getFilter(query);
|
||||
|
||||
@@ -768,7 +770,7 @@ class RequestFactory {
|
||||
|
||||
}
|
||||
|
||||
private SearchRequest prepareSearchRequest(Query query, @Nullable Class<?> clazz, IndexCoordinates indexCoordinates) {
|
||||
private SearchRequest prepareSearchRequest(Query query, @Nullable String routing, @Nullable Class<?> clazz, IndexCoordinates indexCoordinates) {
|
||||
|
||||
String[] indexNames = indexCoordinates.getIndexNames();
|
||||
Assert.notNull(indexNames, "No index defined for Query");
|
||||
@@ -843,6 +845,8 @@ class RequestFactory {
|
||||
|
||||
if (StringUtils.hasLength(query.getRoute())) {
|
||||
request.routing(query.getRoute());
|
||||
} else if (StringUtils.hasText(routing)) {
|
||||
request.routing(routing);
|
||||
}
|
||||
|
||||
Duration timeout = query.getTimeout();
|
||||
|
||||
+1
-1
@@ -66,7 +66,7 @@ import org.springframework.util.StringUtils;
|
||||
/**
|
||||
* This class contains methods that are common to different implementations of the {@link ElasticsearchOperations}
|
||||
* interface that use different clients, like RestHighLevelClient and the next Java client from Elasticsearch or some
|
||||
* future implementation that might use an Opensearch client. This class must not contain imports or use classes that
|
||||
* external implementation that might use a different client. This class must not contain imports or use classes that
|
||||
* are specific to one of these implementations.
|
||||
* <p>
|
||||
* <strong>Note:</strong> Although this class is public, it is not considered to be part of the official Spring Data
|
||||
|
||||
+59
@@ -17,13 +17,17 @@ package org.springframework.data.elasticsearch.core;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.core.publisher.Sinks;
|
||||
import reactor.util.function.Tuple2;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.reactivestreams.Subscriber;
|
||||
import org.reactivestreams.Subscription;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
@@ -207,6 +211,61 @@ abstract public class AbstractReactiveElasticsearchTemplate
|
||||
return save(entity, getIndexCoordinatesFor(entity.getClass()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Flux<T> save(Flux<T> entities, Class<?> clazz, int bulkSize) {
|
||||
return save(entities, getIndexCoordinatesFor(clazz), bulkSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Flux<T> save(Flux<T> entities, IndexCoordinates index, int bulkSize) {
|
||||
|
||||
Assert.notNull(entities, "entities must not be null");
|
||||
Assert.notNull(index, "index must not be null");
|
||||
Assert.isTrue(bulkSize > 0, "bulkSize must be greater than 0");
|
||||
|
||||
return Flux.defer(() -> {
|
||||
Sinks.Many<T> sink = Sinks.many().unicast().onBackpressureBuffer();
|
||||
entities //
|
||||
.bufferTimeout(bulkSize, Duration.ofMillis(200)) //
|
||||
.subscribe(new Subscriber<List<T>>() {
|
||||
private Subscription subscription;
|
||||
private AtomicBoolean upstreamComplete = new AtomicBoolean(false);
|
||||
|
||||
@Override
|
||||
public void onSubscribe(Subscription subscription) {
|
||||
this.subscription = subscription;
|
||||
subscription.request(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNext(List<T> entityList) {
|
||||
saveAll(entityList, index) //
|
||||
.map(sink::tryEmitNext) //
|
||||
.doOnComplete(() -> {
|
||||
if (!upstreamComplete.get()) {
|
||||
subscription.request(1);
|
||||
} else {
|
||||
sink.tryEmitComplete();
|
||||
}
|
||||
}).subscribe();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable throwable) {
|
||||
subscription.cancel();
|
||||
sink.tryEmitError(throwable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete() {
|
||||
upstreamComplete.set(true);
|
||||
}
|
||||
});
|
||||
return sink.asFlux();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Flux<T> saveAll(Mono<? extends Collection<? extends T>> entities, Class<T> clazz) {
|
||||
return saveAll(entities, getIndexCoordinatesFor(clazz));
|
||||
|
||||
+58
@@ -44,6 +44,9 @@ import org.springframework.util.Assert;
|
||||
* @since 4.0
|
||||
*/
|
||||
public interface ReactiveDocumentOperations {
|
||||
|
||||
int FLUX_SAVE_BULK_SIZE = 500;
|
||||
|
||||
/**
|
||||
* Index the given entity, once available, extracting index from entity metadata.
|
||||
*
|
||||
@@ -93,6 +96,61 @@ public interface ReactiveDocumentOperations {
|
||||
*/
|
||||
<T> Mono<T> save(T entity, IndexCoordinates index);
|
||||
|
||||
/**
|
||||
* Indexes the entities into the index extracted from entity metadata.
|
||||
*
|
||||
* @param entities
|
||||
* @param clazz the class to get the index name from
|
||||
* @param <T> entity type
|
||||
* @return a Flux emitting the saved entities
|
||||
* @since 5.1
|
||||
*/
|
||||
default <T> Flux<T> save(Flux<T> entities, Class<?> clazz) {
|
||||
return save(entities, clazz, FLUX_SAVE_BULK_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indexes the entities into the index extracted from entity metadata. The entities are collected into batches of
|
||||
* {bulkSize} with a maximal timeout of 200 ms, see
|
||||
* {@link reactor.core.publisher.Flux#bufferTimeout(int, java.time .Duration)} and then sent in a bulk operation to
|
||||
* Elasticsearch.
|
||||
*
|
||||
* @param entities
|
||||
* @param clazz the class to get the index name from
|
||||
* @param bulkSize number of entities to put in a bulk request
|
||||
* @param <T> entity type
|
||||
* @return a Flux emitting the saved entities
|
||||
* @since 5.1
|
||||
*/
|
||||
<T> Flux<T> save(Flux<T> entities, Class<?> clazz, int bulkSize);
|
||||
|
||||
/**
|
||||
* Indexes the entities into the given index.
|
||||
*
|
||||
* @param entities the entities to save
|
||||
* @param index the index to save to
|
||||
* @param <T> entity type
|
||||
* @return a Flux emitting the saved entities
|
||||
* @since 5.1
|
||||
*/
|
||||
default <T> Flux<T> save(Flux<T> entities, IndexCoordinates index) {
|
||||
return save(entities, index, FLUX_SAVE_BULK_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indexes the entities into the given index. The entities are collected into batches of {bulkSize} with a maximal
|
||||
* timeout of 200 ms, see {@link reactor.core.publisher.Flux#bufferTimeout(int, java.time * .Duration)} and then sent
|
||||
* in a bulk operation to Elasticsearch.
|
||||
*
|
||||
* @param entities the entities to save
|
||||
* @param index the index to save to
|
||||
* @param bulkSize number of entities to put in a bulk request
|
||||
* @param <T> entity type
|
||||
* @return a Flux emitting the saved entities
|
||||
* @since 5.1
|
||||
*/
|
||||
<T> Flux<T> save(Flux<T> entities, IndexCoordinates index, int bulkSize);
|
||||
|
||||
/**
|
||||
* Index entities the index extracted from entity metadata.
|
||||
*
|
||||
|
||||
@@ -45,6 +45,7 @@ import org.springframework.util.Assert;
|
||||
* @author Roman Puchkovskiy
|
||||
* @author Matt Gilene
|
||||
* @author Sascha Woo
|
||||
* @author Jakob Hoeper
|
||||
* @since 4.0
|
||||
*/
|
||||
public class SearchHitMapping<T> {
|
||||
@@ -199,9 +200,10 @@ public class SearchHitMapping<T> {
|
||||
}
|
||||
|
||||
try {
|
||||
ElasticsearchPersistentEntity<?> persistentEntityForType = mappingContext.getPersistentEntity(type);
|
||||
NestedMetaData nestedMetaData = searchHits.getSearchHit(0).getContent().getNestedMetaData();
|
||||
ElasticsearchPersistentEntityWithNestedMetaData persistentEntityWithNestedMetaData = getPersistentEntity(
|
||||
mappingContext.getPersistentEntity(type), nestedMetaData);
|
||||
persistentEntityForType, nestedMetaData);
|
||||
|
||||
if (persistentEntityWithNestedMetaData.entity != null) {
|
||||
List<SearchHit<Object>> convertedSearchHits = new ArrayList<>();
|
||||
@@ -219,7 +221,8 @@ public class SearchHitMapping<T> {
|
||||
searchDocument.getSortValues(), //
|
||||
searchDocument.getHighlightFields(), //
|
||||
searchHit.getInnerHits(), //
|
||||
persistentEntityWithNestedMetaData.nestedMetaData, //
|
||||
getPersistentEntity(persistentEntityForType, //
|
||||
searchHit.getContent().getNestedMetaData()).nestedMetaData, //
|
||||
searchHit.getExplanation(), //
|
||||
searchHit.getMatchedQueries(), //
|
||||
targetObject));
|
||||
|
||||
+17
-2
@@ -941,7 +941,8 @@ public class MappingElasticsearchConverter
|
||||
|
||||
if (!property.isWritable() //
|
||||
|| property.isIndexedIndexNameProperty() //
|
||||
|| (property.isIdProperty() && !entity.storeIdInSource())) {
|
||||
|| (property.isIdProperty() && !entity.storeIdInSource()) //
|
||||
|| (property.isVersionProperty() && !entity.storeVersionInSource())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -960,6 +961,10 @@ public class MappingElasticsearchConverter
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!property.storeEmptyValue() && hasEmptyValue(value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (property.hasPropertyValueConverter()) {
|
||||
value = propertyConverterWrite(property, value);
|
||||
sink.set(property, value);
|
||||
@@ -988,6 +993,16 @@ public class MappingElasticsearchConverter
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasEmptyValue(Object value) {
|
||||
|
||||
if (value instanceof String s && s.isEmpty() || value instanceof Collection<?> c && c.isEmpty()
|
||||
|| value instanceof Map<?, ?> m && m.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void writeProperty(ElasticsearchPersistentProperty property, Object value, MapValueAccessor sink) {
|
||||
|
||||
@@ -1404,7 +1419,7 @@ public class MappingElasticsearchConverter
|
||||
|
||||
}
|
||||
|
||||
if (!fieldName.contains(".")) {
|
||||
if (property.hasExplicitFieldName() || !fieldName.contains(".")) {
|
||||
return target.get(fieldName);
|
||||
}
|
||||
|
||||
|
||||
+6
@@ -181,4 +181,10 @@ public interface ElasticsearchPersistentEntity<T> extends PersistentEntity<T, El
|
||||
* @since 5.1
|
||||
*/
|
||||
boolean storeIdInSource();
|
||||
|
||||
/**
|
||||
* @return the storeVersionInSource value from the document annotation.
|
||||
* @since 5.1
|
||||
*/
|
||||
boolean storeVersionInSource();
|
||||
}
|
||||
|
||||
+14
-1
@@ -39,6 +39,12 @@ public interface ElasticsearchPersistentProperty extends PersistentProperty<Elas
|
||||
*/
|
||||
String getFieldName();
|
||||
|
||||
/**
|
||||
* @return {@literal true} if the field name comes from an explicit value in the field annotation
|
||||
* @since 5.1
|
||||
*/
|
||||
boolean hasExplicitFieldName();
|
||||
|
||||
/**
|
||||
* Returns whether the current property is a {@link SeqNoPrimaryTerm} property.
|
||||
*
|
||||
@@ -74,6 +80,13 @@ public interface ElasticsearchPersistentProperty extends PersistentProperty<Elas
|
||||
*/
|
||||
boolean storeNullValue();
|
||||
|
||||
/**
|
||||
* @return true if empty values ({{@link String}}, or {{@link java.util.Collection}} or {{@link java.util.Map}})
|
||||
* should be store in Elasticsearch.
|
||||
* @since 5.1
|
||||
*/
|
||||
boolean storeEmptyValue();
|
||||
|
||||
/**
|
||||
* @return {@literal true} if this is a GeoPoint property
|
||||
* @since 4.1
|
||||
@@ -100,7 +113,7 @@ public interface ElasticsearchPersistentProperty extends PersistentProperty<Elas
|
||||
|
||||
/**
|
||||
* @return {@literal true} if this is a property annotated with
|
||||
* {@link org.springframework.data.elasticsearch.annotations.IndexedIndexName}.
|
||||
* {@link org.springframework.data.elasticsearch.annotations.IndexedIndexName}.
|
||||
* @since 5.1
|
||||
*/
|
||||
boolean isIndexedIndexNameProperty();
|
||||
|
||||
+8
@@ -84,6 +84,7 @@ public class SimpleElasticsearchPersistentEntity<T> extends BasicPersistentEntit
|
||||
private final Lazy<EvaluationContext> indexNameEvaluationContext = Lazy.of(this::getIndexNameEvaluationContext);
|
||||
|
||||
private final boolean storeIdInSource;
|
||||
private final boolean storeVersionInSource;
|
||||
|
||||
public SimpleElasticsearchPersistentEntity(TypeInformation<T> typeInformation,
|
||||
ContextConfiguration contextConfiguration) {
|
||||
@@ -108,9 +109,11 @@ public class SimpleElasticsearchPersistentEntity<T> extends BasicPersistentEntit
|
||||
this.createIndexAndMapping = document.createIndex();
|
||||
this.dynamic = document.dynamic();
|
||||
this.storeIdInSource = document.storeIdInSource();
|
||||
this.storeVersionInSource = document.storeVersionInSource();
|
||||
} else {
|
||||
this.dynamic = Dynamic.INHERIT;
|
||||
this.storeIdInSource = true;
|
||||
this.storeVersionInSource = true;
|
||||
}
|
||||
Routing routingAnnotation = AnnotatedElementUtils.findMergedAnnotation(clazz, Routing.class);
|
||||
|
||||
@@ -200,6 +203,11 @@ public class SimpleElasticsearchPersistentEntity<T> extends BasicPersistentEntit
|
||||
return storeIdInSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean storeVersionInSource() {
|
||||
return storeVersionInSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPersistentProperty(ElasticsearchPersistentProperty property) {
|
||||
super.addPersistentProperty(property);
|
||||
|
||||
+15
-2
@@ -35,6 +35,7 @@ import org.springframework.data.elasticsearch.annotations.IndexedIndexName;
|
||||
import org.springframework.data.elasticsearch.annotations.MultiField;
|
||||
import org.springframework.data.elasticsearch.annotations.ValueConverter;
|
||||
import org.springframework.data.elasticsearch.annotations.WriteOnlyProperty;
|
||||
import org.springframework.data.elasticsearch.core.convert.AbstractPropertyValueConverter;
|
||||
import org.springframework.data.elasticsearch.core.convert.DatePropertyValueConverter;
|
||||
import org.springframework.data.elasticsearch.core.convert.DateRangePropertyValueConverter;
|
||||
import org.springframework.data.elasticsearch.core.convert.ElasticsearchDateConverter;
|
||||
@@ -82,6 +83,7 @@ public class SimpleElasticsearchPersistentProperty extends
|
||||
private final @Nullable String annotatedFieldName;
|
||||
@Nullable private PropertyValueConverter propertyValueConverter;
|
||||
private final boolean storeNullValue;
|
||||
private final boolean storeEmptyValue;
|
||||
|
||||
public SimpleElasticsearchPersistentProperty(Property property,
|
||||
PersistentEntity<?, ElasticsearchPersistentProperty> owner, SimpleTypeHolder simpleTypeHolder) {
|
||||
@@ -106,6 +108,7 @@ public class SimpleElasticsearchPersistentProperty extends
|
||||
initPropertyValueConverter();
|
||||
|
||||
storeNullValue = isField && getRequiredAnnotation(Field.class).storeNullValue();
|
||||
storeEmptyValue = isField ? getRequiredAnnotation(Field.class).storeEmptyValue() : true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -134,7 +137,13 @@ public class SimpleElasticsearchPersistentProperty extends
|
||||
return storeNullValue;
|
||||
}
|
||||
|
||||
protected boolean hasExplicitFieldName() {
|
||||
@Override
|
||||
public boolean storeEmptyValue() {
|
||||
return storeEmptyValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasExplicitFieldName() {
|
||||
return StringUtils.hasText(getAnnotatedFieldName());
|
||||
}
|
||||
|
||||
@@ -243,7 +252,11 @@ public class SimpleElasticsearchPersistentProperty extends
|
||||
}
|
||||
propertyValueConverter = enumConstants[0];
|
||||
} else {
|
||||
propertyValueConverter = BeanUtils.instantiateClass(clazz);
|
||||
if (AbstractPropertyValueConverter.class.isAssignableFrom(clazz)) {
|
||||
propertyValueConverter = BeanUtils.instantiateClass(BeanUtils.getResolvableConstructor(clazz), this);
|
||||
} else {
|
||||
propertyValueConverter = BeanUtils.instantiateClass(clazz);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,6 +81,7 @@ public class BaseQuery implements Query {
|
||||
@Nullable private Boolean allowNoIndices = null;
|
||||
private EnumSet<IndicesOptions.WildcardStates> expandWildcards;
|
||||
private List<DocValueField> docValueFields = new ArrayList<>();
|
||||
private List<ScriptedField> scriptedFields = new ArrayList<>();
|
||||
|
||||
public BaseQuery() {}
|
||||
|
||||
@@ -115,6 +116,7 @@ public class BaseQuery implements Query {
|
||||
this.allowNoIndices = builder.getAllowNoIndices();
|
||||
this.expandWildcards = builder.getExpandWildcards();
|
||||
this.docValueFields = builder.getDocValueFields();
|
||||
this.scriptedFields = builder.getScriptedFields();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -224,7 +226,7 @@ public class BaseQuery implements Query {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Ids for a multi-get request with on this query.
|
||||
* Set Ids for a multi-get request run with this query. Not used in any other searches.
|
||||
*
|
||||
* @param ids list of id values
|
||||
*/
|
||||
@@ -253,7 +255,7 @@ public class BaseQuery implements Query {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Ids with routing values for a multi-get request set on this query.
|
||||
* Set Ids with routing values for a multi-get request run with this query. Not used in any other searches.
|
||||
*
|
||||
* @param idsWithRouting list of id values, must not be {@literal null}
|
||||
* @since 4.3
|
||||
@@ -543,4 +545,9 @@ public class BaseQuery implements Query {
|
||||
|
||||
this.docValueFields = docValueFields;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ScriptedField> getScriptedFields() {
|
||||
return scriptedFields;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,6 +71,7 @@ public abstract class BaseQueryBuilder<Q extends BaseQuery, SELF extends BaseQue
|
||||
|
||||
@Nullable Integer reactiveBatchSize;
|
||||
private final List<DocValueField> docValueFields = new ArrayList<>();
|
||||
private final List<ScriptedField> scriptedFields = new ArrayList<>();
|
||||
|
||||
@Nullable
|
||||
public Sort getSort() {
|
||||
@@ -226,6 +227,10 @@ public abstract class BaseQueryBuilder<Q extends BaseQuery, SELF extends BaseQue
|
||||
return docValueFields;
|
||||
}
|
||||
|
||||
public List<ScriptedField> getScriptedFields() {
|
||||
return scriptedFields;
|
||||
}
|
||||
|
||||
public SELF withPageable(Pageable pageable) {
|
||||
this.pageable = pageable;
|
||||
return self();
|
||||
@@ -245,6 +250,11 @@ public abstract class BaseQueryBuilder<Q extends BaseQuery, SELF extends BaseQue
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Ids for a multi-get request run with this query. Not used in any other searches.
|
||||
*
|
||||
* @param ids list of id values
|
||||
*/
|
||||
public SELF withIds(String... ids) {
|
||||
|
||||
this.ids.clear();
|
||||
@@ -252,6 +262,11 @@ public abstract class BaseQueryBuilder<Q extends BaseQuery, SELF extends BaseQue
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Ids for a multi-get request run with this query. Not used in any other searches.
|
||||
*
|
||||
* @param ids list of id values
|
||||
*/
|
||||
public SELF withIds(Collection<String> ids) {
|
||||
|
||||
Assert.notNull(ids, "ids must not be null");
|
||||
@@ -367,6 +382,12 @@ public abstract class BaseQueryBuilder<Q extends BaseQuery, SELF extends BaseQue
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Ids with routing values for a multi-get request run with this query. Not used in any other searches.
|
||||
*
|
||||
* @param idsWithRouting list of id values, must not be {@literal null}
|
||||
* @since 4.3
|
||||
*/
|
||||
public SELF withIdsWithRouting(List<Query.IdWithRouting> idsWithRouting) {
|
||||
|
||||
Assert.notNull(idsWithRouting, "idsWithRouting must not be null");
|
||||
@@ -443,6 +464,14 @@ public abstract class BaseQueryBuilder<Q extends BaseQuery, SELF extends BaseQue
|
||||
return self();
|
||||
}
|
||||
|
||||
public SELF withScriptedField(ScriptedField scriptedField) {
|
||||
|
||||
Assert.notNull(scriptedField, "scriptedField must not be null");
|
||||
|
||||
this.scriptedFields.add(scriptedField);
|
||||
return self();
|
||||
}
|
||||
|
||||
public abstract Q build();
|
||||
|
||||
private SELF self() {
|
||||
|
||||
@@ -477,6 +477,12 @@ public interface Query {
|
||||
*/
|
||||
List<DocValueField> getDocValueFields();
|
||||
|
||||
/**
|
||||
* @return the list of scripted fields for the query
|
||||
* @since 5.1
|
||||
*/
|
||||
List<ScriptedField> getScriptedFields();
|
||||
|
||||
/**
|
||||
* @since 4.3
|
||||
*/
|
||||
|
||||
+2
-2
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.repository.support;
|
||||
|
||||
import org.springframework.data.elasticsearch.core.query.BaseQuery;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@@ -30,6 +29,7 @@ import org.springframework.data.elasticsearch.core.RefreshPolicy;
|
||||
import org.springframework.data.elasticsearch.core.SearchHit;
|
||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
import org.springframework.data.elasticsearch.core.query.BaseQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.Query;
|
||||
import org.springframework.data.elasticsearch.repository.ReactiveElasticsearchRepository;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -97,7 +97,7 @@ public class SimpleReactiveElasticsearchRepository<T, ID> implements ReactiveEla
|
||||
|
||||
Assert.notNull(entityStream, "EntityStream must not be null!");
|
||||
|
||||
return operations.saveAll(Flux.from(entityStream).collectList(), entityInformation.getIndexCoordinates())
|
||||
return operations.save(Flux.from(entityStream), entityInformation.getIndexCoordinates())
|
||||
.concatWith(doRefresh().then(Mono.empty()));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Spring Data Elasticsearch 5.1 M1 (2023.0.0)
|
||||
Spring Data Elasticsearch 5.1 RC1 (2023.0.0)
|
||||
Copyright (c) [2013-2022] Pivotal Software, Inc.
|
||||
|
||||
This product is licensed to you under the Apache License, Version 2.0 (the "License").
|
||||
@@ -9,3 +9,6 @@ separate copyright notices and license terms. Your use of the source
|
||||
code for the these subcomponents is subject to the terms and
|
||||
conditions of the subcomponent's license, as noted in the LICENSE file.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
-9
@@ -153,15 +153,6 @@ public class ClientConfigurationUnitTests {
|
||||
assertThat(clientConfiguration.getHostNameVerifier()).contains(NoopHostnameVerifier.INSTANCE);
|
||||
}
|
||||
|
||||
@Test // DATAES-719
|
||||
void shouldHaveDefaultWebClientConfigurer() {
|
||||
ClientConfiguration clientConfiguration = ClientConfiguration.builder() //
|
||||
.connectedTo("foo", "bar") //
|
||||
.build();
|
||||
|
||||
assertThat(clientConfiguration.getWebClientConfigurer()).isEqualTo(Function.identity());
|
||||
}
|
||||
|
||||
@Test // #1885
|
||||
@DisplayName("should use configured httpClientConfigurer as client configurer")
|
||||
void shouldUseConfiguredHttpClientConfigurerAsClientConfigurer() {
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ public class ElasticsearchPartQueryELCIntegrationTests extends ElasticsearchPart
|
||||
|
||||
JacksonJsonpMapper jsonpMapper = new JacksonJsonpMapper();
|
||||
RequestConverter requestConverter = new RequestConverter(operations.getElasticsearchConverter(), jsonpMapper);
|
||||
SearchRequest request = requestConverter.searchRequest(query, clazz, IndexCoordinates.of("dummy"), false);
|
||||
SearchRequest request = requestConverter.searchRequest(query, null, clazz, IndexCoordinates.of("dummy"), false);
|
||||
|
||||
return JsonUtils.toJson(request, jsonpMapper);
|
||||
// return "{\"query\":" + JsonUtils.toJson(request.query(), jsonpMapper) + "}";
|
||||
|
||||
+1
-1
@@ -62,7 +62,7 @@ class RequestConverterTest {
|
||||
.withDocValueFields(docValueFields) //
|
||||
.build();
|
||||
|
||||
var searchRequest = requestConverter.searchRequest(query, SampleEntity.class, IndexCoordinates.of("foo"), true);
|
||||
var searchRequest = requestConverter.searchRequest(query,null, SampleEntity.class, IndexCoordinates.of("foo"), true);
|
||||
|
||||
var fieldAndFormats = searchRequest.docvalueFields();
|
||||
assertThat(fieldAndFormats).hasSize(2);
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ public class ElasticsearchPartQueryERHLCIntegrationTests extends ElasticsearchPa
|
||||
|
||||
protected String buildQueryString(Query query, Class<?> clazz) {
|
||||
SearchSourceBuilder source = new RequestFactory(operations.getElasticsearchConverter())
|
||||
.searchRequest(query, clazz, IndexCoordinates.of("dummy")).source();
|
||||
.searchRequest(query, null, clazz, IndexCoordinates.of("dummy")).source();
|
||||
// remove defaultboost values
|
||||
return source.toString().replaceAll("(\\^\\d+\\.\\d+)", "");
|
||||
}
|
||||
|
||||
+36
-16
@@ -110,7 +110,7 @@ class RequestFactoryTests {
|
||||
.build();
|
||||
|
||||
// when
|
||||
SearchRequest searchRequest = requestFactory.searchRequest(query, null, IndexCoordinates.of("test"));
|
||||
SearchRequest searchRequest = requestFactory.searchRequest(query, null, null, IndexCoordinates.of("test"));
|
||||
|
||||
// then
|
||||
assertThat(searchRequest.source().from()).isEqualTo(30);
|
||||
@@ -218,21 +218,35 @@ class RequestFactoryTests {
|
||||
" ]" + //
|
||||
'}';
|
||||
|
||||
String searchRequest = requestFactory.searchRequest(query, Person.class, IndexCoordinates.of("persons")).source()
|
||||
.toString();
|
||||
String searchRequest = requestFactory.searchRequest(query, null, Person.class, IndexCoordinates.of("persons"))
|
||||
.source().toString();
|
||||
|
||||
assertEquals(expected, searchRequest, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
// DATAES-449
|
||||
void shouldAddRouting() {
|
||||
void shouldAddRoutingFromQuery() {
|
||||
String route = "route66";
|
||||
CriteriaQuery query = new CriteriaQuery(new Criteria("lastName").is("Smith"));
|
||||
query.setRoute(route);
|
||||
converter.updateQuery(query, Person.class);
|
||||
|
||||
SearchRequest searchRequest = requestFactory.searchRequest(query, Person.class, IndexCoordinates.of("persons"));
|
||||
SearchRequest searchRequest = requestFactory.searchRequest(query, null, Person.class,
|
||||
IndexCoordinates.of("persons"));
|
||||
|
||||
assertThat(searchRequest.routing()).isEqualTo(route);
|
||||
}
|
||||
|
||||
@Test
|
||||
// #2087
|
||||
void shouldAddRoutingFromRouting() {
|
||||
String route = "route66";
|
||||
CriteriaQuery query = new CriteriaQuery(new Criteria("lastName").is("Smith"));
|
||||
converter.updateQuery(query, Person.class);
|
||||
|
||||
SearchRequest searchRequest = requestFactory.searchRequest(query, route, Person.class,
|
||||
IndexCoordinates.of("persons"));
|
||||
|
||||
assertThat(searchRequest.routing()).isEqualTo(route);
|
||||
}
|
||||
@@ -242,7 +256,8 @@ class RequestFactoryTests {
|
||||
void shouldAddMaxQueryWindowForUnpagedToRequest() {
|
||||
Query query = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).withPageable(Pageable.unpaged()).build();
|
||||
|
||||
SearchRequest searchRequest = requestFactory.searchRequest(query, Person.class, IndexCoordinates.of("persons"));
|
||||
SearchRequest searchRequest = requestFactory.searchRequest(query, null, Person.class,
|
||||
IndexCoordinates.of("persons"));
|
||||
|
||||
assertThat(searchRequest.source().from()).isEqualTo(0);
|
||||
assertThat(searchRequest.source().size()).isEqualTo(RequestFactory.INDEX_MAX_RESULT_WINDOW);
|
||||
@@ -267,7 +282,7 @@ class RequestFactoryTests {
|
||||
void shouldNotRequestSeqNoAndPrimaryTermWhenEntityClassDoesNotContainSeqNoPrimaryTermProperty() {
|
||||
Query query = new NativeSearchQueryBuilder().build();
|
||||
|
||||
SearchRequest request = requestFactory.searchRequest(query, Person.class, IndexCoordinates.of("persons"));
|
||||
SearchRequest request = requestFactory.searchRequest(query, null, Person.class, IndexCoordinates.of("persons"));
|
||||
|
||||
assertThat(request.source().seqNoAndPrimaryTerm()).isNull();
|
||||
}
|
||||
@@ -277,7 +292,7 @@ class RequestFactoryTests {
|
||||
void shouldRequestSeqNoAndPrimaryTermWhenEntityClassContainsSeqNoPrimaryTermProperty() {
|
||||
Query query = new NativeSearchQueryBuilder().build();
|
||||
|
||||
SearchRequest request = requestFactory.searchRequest(query, EntityWithSeqNoPrimaryTerm.class,
|
||||
SearchRequest request = requestFactory.searchRequest(query, null, EntityWithSeqNoPrimaryTerm.class,
|
||||
IndexCoordinates.of("seqNoPrimaryTerm"));
|
||||
|
||||
assertThat(request.source().seqNoAndPrimaryTerm()).isTrue();
|
||||
@@ -288,7 +303,7 @@ class RequestFactoryTests {
|
||||
void shouldNotRequestSeqNoAndPrimaryTermWhenEntityClassIsNull() {
|
||||
Query query = new NativeSearchQueryBuilder().build();
|
||||
|
||||
SearchRequest request = requestFactory.searchRequest(query, null, IndexCoordinates.of("persons"));
|
||||
SearchRequest request = requestFactory.searchRequest(query, null, null, IndexCoordinates.of("persons"));
|
||||
|
||||
assertThat(request.source().seqNoAndPrimaryTerm()).isNull();
|
||||
}
|
||||
@@ -516,7 +531,8 @@ class RequestFactoryTests {
|
||||
void shouldSetTimeoutToRequest() {
|
||||
Query query = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).withTimeout(Duration.ofSeconds(1)).build();
|
||||
|
||||
SearchRequest searchRequest = requestFactory.searchRequest(query, Person.class, IndexCoordinates.of("persons"));
|
||||
SearchRequest searchRequest = requestFactory.searchRequest(query, null, Person.class,
|
||||
IndexCoordinates.of("persons"));
|
||||
|
||||
assertThat(searchRequest.source().timeout().getMillis()).isEqualTo(Duration.ofSeconds(1).toMillis());
|
||||
}
|
||||
@@ -622,8 +638,8 @@ class RequestFactoryTests {
|
||||
]
|
||||
}""";
|
||||
|
||||
String searchRequest = requestFactory.searchRequest(query, Person.class, IndexCoordinates.of("persons")).source()
|
||||
.toString();
|
||||
String searchRequest = requestFactory.searchRequest(query, null, Person.class, IndexCoordinates.of("persons"))
|
||||
.source().toString();
|
||||
|
||||
assertEquals(expected, searchRequest, false);
|
||||
}
|
||||
@@ -634,7 +650,8 @@ class RequestFactoryTests {
|
||||
|
||||
Query query = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build();
|
||||
|
||||
SearchRequest searchRequest = requestFactory.searchRequest(query, Person.class, IndexCoordinates.of("persons"));
|
||||
SearchRequest searchRequest = requestFactory.searchRequest(query, null, Person.class,
|
||||
IndexCoordinates.of("persons"));
|
||||
|
||||
assertThat(searchRequest.requestCache()).isNull();
|
||||
}
|
||||
@@ -646,7 +663,8 @@ class RequestFactoryTests {
|
||||
Query query = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build();
|
||||
query.setRequestCache(true);
|
||||
|
||||
SearchRequest searchRequest = requestFactory.searchRequest(query, Person.class, IndexCoordinates.of("persons"));
|
||||
SearchRequest searchRequest = requestFactory.searchRequest(query, null, Person.class,
|
||||
IndexCoordinates.of("persons"));
|
||||
|
||||
assertThat(searchRequest.requestCache()).isTrue();
|
||||
}
|
||||
@@ -658,7 +676,8 @@ class RequestFactoryTests {
|
||||
Query query = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build();
|
||||
query.setRequestCache(false);
|
||||
|
||||
SearchRequest searchRequest = requestFactory.searchRequest(query, Person.class, IndexCoordinates.of("persons"));
|
||||
SearchRequest searchRequest = requestFactory.searchRequest(query, null, Person.class,
|
||||
IndexCoordinates.of("persons"));
|
||||
|
||||
assertThat(searchRequest.requestCache()).isFalse();
|
||||
}
|
||||
@@ -670,7 +689,8 @@ class RequestFactoryTests {
|
||||
Query query = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).withStoredFields("lastName", "location")
|
||||
.build();
|
||||
|
||||
SearchRequest searchRequest = requestFactory.searchRequest(query, Person.class, IndexCoordinates.of("persons"));
|
||||
SearchRequest searchRequest = requestFactory.searchRequest(query, null, Person.class,
|
||||
IndexCoordinates.of("persons"));
|
||||
|
||||
assertThat(searchRequest.source().storedFields()).isNotNull();
|
||||
assertThat(searchRequest.source().storedFields().fieldNames())
|
||||
|
||||
+10
-4
@@ -42,6 +42,7 @@ import org.springframework.lang.Nullable;
|
||||
* Testing the querying and parsing of inner_hits.
|
||||
*
|
||||
* @author Peter-Josef Meisch
|
||||
* @author Jakob Hoeper
|
||||
*/
|
||||
@SpringIntegrationTest
|
||||
public abstract class InnerHitsIntegrationTests {
|
||||
@@ -58,8 +59,9 @@ public abstract class InnerHitsIntegrationTests {
|
||||
indexOps.createWithMapping();
|
||||
|
||||
Inhabitant john = new Inhabitant("John", "Smith");
|
||||
Inhabitant carla = new Inhabitant("Carla", "Miller");
|
||||
House cornerHouse = new House("Round the corner", "7", Arrays.asList(john, carla));
|
||||
Inhabitant carla1 = new Inhabitant("Carla", "Miller");
|
||||
Inhabitant carla2 = new Inhabitant("Carla", "Nguyen");
|
||||
House cornerHouse = new House("Round the corner", "7", Arrays.asList(john, carla1, carla2));
|
||||
City metropole = new City("Metropole", Arrays.asList(cornerHouse));
|
||||
|
||||
Inhabitant jack = new Inhabitant("Jack", "Wayne");
|
||||
@@ -76,7 +78,7 @@ public abstract class InnerHitsIntegrationTests {
|
||||
operations.indexOps(IndexCoordinates.of(indexNameProvider.getPrefix() + "*")).delete();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test // #2521
|
||||
void shouldReturnInnerHits() {
|
||||
|
||||
Query query = buildQueryForInnerHits("inner_hit_name", "hou-ses.in-habi-tants", "hou-ses.in-habi-tants.first-name",
|
||||
@@ -91,7 +93,7 @@ public abstract class InnerHitsIntegrationTests {
|
||||
softly.assertThat(searchHit.getInnerHits()).hasSize(1);
|
||||
|
||||
SearchHits<?> innerHits = searchHit.getInnerHits("inner_hit_name");
|
||||
softly.assertThat(innerHits).hasSize(1);
|
||||
softly.assertThat(innerHits).hasSize(2);
|
||||
|
||||
SearchHit<?> innerHit = innerHits.getSearchHit(0);
|
||||
Object content = innerHit.getContent();
|
||||
@@ -106,6 +108,10 @@ public abstract class InnerHitsIntegrationTests {
|
||||
softly.assertThat(nestedMetaData.getChild().getField()).isEqualTo("inhabitants");
|
||||
softly.assertThat(nestedMetaData.getChild().getOffset()).isEqualTo(1);
|
||||
|
||||
innerHit = innerHits.getSearchHit(1);
|
||||
softly.assertThat(((Inhabitant) innerHit.getContent()).getLastName()).isEqualTo("Nguyen");
|
||||
softly.assertThat(innerHit.getNestedMetaData().getChild().getOffset()).isEqualTo(2);
|
||||
|
||||
softly.assertAll();
|
||||
}
|
||||
|
||||
|
||||
+32
-5
@@ -20,7 +20,7 @@ import static org.assertj.core.api.Assertions.*;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.*;
|
||||
import static org.springframework.data.elasticsearch.annotations.FieldType.*;
|
||||
|
||||
import org.springframework.data.elasticsearch.annotations.IndexedIndexName;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
@@ -61,6 +61,7 @@ import org.springframework.data.elasticsearch.RestStatusException;
|
||||
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.IndexedIndexName;
|
||||
import org.springframework.data.elasticsearch.annotations.Mapping;
|
||||
import org.springframework.data.elasticsearch.annotations.Setting;
|
||||
import org.springframework.data.elasticsearch.annotations.WriteOnlyProperty;
|
||||
@@ -170,7 +171,6 @@ public abstract class ReactiveElasticsearchIntegrationTests {
|
||||
assertThat(saved.getIndexedIndexName()).isEqualTo(indexNameProvider.indexName() + "-indexedindexname");
|
||||
}
|
||||
|
||||
|
||||
private Mono<Boolean> documentWithIdExistsInIndex(String id, String index) {
|
||||
return operations.exists(id, IndexCoordinates.of(index));
|
||||
}
|
||||
@@ -1180,6 +1180,25 @@ public abstract class ReactiveElasticsearchIntegrationTests {
|
||||
assertThat(readEntity.getPart2()).isEqualTo(entity.getPart2()); //
|
||||
}).verifyComplete();
|
||||
}
|
||||
|
||||
@Test // #2496
|
||||
@DisplayName("should save data from Flux and return saved data in a flux")
|
||||
void shouldSaveDataFromFluxAndReturnSavedDataInAFlux() {
|
||||
|
||||
var count = 12_345;
|
||||
var entityList = IntStream.rangeClosed(1, count)//
|
||||
.mapToObj(SampleEntity::of) //
|
||||
.collect(Collectors.toList());
|
||||
|
||||
var entityFlux = Flux.fromIterable(entityList);
|
||||
|
||||
operations.save(entityFlux, SampleEntity.class).collectList() //
|
||||
.as(StepVerifier::create) //
|
||||
.consumeNextWith(savedEntities -> {
|
||||
assertThat(savedEntities).isEqualTo(entityList);
|
||||
}) //
|
||||
.verifyComplete();
|
||||
}
|
||||
// endregion
|
||||
|
||||
// region Helper functions
|
||||
@@ -1262,6 +1281,13 @@ public abstract class ReactiveElasticsearchIntegrationTests {
|
||||
@Nullable
|
||||
@Version private Long version;
|
||||
|
||||
static SampleEntity of(int id) {
|
||||
var entity = new SampleEntity();
|
||||
entity.setId("" + id);
|
||||
entity.setMessage(" message " + id);
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getId() {
|
||||
return id;
|
||||
@@ -1543,6 +1569,7 @@ public abstract class ReactiveElasticsearchIntegrationTests {
|
||||
this.part2 = part2;
|
||||
}
|
||||
}
|
||||
|
||||
@Document(indexName = "#{@indexNameProvider.indexName()}-indexedindexname")
|
||||
private static class IndexedIndexNameEntity {
|
||||
@Nullable
|
||||
@@ -1550,8 +1577,7 @@ public abstract class ReactiveElasticsearchIntegrationTests {
|
||||
@Nullable
|
||||
@Field(type = Text) private String someText;
|
||||
@Nullable
|
||||
@IndexedIndexName
|
||||
private String indexedIndexName;
|
||||
@IndexedIndexName private String indexedIndexName;
|
||||
|
||||
@Nullable
|
||||
public String getId() {
|
||||
@@ -1579,5 +1605,6 @@ public abstract class ReactiveElasticsearchIntegrationTests {
|
||||
public void setIndexedIndexName(@Nullable String indexedIndexName) {
|
||||
this.indexedIndexName = indexedIndexName;
|
||||
}
|
||||
} // endregion
|
||||
}
|
||||
// endregion
|
||||
}
|
||||
|
||||
+243
@@ -50,6 +50,7 @@ import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.annotation.ReadOnlyProperty;
|
||||
import org.springframework.data.annotation.Transient;
|
||||
import org.springframework.data.annotation.TypeAlias;
|
||||
import org.springframework.data.annotation.Version;
|
||||
import org.springframework.data.convert.ReadingConverter;
|
||||
import org.springframework.data.convert.WritingConverter;
|
||||
import org.springframework.data.domain.Range;
|
||||
@@ -1893,6 +1894,101 @@ public class MappingElasticsearchConverterUnitTests {
|
||||
assertEquals(expected, json, true);
|
||||
}
|
||||
|
||||
@Test // #2364
|
||||
@DisplayName("should not write version property to document source if configured so")
|
||||
void shouldNotWriteVersionPropertyToDocumentSourceIfConfiguredSo() throws JSONException {
|
||||
|
||||
@Language("JSON")
|
||||
var expected = """
|
||||
{
|
||||
"_class": "org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverterUnitTests$DontWriteVersionToSourceEntity",
|
||||
"id": "42",
|
||||
"text": "some text"
|
||||
}
|
||||
""";
|
||||
var entity = new DontWriteVersionToSourceEntity();
|
||||
entity.setId("42");
|
||||
entity.setVersion(7L);
|
||||
entity.setText("some text");
|
||||
|
||||
Document document = Document.create();
|
||||
mappingElasticsearchConverter.write(entity, document);
|
||||
String json = document.toJson();
|
||||
|
||||
assertEquals(expected, json, true);
|
||||
}
|
||||
|
||||
@Test // #2290
|
||||
@DisplayName("should respect field setting for empty properties")
|
||||
void shouldRespectFieldSettingForEmptyProperties() throws JSONException {
|
||||
@Language("JSON")
|
||||
var expected = """
|
||||
{
|
||||
"_class": "org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverterUnitTests$EntityWithPropertiesThatMightBeEmpty",
|
||||
"id": "42",
|
||||
"stringToWriteWhenEmpty": "",
|
||||
"listToWriteWhenEmpty": [],
|
||||
"mapToWriteWhenEmpty": {}
|
||||
}
|
||||
""";
|
||||
var entity = new EntityWithPropertiesThatMightBeEmpty();
|
||||
entity.setId("42");
|
||||
entity.setStringToWriteWhenEmpty("");
|
||||
entity.setStringToNotWriteWhenEmpty("");
|
||||
entity.setListToWriteWhenEmpty(emptyList());
|
||||
entity.setListToNotWriteWhenEmpty(emptyList());
|
||||
entity.setMapToWriteWhenEmpty(emptyMap());
|
||||
entity.setMapToNotWriteWhenEmpty(emptyMap());
|
||||
|
||||
Document document = Document.create();
|
||||
mappingElasticsearchConverter.write(entity, document);
|
||||
String json = document.toJson();
|
||||
|
||||
assertEquals(expected, json, true);
|
||||
}
|
||||
|
||||
@Test // #2502
|
||||
@DisplayName("should write entity with dotted field name")
|
||||
void shouldWriteEntityWithDottedFieldName() throws JSONException {
|
||||
|
||||
@Language("JSON")
|
||||
var expected = """
|
||||
{
|
||||
"_class": "org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverterUnitTests$FieldNameDotsEntity",
|
||||
"id": "42",
|
||||
"dotted.field": "dotted field"
|
||||
}
|
||||
""";
|
||||
var entity = new FieldNameDotsEntity();
|
||||
entity.setId("42");
|
||||
entity.setDottedField("dotted field");
|
||||
|
||||
Document document = Document.create();
|
||||
mappingElasticsearchConverter.write(entity, document);
|
||||
String json = document.toJson();
|
||||
|
||||
assertEquals(expected, json, true);
|
||||
}
|
||||
|
||||
@Test // #2502
|
||||
@DisplayName("should read entity with dotted field name")
|
||||
void shouldReadEntityWithDottedFieldName() {
|
||||
|
||||
@Language("JSON")
|
||||
String json = """
|
||||
{
|
||||
"id": "42",
|
||||
"dotted.field": "dotted field"
|
||||
}""";
|
||||
|
||||
Document document = Document.parse(json);
|
||||
|
||||
FieldNameDotsEntity entity = mappingElasticsearchConverter.read(FieldNameDotsEntity.class, document);
|
||||
|
||||
assertThat(entity.id).isEqualTo("42");
|
||||
assertThat(entity.getDottedField()).isEqualTo("dotted field");
|
||||
}
|
||||
|
||||
// region entities
|
||||
public static class Sample {
|
||||
@Nullable public @ReadOnlyProperty String readOnly;
|
||||
@@ -2974,6 +3070,153 @@ public class MappingElasticsearchConverterUnitTests {
|
||||
this.text = text;
|
||||
}
|
||||
}
|
||||
|
||||
@org.springframework.data.elasticsearch.annotations.Document(indexName = "doesnt-matter",
|
||||
storeVersionInSource = false)
|
||||
static class DontWriteVersionToSourceEntity {
|
||||
@Nullable private String id;
|
||||
@Version
|
||||
@Nullable private Long version;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Text) private String text;
|
||||
|
||||
@Nullable
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(@Nullable String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Long getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(@Nullable Long version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(@Nullable String text) {
|
||||
this.text = text;
|
||||
}
|
||||
}
|
||||
|
||||
static class EntityWithPropertiesThatMightBeEmpty {
|
||||
@Nullable private String id;
|
||||
|
||||
@Field(type = FieldType.Text)
|
||||
@Nullable private String stringToWriteWhenEmpty;
|
||||
|
||||
@Field(type = FieldType.Text, storeEmptyValue = false)
|
||||
@Nullable private String stringToNotWriteWhenEmpty;
|
||||
|
||||
@Field(type = FieldType.Nested)
|
||||
@Nullable private List<String> listToWriteWhenEmpty;
|
||||
|
||||
@Field(type = FieldType.Nested, storeEmptyValue = false)
|
||||
@Nullable private List<String> listToNotWriteWhenEmpty;
|
||||
|
||||
@Field(type = FieldType.Nested)
|
||||
@Nullable private Map<String, String> mapToWriteWhenEmpty;
|
||||
|
||||
@Field(type = FieldType.Nested, storeEmptyValue = false)
|
||||
@Nullable private Map<String, String> mapToNotWriteWhenEmpty;
|
||||
|
||||
@Nullable
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(@Nullable String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getStringToWriteWhenEmpty() {
|
||||
return stringToWriteWhenEmpty;
|
||||
}
|
||||
|
||||
public void setStringToWriteWhenEmpty(@Nullable String stringToWriteWhenEmpty) {
|
||||
this.stringToWriteWhenEmpty = stringToWriteWhenEmpty;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getStringToNotWriteWhenEmpty() {
|
||||
return stringToNotWriteWhenEmpty;
|
||||
}
|
||||
|
||||
public void setStringToNotWriteWhenEmpty(@Nullable String stringToNotWriteWhenEmpty) {
|
||||
this.stringToNotWriteWhenEmpty = stringToNotWriteWhenEmpty;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public List<String> getListToWriteWhenEmpty() {
|
||||
return listToWriteWhenEmpty;
|
||||
}
|
||||
|
||||
public void setListToWriteWhenEmpty(@Nullable List<String> listToWriteWhenEmpty) {
|
||||
this.listToWriteWhenEmpty = listToWriteWhenEmpty;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public List<String> getListToNotWriteWhenEmpty() {
|
||||
return listToNotWriteWhenEmpty;
|
||||
}
|
||||
|
||||
public void setListToNotWriteWhenEmpty(@Nullable List<String> listToNotWriteWhenEmpty) {
|
||||
this.listToNotWriteWhenEmpty = listToNotWriteWhenEmpty;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Map<String, String> getMapToWriteWhenEmpty() {
|
||||
return mapToWriteWhenEmpty;
|
||||
}
|
||||
|
||||
public void setMapToWriteWhenEmpty(@Nullable Map<String, String> mapToWriteWhenEmpty) {
|
||||
this.mapToWriteWhenEmpty = mapToWriteWhenEmpty;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Map<String, String> getMapToNotWriteWhenEmpty() {
|
||||
return mapToNotWriteWhenEmpty;
|
||||
}
|
||||
|
||||
public void setMapToNotWriteWhenEmpty(@Nullable Map<String, String> mapToNotWriteWhenEmpty) {
|
||||
this.mapToNotWriteWhenEmpty = mapToNotWriteWhenEmpty;
|
||||
}
|
||||
}
|
||||
static class FieldNameDotsEntity {
|
||||
@Id
|
||||
@Nullable private String id;
|
||||
@Nullable
|
||||
@Field(name = "dotted.field", type = FieldType.Text) private String dottedField;
|
||||
|
||||
@Nullable
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(@Nullable String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getDottedField() {
|
||||
return dottedField;
|
||||
}
|
||||
|
||||
public void setDottedField(@Nullable String dottedField) {
|
||||
this.dottedField = dottedField;
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
private static String reverse(Object o) {
|
||||
|
||||
+53
-3
@@ -43,7 +43,16 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.elasticsearch.NewElasticsearchClientDevelopment;
|
||||
import org.springframework.data.elasticsearch.annotations.*;
|
||||
import org.springframework.data.elasticsearch.annotations.DateFormat;
|
||||
import org.springframework.data.elasticsearch.annotations.Document;
|
||||
import org.springframework.data.elasticsearch.annotations.Dynamic;
|
||||
import org.springframework.data.elasticsearch.annotations.Field;
|
||||
import org.springframework.data.elasticsearch.annotations.FieldType;
|
||||
import org.springframework.data.elasticsearch.annotations.InnerField;
|
||||
import org.springframework.data.elasticsearch.annotations.Mapping;
|
||||
import org.springframework.data.elasticsearch.annotations.MultiField;
|
||||
import org.springframework.data.elasticsearch.annotations.Setting;
|
||||
import org.springframework.data.elasticsearch.annotations.TermVector;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
||||
import org.springframework.data.elasticsearch.core.IndexOperations;
|
||||
import org.springframework.data.elasticsearch.core.MappingContextBaseTests;
|
||||
@@ -205,11 +214,37 @@ public abstract class MappingBuilderIntegrationTests extends MappingContextBaseT
|
||||
}
|
||||
|
||||
@Test // #1767
|
||||
@DisplayName("should write dynamic mapping annotations")
|
||||
void shouldWriteDynamicMappingAnnotations() {
|
||||
@DisplayName("should write dynamic mapping annotations on create")
|
||||
void shouldWriteDynamicMappingAnnotationsOnCreate() {
|
||||
|
||||
IndexOperations indexOps = operations.indexOps(DynamicMappingAnnotationEntity.class);
|
||||
indexOps.createWithMapping();
|
||||
|
||||
var mapping = indexOps.getMapping();
|
||||
var dynamic = mapping.get("dynamic");
|
||||
if (dynamic instanceof String s) {
|
||||
assertThat(dynamic).isEqualTo("false");
|
||||
} else {
|
||||
assertThat(mapping.get("dynamic")).isEqualTo(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Test // #2478
|
||||
@DisplayName("should write dynamic mapping annotations on put")
|
||||
void shouldWriteDynamicMappingAnnotationsOnPut() {
|
||||
|
||||
IndexOperations indexOps = operations.indexOps(DynamicMappingAnnotationEntity.class);
|
||||
indexOps.create();
|
||||
|
||||
indexOps.putMapping();
|
||||
|
||||
var mapping = indexOps.getMapping();
|
||||
var dynamic = mapping.get("dynamic");
|
||||
if (dynamic instanceof String s) {
|
||||
assertThat(dynamic).isEqualTo("false");
|
||||
} else {
|
||||
assertThat(mapping.get("dynamic")).isEqualTo(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Test // #1871
|
||||
@@ -244,6 +279,14 @@ public abstract class MappingBuilderIntegrationTests extends MappingContextBaseT
|
||||
indexOps.createWithMapping();
|
||||
}
|
||||
|
||||
@Test // #2502
|
||||
@DisplayName(" should write mapping with field name with dots")
|
||||
void shouldWriteMappingWithFieldNameWithDots() {
|
||||
|
||||
IndexOperations indexOps = operations.indexOps(FieldNameDotsEntity.class);
|
||||
indexOps.createWithMapping();
|
||||
}
|
||||
|
||||
// region Entities
|
||||
@Document(indexName = "#{@indexNameProvider.indexName()}")
|
||||
static class Book {
|
||||
@@ -866,5 +909,12 @@ public abstract class MappingBuilderIntegrationTests extends MappingContextBaseT
|
||||
@Nullable
|
||||
@Field(type = FieldType.Dense_Vector, dims = 1) String denseVectorField;
|
||||
}
|
||||
@Document(indexName = "#{@indexNameProvider.indexName()}")
|
||||
private static class FieldNameDotsEntity {
|
||||
@Id
|
||||
@Nullable private String id;
|
||||
@Nullable
|
||||
@Field(name = "dotted.field", type = Text) private String dottedField;
|
||||
}
|
||||
// endregion
|
||||
}
|
||||
|
||||
+32
-2
@@ -1065,6 +1065,30 @@ public class MappingBuilderUnitTests extends MappingContextBaseTests {
|
||||
|
||||
assertEquals(expected, mapping, true);
|
||||
}
|
||||
|
||||
@Test // #2502
|
||||
@DisplayName("should use custom name with dots")
|
||||
void shouldUseCustomNameWithDots() throws JSONException {
|
||||
|
||||
var expected = """
|
||||
{
|
||||
"properties": {
|
||||
"_class": {
|
||||
"type": "keyword",
|
||||
"index": false,
|
||||
"doc_values": false
|
||||
},
|
||||
"dotted.field": {
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
String mapping = getMappingBuilder().buildPropertyMapping(FieldNameDotsEntity.class);
|
||||
|
||||
assertEquals(expected, mapping, true);
|
||||
}
|
||||
|
||||
// region entities
|
||||
|
||||
@Document(indexName = "ignore-above-index")
|
||||
@@ -2220,8 +2244,14 @@ public class MappingBuilderUnitTests extends MappingContextBaseTests {
|
||||
@Nullable
|
||||
@Field(type = Text) private String someText;
|
||||
@Nullable
|
||||
@IndexedIndexName
|
||||
private String storedIndexName;
|
||||
@IndexedIndexName private String storedIndexName;
|
||||
}
|
||||
|
||||
private static class FieldNameDotsEntity {
|
||||
@Id
|
||||
@Nullable private String id;
|
||||
@Nullable
|
||||
@Field(name = "dotted.field", type = Text) private String dottedField;
|
||||
}
|
||||
// endregion
|
||||
}
|
||||
|
||||
+23
@@ -34,8 +34,10 @@ import org.springframework.data.elasticsearch.annotations.FieldType;
|
||||
import org.springframework.data.elasticsearch.annotations.InnerField;
|
||||
import org.springframework.data.elasticsearch.annotations.MultiField;
|
||||
import org.springframework.data.elasticsearch.annotations.ValueConverter;
|
||||
import org.springframework.data.elasticsearch.core.convert.AbstractPropertyValueConverter;
|
||||
import org.springframework.data.elasticsearch.core.query.SeqNoPrimaryTerm;
|
||||
import org.springframework.data.mapping.MappingException;
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.data.mapping.model.FieldNamingStrategy;
|
||||
import org.springframework.data.mapping.model.Property;
|
||||
import org.springframework.data.mapping.model.PropertyNameFieldNamingStrategy;
|
||||
@@ -258,6 +260,8 @@ public class SimpleElasticsearchPersistentPropertyUnitTests {
|
||||
assertThat(
|
||||
persistentEntity.getRequiredPersistentProperty("fieldWithClassBasedConverter").getPropertyValueConverter())
|
||||
.isInstanceOf(ClassBasedValueConverter.class);
|
||||
assertThat(persistentEntity.getRequiredPersistentProperty("fieldWithClassBasedDerivedFromAbstractValueConverter")
|
||||
.getPropertyValueConverter()).isInstanceOf(ClassBasedDerivedFromAbstractValueConverter.class);
|
||||
assertThat(
|
||||
persistentEntity.getRequiredPersistentProperty("fieldWithEnumBasedConverter").getPropertyValueConverter())
|
||||
.isInstanceOf(EnumBasedValueConverter.class);
|
||||
@@ -354,6 +358,8 @@ public class SimpleElasticsearchPersistentPropertyUnitTests {
|
||||
@Nullable
|
||||
@ValueConverter(ClassBasedValueConverter.class) private String fieldWithClassBasedConverter;
|
||||
@Nullable
|
||||
@ValueConverter(ClassBasedDerivedFromAbstractValueConverter.class) private String fieldWithClassBasedDerivedFromAbstractValueConverter;
|
||||
@Nullable
|
||||
@ValueConverter(EnumBasedValueConverter.class) private String fieldWithEnumBasedConverter;
|
||||
}
|
||||
|
||||
@@ -370,6 +376,23 @@ public class SimpleElasticsearchPersistentPropertyUnitTests {
|
||||
}
|
||||
}
|
||||
|
||||
private static class ClassBasedDerivedFromAbstractValueConverter extends AbstractPropertyValueConverter {
|
||||
|
||||
public ClassBasedDerivedFromAbstractValueConverter(PersistentProperty<?> property) {
|
||||
super(property);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object write(Object value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object read(Object value) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
private enum EnumBasedValueConverter implements PropertyValueConverter {
|
||||
INSTANCE;
|
||||
|
||||
|
||||
-3
@@ -112,7 +112,6 @@ public abstract class CompletionIntegrationTests implements NewElasticsearchClie
|
||||
operations.bulkIndex(indexQueries, AnnotatedCompletionEntity.class);
|
||||
}
|
||||
|
||||
// @DisabledIf(value = "newElasticsearchClient", disabledReason = "todo #2139, ES issue 150")
|
||||
@Test
|
||||
public void shouldFindSuggestionsForGivenCriteriaQueryUsingCompletionEntity() {
|
||||
|
||||
@@ -144,7 +143,6 @@ public abstract class CompletionIntegrationTests implements NewElasticsearchClie
|
||||
operations.get("1", CompletionEntity.class);
|
||||
}
|
||||
|
||||
// @DisabledIf(value = "newElasticsearchClient", disabledReason = "todo #2139, ES issue 150")
|
||||
@Test
|
||||
public void shouldFindSuggestionsForGivenCriteriaQueryUsingAnnotatedCompletionEntity() {
|
||||
|
||||
@@ -168,7 +166,6 @@ public abstract class CompletionIntegrationTests implements NewElasticsearchClie
|
||||
assertThat(options.get(1).getText()).isIn("Marchand", "Mohsin");
|
||||
}
|
||||
|
||||
// @DisabledIf(value = "newElasticsearchClient", disabledReason = "todo #2139, ES 1issue 150")
|
||||
@Test
|
||||
public void shouldFindSuggestionsWithWeightsForGivenCriteriaQueryUsingAnnotatedCompletionEntity() {
|
||||
|
||||
|
||||
-1
@@ -66,7 +66,6 @@ public abstract class ReactiveSuggestIntegrationTests implements NewElasticsearc
|
||||
operations.indexOps(IndexCoordinates.of(indexNameProvider.getPrefix() + "*")).delete().block();
|
||||
}
|
||||
|
||||
// @DisabledIf(value = "newElasticsearchClient", disabledReason = "todo #2139, ES issue 150")
|
||||
@Test // #1302
|
||||
@DisplayName("should find suggestions for given prefix completion")
|
||||
void shouldFindSuggestionsForGivenPrefixCompletion() {
|
||||
|
||||
+1
-2
@@ -20,7 +20,7 @@ package org.springframework.data.elasticsearch.junit.jupiter;
|
||||
*/
|
||||
public enum IntegrationtestEnvironment {
|
||||
|
||||
ELASTICSEARCH, OPENSEARCH, UNDEFINED;
|
||||
ELASTICSEARCH, UNDEFINED;
|
||||
|
||||
public static final String SYSTEM_PROPERTY = "sde.integration-test.environment";
|
||||
|
||||
@@ -29,7 +29,6 @@ public enum IntegrationtestEnvironment {
|
||||
String property = System.getProperty(SYSTEM_PROPERTY, "elasticsearch");
|
||||
return switch (property.toUpperCase()) {
|
||||
case "ELASTICSEARCH" -> ELASTICSEARCH;
|
||||
case "OPENSEARCH" -> OPENSEARCH;
|
||||
default -> UNDEFINED;
|
||||
};
|
||||
}
|
||||
|
||||
+6
@@ -20,6 +20,7 @@ import java.util.Iterator;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.ScrollPosition;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.repository.query.ParameterAccessor;
|
||||
|
||||
@@ -37,6 +38,11 @@ class StubParameterAccessor implements ElasticsearchParameterAccessor {
|
||||
this.values = values;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScrollPosition getScrollPosition() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.ParameterAccessor#getPageable()
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Integration tests to check that {@link org.springframework.data.elasticsearch.annotations.ValueConverter} annotated
|
||||
* properties are handle correctly (method name derived queries, for
|
||||
* properties are handled correctly (method name derived queries, for
|
||||
*
|
||||
* @{@link org.springframework.data.elasticsearch.core.query.Query} methods we don't know which parameters map to which
|
||||
* property.
|
||||
|
||||
+25
@@ -739,6 +739,24 @@ abstract class SimpleReactiveElasticsearchRepositoryIntegrationTests {
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // #2496
|
||||
@DisplayName("should save data from Flux and return saved data in a flux")
|
||||
void shouldSaveDataFromFluxAndReturnSavedDataInAFlux() {
|
||||
var count = 12_345;
|
||||
var entityList = IntStream.rangeClosed(1, count)//
|
||||
.mapToObj(SampleEntity::of) //
|
||||
.collect(Collectors.toList());
|
||||
|
||||
var entityFlux = Flux.fromIterable(entityList);
|
||||
|
||||
repository.saveAll(entityFlux).collectList() //
|
||||
.as(StepVerifier::create) //
|
||||
.consumeNextWith(savedEntities -> {
|
||||
assertThat(savedEntities).isEqualTo(entityList);
|
||||
}) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
Mono<Void> bulkIndex(SampleEntity... entities) {
|
||||
return operations.saveAll(Arrays.asList(entities), IndexCoordinates.of(indexNameProvider.indexName())).then();
|
||||
}
|
||||
@@ -829,6 +847,13 @@ abstract class SimpleReactiveElasticsearchRepositoryIntegrationTests {
|
||||
@Field(name = "custom_field_name", type = FieldType.Text)
|
||||
@Nullable private String customFieldNameMessage;
|
||||
|
||||
static SampleEntity of(int id) {
|
||||
var entity = new SampleEntity();
|
||||
entity.setId("" + id);
|
||||
entity.setMessage(" message " + id);
|
||||
return entity;
|
||||
}
|
||||
|
||||
public SampleEntity() {}
|
||||
|
||||
public SampleEntity(@Nullable String id) {
|
||||
|
||||
+358
-372
@@ -15,10 +15,16 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.repository.support.querybyexample;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.springframework.data.elasticsearch.utils.IdGenerator.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.assertj.core.api.AbstractThrowableAssert;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
||||
@@ -39,14 +45,6 @@ import org.springframework.data.elasticsearch.utils.IndexNameProvider;
|
||||
import org.springframework.data.repository.query.QueryByExampleExecutor;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.springframework.data.elasticsearch.utils.IdGenerator.nextIdAsString;
|
||||
|
||||
/**
|
||||
* @author Ezequiel Antúnez Camacho
|
||||
* @since 5.1
|
||||
@@ -65,410 +63,398 @@ abstract class QueryByExampleElasticsearchExecutorIntegrationTests {
|
||||
}
|
||||
|
||||
@Test // #2418
|
||||
@org.junit.jupiter.api.Order(Integer.MAX_VALUE)
|
||||
@Order(Integer.MAX_VALUE)
|
||||
void cleanup() {
|
||||
operations.indexOps(IndexCoordinates.of(indexNameProvider.getPrefix() + "*")).delete();
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("All QueryByExampleExecutor operations should work")
|
||||
class QueryByExampleExecutorOperations {
|
||||
@Test // #2418
|
||||
void shouldFindOne() {
|
||||
// given
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(documentId);
|
||||
sampleEntity.setMessage("some message");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
@Test // #2418
|
||||
void shouldFindOne() {
|
||||
// given
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(documentId);
|
||||
sampleEntity.setMessage("some message");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(documentId2);
|
||||
sampleEntity2.setMessage("some message");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(documentId2);
|
||||
sampleEntity2.setMessage("some message");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2));
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2));
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setDocumentId(documentId2);
|
||||
Optional<SampleEntity> entityFromElasticSearch = repository.findOne(Example.of(probe));
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setDocumentId(documentId2);
|
||||
Optional<SampleEntity> entityFromElasticSearch = repository.findOne(Example.of(probe));
|
||||
|
||||
// then
|
||||
assertThat(entityFromElasticSearch).contains(sampleEntity2);
|
||||
|
||||
}
|
||||
|
||||
@Test // #2418
|
||||
void shouldThrowExceptionIfMoreThanOneResultInFindOne() {
|
||||
// given
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(nextIdAsString());
|
||||
sampleEntity.setMessage("some message");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(nextIdAsString());
|
||||
sampleEntity2.setMessage("some message");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2));
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setMessage("some message");
|
||||
final Example<SampleEntity> example = Example.of(probe);
|
||||
AbstractThrowableAssert<?, ? extends Throwable> assertThatThrownBy = assertThatThrownBy(
|
||||
() -> repository.findOne(example));
|
||||
|
||||
// then
|
||||
assertThatThrownBy.isInstanceOf(IncorrectResultSizeDataAccessException.class);
|
||||
|
||||
}
|
||||
|
||||
@Test // #2418
|
||||
void shouldFindOneWithNestedField() {
|
||||
// given
|
||||
SampleEntity.SampleNestedEntity sampleNestedEntity = new SampleEntity.SampleNestedEntity();
|
||||
sampleNestedEntity.setNestedData("sampleNestedData");
|
||||
sampleNestedEntity.setAnotherNestedData("sampleAnotherNestedData");
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(nextIdAsString());
|
||||
sampleEntity.setMessage("some message");
|
||||
sampleEntity.setSampleNestedEntity(sampleNestedEntity);
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity.SampleNestedEntity sampleNestedEntity2 = new SampleEntity.SampleNestedEntity();
|
||||
sampleNestedEntity2.setNestedData("sampleNestedData2");
|
||||
sampleNestedEntity2.setAnotherNestedData("sampleAnotherNestedData2");
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(nextIdAsString());
|
||||
sampleEntity2.setMessage("some message");
|
||||
sampleEntity2.setSampleNestedEntity(sampleNestedEntity2);
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2));
|
||||
|
||||
// when
|
||||
SampleEntity.SampleNestedEntity sampleNestedEntityProbe = new SampleEntity.SampleNestedEntity();
|
||||
sampleNestedEntityProbe.setNestedData("sampleNestedData");
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setSampleNestedEntity(sampleNestedEntityProbe);
|
||||
|
||||
Optional<SampleEntity> entityFromElasticSearch = repository.findOne(Example.of(probe));
|
||||
|
||||
// then
|
||||
assertThat(entityFromElasticSearch).contains(sampleEntity);
|
||||
|
||||
}
|
||||
|
||||
@Test // #2418
|
||||
void shouldFindAll() {
|
||||
// given
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(nextIdAsString());
|
||||
sampleEntity.setMessage("hello world");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(nextIdAsString());
|
||||
sampleEntity2.setMessage("hello world");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity3 = new SampleEntity();
|
||||
sampleEntity3.setDocumentId(nextIdAsString());
|
||||
sampleEntity3.setMessage("bye world");
|
||||
sampleEntity3.setVersion(System.currentTimeMillis());
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2, sampleEntity3));
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setMessage("hello world");
|
||||
Iterable<SampleEntity> sampleEntities = repository.findAll(Example.of(probe));
|
||||
|
||||
// then
|
||||
assertThat(sampleEntities).isNotNull().hasSize(2);
|
||||
}
|
||||
|
||||
@Test // #2418
|
||||
void shouldFindAllWithSort() {
|
||||
// given
|
||||
SampleEntity sampleEntityWithRate11 = new SampleEntity();
|
||||
sampleEntityWithRate11.setDocumentId(nextIdAsString());
|
||||
sampleEntityWithRate11.setMessage("hello world");
|
||||
sampleEntityWithRate11.setRate(11);
|
||||
sampleEntityWithRate11.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntityWithRate13 = new SampleEntity();
|
||||
sampleEntityWithRate13.setDocumentId(nextIdAsString());
|
||||
sampleEntityWithRate13.setMessage("hello world");
|
||||
sampleEntityWithRate13.setRate(13);
|
||||
sampleEntityWithRate13.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntityWithRate22 = new SampleEntity();
|
||||
sampleEntityWithRate22.setDocumentId(nextIdAsString());
|
||||
sampleEntityWithRate22.setMessage("hello world");
|
||||
sampleEntityWithRate22.setRate(22);
|
||||
sampleEntityWithRate22.setVersion(System.currentTimeMillis());
|
||||
|
||||
repository.saveAll(List.of(sampleEntityWithRate11, sampleEntityWithRate13, sampleEntityWithRate22));
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
final Iterable<SampleEntity> all = repository.findAll();
|
||||
Iterable<SampleEntity> sampleEntities = repository.findAll(Example.of(probe),
|
||||
Sort.by(Sort.Direction.DESC, "rate"));
|
||||
|
||||
// then
|
||||
assertThat(sampleEntities).isNotNull().hasSize(3).containsExactly(sampleEntityWithRate22, sampleEntityWithRate13,
|
||||
sampleEntityWithRate11);
|
||||
}
|
||||
|
||||
@Test // #2418
|
||||
void shouldFindAllWithPageable() {
|
||||
// given
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(nextIdAsString());
|
||||
sampleEntity.setMessage("hello world");
|
||||
sampleEntity.setRate(1);
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(nextIdAsString());
|
||||
sampleEntity2.setMessage("hello world");
|
||||
sampleEntity2.setRate(3);
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity3 = new SampleEntity();
|
||||
sampleEntity3.setDocumentId(nextIdAsString());
|
||||
sampleEntity3.setMessage("hello world");
|
||||
sampleEntity3.setRate(2);
|
||||
sampleEntity3.setVersion(System.currentTimeMillis());
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2, sampleEntity3));
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
Iterable<SampleEntity> page1 = repository.findAll(Example.of(probe),
|
||||
PageRequest.of(0, 2, Sort.Direction.DESC, "rate"));
|
||||
Iterable<SampleEntity> page2 = repository.findAll(Example.of(probe),
|
||||
PageRequest.of(1, 2, Sort.Direction.DESC, "rate"));
|
||||
|
||||
// then
|
||||
assertThat(page1).isNotNull().hasSize(2).containsExactly(sampleEntity2, sampleEntity3);
|
||||
assertThat(page2).isNotNull().hasSize(1).containsExactly(sampleEntity);
|
||||
}
|
||||
|
||||
@Test // #2418
|
||||
void shouldCount() {
|
||||
// given
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(documentId);
|
||||
sampleEntity.setMessage("some message");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(documentId2);
|
||||
sampleEntity2.setMessage("some message");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2));
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setDocumentId(documentId2);
|
||||
final long count = repository.count(Example.of(probe));
|
||||
|
||||
// then
|
||||
assertThat(count).isPositive();
|
||||
}
|
||||
|
||||
@Test // #2418
|
||||
void shouldExists() {
|
||||
// given
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(documentId);
|
||||
sampleEntity.setMessage("some message");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(documentId2);
|
||||
sampleEntity2.setMessage("some message");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2));
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setDocumentId(documentId2);
|
||||
boolean exists = repository.exists(Example.of(probe));
|
||||
|
||||
// then
|
||||
assertThat(exists).isTrue();
|
||||
}
|
||||
// then
|
||||
assertThat(entityFromElasticSearch).contains(sampleEntity2);
|
||||
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("All ExampleMatchers should work")
|
||||
class AllExampleMatchersShouldWork {
|
||||
@Test // #2418
|
||||
void shouldThrowExceptionIfMoreThanOneResultInFindOne() {
|
||||
// given
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(nextIdAsString());
|
||||
sampleEntity.setMessage("some message");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
|
||||
@Test // #2418
|
||||
void defaultStringMatcherShouldWork() {
|
||||
// given
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(nextIdAsString());
|
||||
sampleEntity.setMessage("hello world");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(nextIdAsString());
|
||||
sampleEntity2.setMessage("some message");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(nextIdAsString());
|
||||
sampleEntity2.setMessage("bye world");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2));
|
||||
|
||||
SampleEntity sampleEntity3 = new SampleEntity();
|
||||
sampleEntity3.setDocumentId(nextIdAsString());
|
||||
sampleEntity3.setMessage("hola mundo");
|
||||
sampleEntity3.setVersion(System.currentTimeMillis());
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setMessage("some message");
|
||||
final Example<SampleEntity> example = Example.of(probe);
|
||||
AbstractThrowableAssert<?, ? extends Throwable> assertThatThrownBy = assertThatThrownBy(
|
||||
() -> repository.findOne(example));
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2, sampleEntity3));
|
||||
// then
|
||||
assertThatThrownBy.isInstanceOf(IncorrectResultSizeDataAccessException.class);
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setMessage("hello world");
|
||||
Iterable<SampleEntity> sampleEntities = repository.findAll(Example.of(probe, ExampleMatcher.matching()
|
||||
.withMatcher("message", ExampleMatcher.GenericPropertyMatcher.of(ExampleMatcher.StringMatcher.DEFAULT))));
|
||||
}
|
||||
|
||||
// then
|
||||
assertThat(sampleEntities).isNotNull().hasSize(1);
|
||||
}
|
||||
@Test // #2418
|
||||
void shouldFindOneWithNestedField() {
|
||||
// given
|
||||
SampleEntity.SampleNestedEntity sampleNestedEntity = new SampleEntity.SampleNestedEntity();
|
||||
sampleNestedEntity.setNestedData("sampleNestedData");
|
||||
sampleNestedEntity.setAnotherNestedData("sampleAnotherNestedData");
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(nextIdAsString());
|
||||
sampleEntity.setMessage("some message");
|
||||
sampleEntity.setSampleNestedEntity(sampleNestedEntity);
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
|
||||
@Test // #2418
|
||||
void exactStringMatcherShouldWork() {
|
||||
// given
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(nextIdAsString());
|
||||
sampleEntity.setMessage("hello world");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
SampleEntity.SampleNestedEntity sampleNestedEntity2 = new SampleEntity.SampleNestedEntity();
|
||||
sampleNestedEntity2.setNestedData("sampleNestedData2");
|
||||
sampleNestedEntity2.setAnotherNestedData("sampleAnotherNestedData2");
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(nextIdAsString());
|
||||
sampleEntity2.setMessage("some message");
|
||||
sampleEntity2.setSampleNestedEntity(sampleNestedEntity2);
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(nextIdAsString());
|
||||
sampleEntity2.setMessage("bye world");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2));
|
||||
|
||||
SampleEntity sampleEntity3 = new SampleEntity();
|
||||
sampleEntity3.setDocumentId(nextIdAsString());
|
||||
sampleEntity3.setMessage("hola mundo");
|
||||
sampleEntity3.setVersion(System.currentTimeMillis());
|
||||
// when
|
||||
SampleEntity.SampleNestedEntity sampleNestedEntityProbe = new SampleEntity.SampleNestedEntity();
|
||||
sampleNestedEntityProbe.setNestedData("sampleNestedData");
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setSampleNestedEntity(sampleNestedEntityProbe);
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2, sampleEntity3));
|
||||
Optional<SampleEntity> entityFromElasticSearch = repository.findOne(Example.of(probe));
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setMessage("bye world");
|
||||
Iterable<SampleEntity> sampleEntities = repository.findAll(Example.of(probe, ExampleMatcher.matching()
|
||||
.withMatcher("message", ExampleMatcher.GenericPropertyMatcher.of(ExampleMatcher.StringMatcher.EXACT))));
|
||||
// then
|
||||
assertThat(entityFromElasticSearch).contains(sampleEntity);
|
||||
|
||||
// then
|
||||
assertThat(sampleEntities).isNotNull().hasSize(1);
|
||||
}
|
||||
}
|
||||
|
||||
@Test // #2418
|
||||
void startingStringMatcherShouldWork() {
|
||||
// given
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(nextIdAsString());
|
||||
sampleEntity.setMessage("hello world");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
@Test // #2418
|
||||
void shouldFindAll() {
|
||||
// given
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(nextIdAsString());
|
||||
sampleEntity.setMessage("hello world");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(nextIdAsString());
|
||||
sampleEntity2.setMessage("bye world");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(nextIdAsString());
|
||||
sampleEntity2.setMessage("hello world");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity3 = new SampleEntity();
|
||||
sampleEntity3.setDocumentId(nextIdAsString());
|
||||
sampleEntity3.setMessage("hola mundo");
|
||||
sampleEntity3.setVersion(System.currentTimeMillis());
|
||||
SampleEntity sampleEntity3 = new SampleEntity();
|
||||
sampleEntity3.setDocumentId(nextIdAsString());
|
||||
sampleEntity3.setMessage("bye world");
|
||||
sampleEntity3.setVersion(System.currentTimeMillis());
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2, sampleEntity3));
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2, sampleEntity3));
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setMessage("h");
|
||||
Iterable<SampleEntity> sampleEntities = repository.findAll(Example.of(probe, ExampleMatcher.matching()
|
||||
.withMatcher("message", ExampleMatcher.GenericPropertyMatcher.of(ExampleMatcher.StringMatcher.STARTING))));
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setMessage("hello world");
|
||||
Iterable<SampleEntity> sampleEntities = repository.findAll(Example.of(probe));
|
||||
|
||||
// then
|
||||
assertThat(sampleEntities).isNotNull().hasSize(2);
|
||||
}
|
||||
// then
|
||||
assertThat(sampleEntities).isNotNull().hasSize(2);
|
||||
}
|
||||
|
||||
@Test // #2418
|
||||
void endingStringMatcherShouldWork() {
|
||||
// given
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(nextIdAsString());
|
||||
sampleEntity.setMessage("hello world");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
@Test // #2418
|
||||
void shouldFindAllWithSort() {
|
||||
// given
|
||||
SampleEntity sampleEntityWithRate11 = new SampleEntity();
|
||||
sampleEntityWithRate11.setDocumentId(nextIdAsString());
|
||||
sampleEntityWithRate11.setMessage("hello world");
|
||||
sampleEntityWithRate11.setRate(11);
|
||||
sampleEntityWithRate11.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(nextIdAsString());
|
||||
sampleEntity2.setMessage("bye world");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
SampleEntity sampleEntityWithRate13 = new SampleEntity();
|
||||
sampleEntityWithRate13.setDocumentId(nextIdAsString());
|
||||
sampleEntityWithRate13.setMessage("hello world");
|
||||
sampleEntityWithRate13.setRate(13);
|
||||
sampleEntityWithRate13.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity3 = new SampleEntity();
|
||||
sampleEntity3.setDocumentId(nextIdAsString());
|
||||
sampleEntity3.setMessage("hola mundo");
|
||||
sampleEntity3.setVersion(System.currentTimeMillis());
|
||||
SampleEntity sampleEntityWithRate22 = new SampleEntity();
|
||||
sampleEntityWithRate22.setDocumentId(nextIdAsString());
|
||||
sampleEntityWithRate22.setMessage("hello world");
|
||||
sampleEntityWithRate22.setRate(22);
|
||||
sampleEntityWithRate22.setVersion(System.currentTimeMillis());
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2, sampleEntity3));
|
||||
repository.saveAll(List.of(sampleEntityWithRate11, sampleEntityWithRate13, sampleEntityWithRate22));
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setMessage("world");
|
||||
Iterable<SampleEntity> sampleEntities = repository.findAll(Example.of(probe, ExampleMatcher.matching()
|
||||
.withMatcher("message", ExampleMatcher.GenericPropertyMatcher.of(ExampleMatcher.StringMatcher.ENDING))));
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
final Iterable<SampleEntity> all = repository.findAll();
|
||||
Iterable<SampleEntity> sampleEntities = repository.findAll(Example.of(probe), Sort.by(Sort.Direction.DESC, "rate"));
|
||||
|
||||
// then
|
||||
assertThat(sampleEntities).isNotNull().hasSize(2);
|
||||
}
|
||||
// then
|
||||
assertThat(sampleEntities).isNotNull().hasSize(3).containsExactly(sampleEntityWithRate22, sampleEntityWithRate13,
|
||||
sampleEntityWithRate11);
|
||||
}
|
||||
|
||||
@Test // #2418
|
||||
void regexStringMatcherShouldWork() {
|
||||
// given
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(nextIdAsString());
|
||||
sampleEntity.setMessage("hello world");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
@Test // #2418
|
||||
void shouldFindAllWithPageable() {
|
||||
// given
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(nextIdAsString());
|
||||
sampleEntity.setMessage("hello world");
|
||||
sampleEntity.setRate(1);
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(nextIdAsString());
|
||||
sampleEntity2.setMessage("bye world");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(nextIdAsString());
|
||||
sampleEntity2.setMessage("hello world");
|
||||
sampleEntity2.setRate(3);
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity3 = new SampleEntity();
|
||||
sampleEntity3.setDocumentId(nextIdAsString());
|
||||
sampleEntity3.setMessage("hola mundo");
|
||||
sampleEntity3.setVersion(System.currentTimeMillis());
|
||||
SampleEntity sampleEntity3 = new SampleEntity();
|
||||
sampleEntity3.setDocumentId(nextIdAsString());
|
||||
sampleEntity3.setMessage("hello world");
|
||||
sampleEntity3.setRate(2);
|
||||
sampleEntity3.setVersion(System.currentTimeMillis());
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2, sampleEntity3));
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2, sampleEntity3));
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setMessage("[(hello)(hola)].*");
|
||||
Iterable<SampleEntity> sampleEntities = repository.findAll(Example.of(probe, ExampleMatcher.matching()
|
||||
.withMatcher("message", ExampleMatcher.GenericPropertyMatcher.of(ExampleMatcher.StringMatcher.REGEX))));
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
Iterable<SampleEntity> page1 = repository.findAll(Example.of(probe),
|
||||
PageRequest.of(0, 2, Sort.Direction.DESC, "rate"));
|
||||
Iterable<SampleEntity> page2 = repository.findAll(Example.of(probe),
|
||||
PageRequest.of(1, 2, Sort.Direction.DESC, "rate"));
|
||||
|
||||
// then
|
||||
assertThat(sampleEntities).isNotNull().hasSize(2);
|
||||
}
|
||||
// then
|
||||
assertThat(page1).isNotNull().hasSize(2).containsExactly(sampleEntity2, sampleEntity3);
|
||||
assertThat(page2).isNotNull().hasSize(1).containsExactly(sampleEntity);
|
||||
}
|
||||
|
||||
@Test // #2418
|
||||
void shouldCount() {
|
||||
// given
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(documentId);
|
||||
sampleEntity.setMessage("some message");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(documentId2);
|
||||
sampleEntity2.setMessage("some message");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2));
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setDocumentId(documentId2);
|
||||
final long count = repository.count(Example.of(probe));
|
||||
|
||||
// then
|
||||
assertThat(count).isPositive();
|
||||
}
|
||||
|
||||
@Test // #2418
|
||||
void shouldExists() {
|
||||
// given
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(documentId);
|
||||
sampleEntity.setMessage("some message");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(documentId2);
|
||||
sampleEntity2.setMessage("some message");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2));
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setDocumentId(documentId2);
|
||||
boolean exists = repository.exists(Example.of(probe));
|
||||
|
||||
// then
|
||||
assertThat(exists).isTrue();
|
||||
}
|
||||
|
||||
@Test // #2418
|
||||
void defaultStringMatcherShouldWork() {
|
||||
// given
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(nextIdAsString());
|
||||
sampleEntity.setMessage("hello world");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(nextIdAsString());
|
||||
sampleEntity2.setMessage("bye world");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity3 = new SampleEntity();
|
||||
sampleEntity3.setDocumentId(nextIdAsString());
|
||||
sampleEntity3.setMessage("hola mundo");
|
||||
sampleEntity3.setVersion(System.currentTimeMillis());
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2, sampleEntity3));
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setMessage("hello world");
|
||||
Iterable<SampleEntity> sampleEntities = repository.findAll(Example.of(probe, ExampleMatcher.matching()
|
||||
.withMatcher("message", ExampleMatcher.GenericPropertyMatcher.of(ExampleMatcher.StringMatcher.DEFAULT))));
|
||||
|
||||
// then
|
||||
assertThat(sampleEntities).isNotNull().hasSize(1);
|
||||
}
|
||||
|
||||
@Test // #2418
|
||||
void exactStringMatcherShouldWork() {
|
||||
// given
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(nextIdAsString());
|
||||
sampleEntity.setMessage("hello world");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(nextIdAsString());
|
||||
sampleEntity2.setMessage("bye world");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity3 = new SampleEntity();
|
||||
sampleEntity3.setDocumentId(nextIdAsString());
|
||||
sampleEntity3.setMessage("hola mundo");
|
||||
sampleEntity3.setVersion(System.currentTimeMillis());
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2, sampleEntity3));
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setMessage("bye world");
|
||||
Iterable<SampleEntity> sampleEntities = repository.findAll(Example.of(probe, ExampleMatcher.matching()
|
||||
.withMatcher("message", ExampleMatcher.GenericPropertyMatcher.of(ExampleMatcher.StringMatcher.EXACT))));
|
||||
|
||||
// then
|
||||
assertThat(sampleEntities).isNotNull().hasSize(1);
|
||||
}
|
||||
|
||||
@Test // #2418
|
||||
void startingStringMatcherShouldWork() {
|
||||
// given
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(nextIdAsString());
|
||||
sampleEntity.setMessage("hello world");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(nextIdAsString());
|
||||
sampleEntity2.setMessage("bye world");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity3 = new SampleEntity();
|
||||
sampleEntity3.setDocumentId(nextIdAsString());
|
||||
sampleEntity3.setMessage("hola mundo");
|
||||
sampleEntity3.setVersion(System.currentTimeMillis());
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2, sampleEntity3));
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setMessage("h");
|
||||
Iterable<SampleEntity> sampleEntities = repository.findAll(Example.of(probe, ExampleMatcher.matching()
|
||||
.withMatcher("message", ExampleMatcher.GenericPropertyMatcher.of(ExampleMatcher.StringMatcher.STARTING))));
|
||||
|
||||
// then
|
||||
assertThat(sampleEntities).isNotNull().hasSize(2);
|
||||
}
|
||||
|
||||
@Test // #2418
|
||||
void endingStringMatcherShouldWork() {
|
||||
// given
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(nextIdAsString());
|
||||
sampleEntity.setMessage("hello world");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(nextIdAsString());
|
||||
sampleEntity2.setMessage("bye world");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity3 = new SampleEntity();
|
||||
sampleEntity3.setDocumentId(nextIdAsString());
|
||||
sampleEntity3.setMessage("hola mundo");
|
||||
sampleEntity3.setVersion(System.currentTimeMillis());
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2, sampleEntity3));
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setMessage("world");
|
||||
Iterable<SampleEntity> sampleEntities = repository.findAll(Example.of(probe, ExampleMatcher.matching()
|
||||
.withMatcher("message", ExampleMatcher.GenericPropertyMatcher.of(ExampleMatcher.StringMatcher.ENDING))));
|
||||
|
||||
// then
|
||||
assertThat(sampleEntities).isNotNull().hasSize(2);
|
||||
}
|
||||
|
||||
@Test // #2418
|
||||
void regexStringMatcherShouldWork() {
|
||||
// given
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(nextIdAsString());
|
||||
sampleEntity.setMessage("hello world");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(nextIdAsString());
|
||||
sampleEntity2.setMessage("bye world");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity3 = new SampleEntity();
|
||||
sampleEntity3.setDocumentId(nextIdAsString());
|
||||
sampleEntity3.setMessage("hola mundo");
|
||||
sampleEntity3.setVersion(System.currentTimeMillis());
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2, sampleEntity3));
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setMessage("[(hello)(hola)].*");
|
||||
Iterable<SampleEntity> sampleEntities = repository.findAll(Example.of(probe, ExampleMatcher.matching()
|
||||
.withMatcher("message", ExampleMatcher.GenericPropertyMatcher.of(ExampleMatcher.StringMatcher.REGEX))));
|
||||
|
||||
// then
|
||||
assertThat(sampleEntities).isNotNull().hasSize(2);
|
||||
}
|
||||
|
||||
@Document(indexName = "#{@indexNameProvider.indexName()}")
|
||||
|
||||
+393
-405
@@ -15,9 +15,16 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.repository.support.querybyexample;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.springframework.data.elasticsearch.utils.IdGenerator.*;
|
||||
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
||||
@@ -36,13 +43,6 @@ import org.springframework.data.elasticsearch.repository.ReactiveElasticsearchRe
|
||||
import org.springframework.data.elasticsearch.utils.IndexNameProvider;
|
||||
import org.springframework.data.repository.query.ReactiveQueryByExampleExecutor;
|
||||
import org.springframework.lang.Nullable;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.data.elasticsearch.utils.IdGenerator.nextIdAsString;
|
||||
|
||||
/**
|
||||
* @author Ezequiel Antúnez Camacho
|
||||
@@ -58,430 +58,418 @@ abstract class ReactiveQueryByExampleElasticsearchExecutorIntegrationTests {
|
||||
@BeforeEach
|
||||
void before() {
|
||||
indexNameProvider.increment();
|
||||
operations.indexOps(SampleEntity.class).createWithMapping()
|
||||
operations.indexOps(SampleEntity.class).createWithMapping().as(StepVerifier::create) //
|
||||
.expectNext(true) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // #2418
|
||||
@Order(Integer.MAX_VALUE)
|
||||
void cleanup() {
|
||||
operations.indexOps(IndexCoordinates.of(indexNameProvider.getPrefix() + "*")).delete().block();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldFindOne() {
|
||||
// given
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(documentId);
|
||||
sampleEntity.setMessage("some message");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(documentId2);
|
||||
sampleEntity2.setMessage("some message");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextCount(2L) //
|
||||
.verifyComplete();
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setDocumentId(documentId2);
|
||||
repository.findOne(Example.of(probe))
|
||||
// then
|
||||
.as(StepVerifier::create) //
|
||||
.consumeNextWith(entityFromElasticSearch -> assertThat(entityFromElasticSearch).isEqualTo(sampleEntity2)) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldThrowExceptionIfMoreThanOneResultInFindOne() {
|
||||
// given
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(nextIdAsString());
|
||||
sampleEntity.setMessage("some message");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(nextIdAsString());
|
||||
sampleEntity2.setMessage("some message");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextCount(2L) //
|
||||
.verifyComplete();
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
repository.findOne(Example.of(probe))
|
||||
// then
|
||||
.as(StepVerifier::create) //
|
||||
.expectError(IncorrectResultSizeDataAccessException.class) //
|
||||
.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldFindOneWithNestedField() {
|
||||
// given
|
||||
SampleEntity.SampleNestedEntity sampleNestedEntity = new SampleEntity.SampleNestedEntity();
|
||||
sampleNestedEntity.setNestedData("sampleNestedData");
|
||||
sampleNestedEntity.setAnotherNestedData("sampleAnotherNestedData");
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(nextIdAsString());
|
||||
sampleEntity.setMessage("some message");
|
||||
sampleEntity.setSampleNestedEntity(sampleNestedEntity);
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity.SampleNestedEntity sampleNestedEntity2 = new SampleEntity.SampleNestedEntity();
|
||||
sampleNestedEntity2.setNestedData("sampleNestedData2");
|
||||
sampleNestedEntity2.setAnotherNestedData("sampleAnotherNestedData2");
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(nextIdAsString());
|
||||
sampleEntity2.setMessage("some message");
|
||||
sampleEntity2.setSampleNestedEntity(sampleNestedEntity2);
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextCount(2L) //
|
||||
.verifyComplete();
|
||||
|
||||
// when
|
||||
SampleEntity.SampleNestedEntity sampleNestedEntityProbe = new SampleEntity.SampleNestedEntity();
|
||||
sampleNestedEntityProbe.setNestedData("sampleNestedData");
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setSampleNestedEntity(sampleNestedEntityProbe);
|
||||
repository.findOne(Example.of(probe))
|
||||
// then
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(sampleEntity) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldFindAll() {
|
||||
// given
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(nextIdAsString());
|
||||
sampleEntity.setMessage("hello world");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(nextIdAsString());
|
||||
sampleEntity2.setMessage("hello world");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity3 = new SampleEntity();
|
||||
sampleEntity3.setDocumentId(nextIdAsString());
|
||||
sampleEntity3.setMessage("bye world");
|
||||
sampleEntity3.setVersion(System.currentTimeMillis());
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2, sampleEntity3)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextCount(3L) //
|
||||
.verifyComplete();
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setMessage("hello world");
|
||||
repository.findAll(Example.of(probe))
|
||||
// then
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextSequence(List.of(sampleEntity, sampleEntity2)) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldFindAllWithSort() {
|
||||
// given
|
||||
SampleEntity sampleEntityWithRate11 = new SampleEntity();
|
||||
sampleEntityWithRate11.setDocumentId(nextIdAsString());
|
||||
sampleEntityWithRate11.setMessage("hello world");
|
||||
sampleEntityWithRate11.setRate(11);
|
||||
sampleEntityWithRate11.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntityWithRate13 = new SampleEntity();
|
||||
sampleEntityWithRate13.setDocumentId(nextIdAsString());
|
||||
sampleEntityWithRate13.setMessage("hello world");
|
||||
sampleEntityWithRate13.setRate(13);
|
||||
sampleEntityWithRate13.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntityWithRate22 = new SampleEntity();
|
||||
sampleEntityWithRate22.setDocumentId(nextIdAsString());
|
||||
sampleEntityWithRate22.setMessage("hello world");
|
||||
sampleEntityWithRate22.setRate(22);
|
||||
sampleEntityWithRate22.setVersion(System.currentTimeMillis());
|
||||
|
||||
repository.saveAll(List.of(sampleEntityWithRate11, sampleEntityWithRate13, sampleEntityWithRate22)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextCount(3L) //
|
||||
.verifyComplete();
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
repository.findAll(Example.of(probe), Sort.by(Sort.Direction.DESC, "rate"))
|
||||
// then
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextSequence(List.of(sampleEntityWithRate22, sampleEntityWithRate13, sampleEntityWithRate11)) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCount() {
|
||||
// given
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(documentId);
|
||||
sampleEntity.setMessage("some message");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(documentId2);
|
||||
sampleEntity2.setMessage("some message");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextCount(2L) //
|
||||
.verifyComplete();
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setDocumentId(documentId2);
|
||||
repository.count(Example.of(probe))
|
||||
// then
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(1L) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldExists() {
|
||||
// given
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(documentId);
|
||||
sampleEntity.setMessage("some message");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(documentId2);
|
||||
sampleEntity2.setMessage("some message");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextCount(2L) //
|
||||
.verifyComplete();
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setDocumentId(documentId2);
|
||||
repository.exists(Example.of(probe))
|
||||
// then
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(true) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // #2418
|
||||
@org.junit.jupiter.api.Order(Integer.MAX_VALUE)
|
||||
void cleanup() {
|
||||
operations.indexOps(IndexCoordinates.of(indexNameProvider.getPrefix() + "*")).delete();
|
||||
void defaultStringMatcherShouldWork() {
|
||||
// given
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(nextIdAsString());
|
||||
sampleEntity.setMessage("hello world");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(nextIdAsString());
|
||||
sampleEntity2.setMessage("bye world");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity3 = new SampleEntity();
|
||||
sampleEntity3.setDocumentId(nextIdAsString());
|
||||
sampleEntity3.setMessage("hola mundo");
|
||||
sampleEntity3.setVersion(System.currentTimeMillis());
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2, sampleEntity3)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextCount(3L) //
|
||||
.verifyComplete();
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setMessage("hello world");
|
||||
repository
|
||||
.findAll(Example.of(probe,
|
||||
ExampleMatcher.matching().withMatcher("message",
|
||||
ExampleMatcher.GenericPropertyMatcher.of(ExampleMatcher.StringMatcher.DEFAULT))))
|
||||
// then
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(sampleEntity) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("All QueryByExampleExecutor operations should work")
|
||||
class ReactiveQueryByExampleExecutorOperations {
|
||||
@Test
|
||||
void shouldFindOne() {
|
||||
// given
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(documentId);
|
||||
sampleEntity.setMessage("some message");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
@Test // #2418
|
||||
void exactStringMatcherShouldWork() {
|
||||
// given
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(nextIdAsString());
|
||||
sampleEntity.setMessage("hello world");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(documentId2);
|
||||
sampleEntity2.setMessage("some message");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(nextIdAsString());
|
||||
sampleEntity2.setMessage("bye world");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextCount(2L) //
|
||||
.verifyComplete();
|
||||
SampleEntity sampleEntity3 = new SampleEntity();
|
||||
sampleEntity3.setDocumentId(nextIdAsString());
|
||||
sampleEntity3.setMessage("hola mundo");
|
||||
sampleEntity3.setVersion(System.currentTimeMillis());
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setDocumentId(documentId2);
|
||||
repository.findOne(Example.of(probe))
|
||||
// then
|
||||
.as(StepVerifier::create) //
|
||||
.consumeNextWith(entityFromElasticSearch -> assertThat(entityFromElasticSearch).isEqualTo(sampleEntity2)) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldThrowExceptionIfMoreThanOneResultInFindOne() {
|
||||
// given
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(nextIdAsString());
|
||||
sampleEntity.setMessage("some message");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(nextIdAsString());
|
||||
sampleEntity2.setMessage("some message");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextCount(2L) //
|
||||
.verifyComplete();
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
repository.findOne(Example.of(probe))
|
||||
// then
|
||||
.as(StepVerifier::create) //
|
||||
.expectError(IncorrectResultSizeDataAccessException.class) //
|
||||
.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldFindOneWithNestedField() {
|
||||
// given
|
||||
SampleEntity.SampleNestedEntity sampleNestedEntity = new SampleEntity.SampleNestedEntity();
|
||||
sampleNestedEntity.setNestedData("sampleNestedData");
|
||||
sampleNestedEntity.setAnotherNestedData("sampleAnotherNestedData");
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(nextIdAsString());
|
||||
sampleEntity.setMessage("some message");
|
||||
sampleEntity.setSampleNestedEntity(sampleNestedEntity);
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity.SampleNestedEntity sampleNestedEntity2 = new SampleEntity.SampleNestedEntity();
|
||||
sampleNestedEntity2.setNestedData("sampleNestedData2");
|
||||
sampleNestedEntity2.setAnotherNestedData("sampleAnotherNestedData2");
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(nextIdAsString());
|
||||
sampleEntity2.setMessage("some message");
|
||||
sampleEntity2.setSampleNestedEntity(sampleNestedEntity2);
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextCount(2L) //
|
||||
.verifyComplete();
|
||||
|
||||
// when
|
||||
SampleEntity.SampleNestedEntity sampleNestedEntityProbe = new SampleEntity.SampleNestedEntity();
|
||||
sampleNestedEntityProbe.setNestedData("sampleNestedData");
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setSampleNestedEntity(sampleNestedEntityProbe);
|
||||
repository.findOne(Example.of(probe))
|
||||
// then
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(sampleEntity) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldFindAll() {
|
||||
// given
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(nextIdAsString());
|
||||
sampleEntity.setMessage("hello world");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(nextIdAsString());
|
||||
sampleEntity2.setMessage("hello world");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity3 = new SampleEntity();
|
||||
sampleEntity3.setDocumentId(nextIdAsString());
|
||||
sampleEntity3.setMessage("bye world");
|
||||
sampleEntity3.setVersion(System.currentTimeMillis());
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2, sampleEntity3)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextCount(3L) //
|
||||
.verifyComplete();
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setMessage("hello world");
|
||||
repository.findAll(Example.of(probe))
|
||||
// then
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextSequence(List.of(sampleEntity, sampleEntity2)) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldFindAllWithSort() {
|
||||
// given
|
||||
SampleEntity sampleEntityWithRate11 = new SampleEntity();
|
||||
sampleEntityWithRate11.setDocumentId(nextIdAsString());
|
||||
sampleEntityWithRate11.setMessage("hello world");
|
||||
sampleEntityWithRate11.setRate(11);
|
||||
sampleEntityWithRate11.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntityWithRate13 = new SampleEntity();
|
||||
sampleEntityWithRate13.setDocumentId(nextIdAsString());
|
||||
sampleEntityWithRate13.setMessage("hello world");
|
||||
sampleEntityWithRate13.setRate(13);
|
||||
sampleEntityWithRate13.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntityWithRate22 = new SampleEntity();
|
||||
sampleEntityWithRate22.setDocumentId(nextIdAsString());
|
||||
sampleEntityWithRate22.setMessage("hello world");
|
||||
sampleEntityWithRate22.setRate(22);
|
||||
sampleEntityWithRate22.setVersion(System.currentTimeMillis());
|
||||
|
||||
repository.saveAll(List.of(sampleEntityWithRate11, sampleEntityWithRate13, sampleEntityWithRate22)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextCount(3L) //
|
||||
.verifyComplete();
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
repository.findAll(Example.of(probe), Sort.by(Sort.Direction.DESC, "rate"))
|
||||
// then
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextSequence(List.of(sampleEntityWithRate22, sampleEntityWithRate13, sampleEntityWithRate11)) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCount() {
|
||||
// given
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(documentId);
|
||||
sampleEntity.setMessage("some message");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(documentId2);
|
||||
sampleEntity2.setMessage("some message");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextCount(2L) //
|
||||
.verifyComplete();
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setDocumentId(documentId2);
|
||||
repository.count(Example.of(probe))
|
||||
// then
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(1L) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldExists() {
|
||||
// given
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(documentId);
|
||||
sampleEntity.setMessage("some message");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(documentId2);
|
||||
sampleEntity2.setMessage("some message");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextCount(2L) //
|
||||
.verifyComplete();
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setDocumentId(documentId2);
|
||||
repository.exists(Example.of(probe))
|
||||
// then
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(true) //
|
||||
.verifyComplete();
|
||||
}
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2, sampleEntity3)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextCount(3L) //
|
||||
.verifyComplete();
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setMessage("bye world");
|
||||
repository
|
||||
.findAll(Example.of(probe,
|
||||
ExampleMatcher.matching().withMatcher("message",
|
||||
ExampleMatcher.GenericPropertyMatcher.of(ExampleMatcher.StringMatcher.EXACT))))
|
||||
// then
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(sampleEntity2) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("All ExampleMatchers should work")
|
||||
class AllExampleMatchersShouldWork {
|
||||
@Test // #2418
|
||||
void startingStringMatcherShouldWork() {
|
||||
// given
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(nextIdAsString());
|
||||
sampleEntity.setMessage("hello world");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
|
||||
@Test // #2418
|
||||
void defaultStringMatcherShouldWork() {
|
||||
// given
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(nextIdAsString());
|
||||
sampleEntity.setMessage("hello world");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(nextIdAsString());
|
||||
sampleEntity2.setMessage("bye world");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(nextIdAsString());
|
||||
sampleEntity2.setMessage("bye world");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
SampleEntity sampleEntity3 = new SampleEntity();
|
||||
sampleEntity3.setDocumentId(nextIdAsString());
|
||||
sampleEntity3.setMessage("hola mundo");
|
||||
sampleEntity3.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity3 = new SampleEntity();
|
||||
sampleEntity3.setDocumentId(nextIdAsString());
|
||||
sampleEntity3.setMessage("hola mundo");
|
||||
sampleEntity3.setVersion(System.currentTimeMillis());
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2, sampleEntity3)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextCount(3L) //
|
||||
.verifyComplete();
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2, sampleEntity3)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextCount(3L) //
|
||||
.verifyComplete();
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setMessage("h");
|
||||
repository
|
||||
.findAll(Example.of(probe,
|
||||
ExampleMatcher.matching().withMatcher("message",
|
||||
ExampleMatcher.GenericPropertyMatcher.of(ExampleMatcher.StringMatcher.STARTING))))
|
||||
// then
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextSequence(List.of(sampleEntity, sampleEntity3)) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setMessage("hello world");
|
||||
repository
|
||||
.findAll(Example.of(probe,
|
||||
ExampleMatcher.matching().withMatcher("message",
|
||||
ExampleMatcher.GenericPropertyMatcher.of(ExampleMatcher.StringMatcher.DEFAULT))))
|
||||
// then
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(sampleEntity) //
|
||||
.verifyComplete();
|
||||
}
|
||||
@Test // #2418
|
||||
void endingStringMatcherShouldWork() {
|
||||
// given
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(nextIdAsString());
|
||||
sampleEntity.setMessage("hello world");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
|
||||
@Test // #2418
|
||||
void exactStringMatcherShouldWork() {
|
||||
// given
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(nextIdAsString());
|
||||
sampleEntity.setMessage("hello world");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(nextIdAsString());
|
||||
sampleEntity2.setMessage("bye world");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(nextIdAsString());
|
||||
sampleEntity2.setMessage("bye world");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
SampleEntity sampleEntity3 = new SampleEntity();
|
||||
sampleEntity3.setDocumentId(nextIdAsString());
|
||||
sampleEntity3.setMessage("hola mundo");
|
||||
sampleEntity3.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity3 = new SampleEntity();
|
||||
sampleEntity3.setDocumentId(nextIdAsString());
|
||||
sampleEntity3.setMessage("hola mundo");
|
||||
sampleEntity3.setVersion(System.currentTimeMillis());
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2, sampleEntity3)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextCount(3L) //
|
||||
.verifyComplete();
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2, sampleEntity3)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextCount(3L) //
|
||||
.verifyComplete();
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setMessage("world");
|
||||
repository
|
||||
.findAll(Example.of(probe,
|
||||
ExampleMatcher.matching().withMatcher("message",
|
||||
ExampleMatcher.GenericPropertyMatcher.of(ExampleMatcher.StringMatcher.ENDING))))
|
||||
// then
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextSequence(List.of(sampleEntity, sampleEntity2)) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setMessage("bye world");
|
||||
repository
|
||||
.findAll(Example.of(probe,
|
||||
ExampleMatcher.matching().withMatcher("message",
|
||||
ExampleMatcher.GenericPropertyMatcher.of(ExampleMatcher.StringMatcher.EXACT))))
|
||||
// then
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(sampleEntity2) //
|
||||
.verifyComplete();
|
||||
}
|
||||
@Test // #2418
|
||||
void regexStringMatcherShouldWork() {
|
||||
// given
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(nextIdAsString());
|
||||
sampleEntity.setMessage("hello world");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
|
||||
@Test // #2418
|
||||
void startingStringMatcherShouldWork() {
|
||||
// given
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(nextIdAsString());
|
||||
sampleEntity.setMessage("hello world");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(nextIdAsString());
|
||||
sampleEntity2.setMessage("bye world");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(nextIdAsString());
|
||||
sampleEntity2.setMessage("bye world");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
SampleEntity sampleEntity3 = new SampleEntity();
|
||||
sampleEntity3.setDocumentId(nextIdAsString());
|
||||
sampleEntity3.setMessage("hola mundo");
|
||||
sampleEntity3.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity3 = new SampleEntity();
|
||||
sampleEntity3.setDocumentId(nextIdAsString());
|
||||
sampleEntity3.setMessage("hola mundo");
|
||||
sampleEntity3.setVersion(System.currentTimeMillis());
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2, sampleEntity3)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextCount(3L) //
|
||||
.verifyComplete();
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setMessage("h");
|
||||
repository
|
||||
.findAll(Example.of(probe,
|
||||
ExampleMatcher.matching().withMatcher("message",
|
||||
ExampleMatcher.GenericPropertyMatcher.of(ExampleMatcher.StringMatcher.STARTING))))
|
||||
// then
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextSequence(List.of(sampleEntity, sampleEntity3)) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // #2418
|
||||
void endingStringMatcherShouldWork() {
|
||||
// given
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(nextIdAsString());
|
||||
sampleEntity.setMessage("hello world");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(nextIdAsString());
|
||||
sampleEntity2.setMessage("bye world");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity3 = new SampleEntity();
|
||||
sampleEntity3.setDocumentId(nextIdAsString());
|
||||
sampleEntity3.setMessage("hola mundo");
|
||||
sampleEntity3.setVersion(System.currentTimeMillis());
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2, sampleEntity3)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextCount(3L) //
|
||||
.verifyComplete();
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setMessage("world");
|
||||
repository
|
||||
.findAll(Example.of(probe,
|
||||
ExampleMatcher.matching().withMatcher("message",
|
||||
ExampleMatcher.GenericPropertyMatcher.of(ExampleMatcher.StringMatcher.ENDING))))
|
||||
// then
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextSequence(List.of(sampleEntity, sampleEntity2)) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // #2418
|
||||
void regexStringMatcherShouldWork() {
|
||||
// given
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setDocumentId(nextIdAsString());
|
||||
sampleEntity.setMessage("hello world");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setDocumentId(nextIdAsString());
|
||||
sampleEntity2.setMessage("bye world");
|
||||
sampleEntity2.setVersion(System.currentTimeMillis());
|
||||
|
||||
SampleEntity sampleEntity3 = new SampleEntity();
|
||||
sampleEntity3.setDocumentId(nextIdAsString());
|
||||
sampleEntity3.setMessage("hola mundo");
|
||||
sampleEntity3.setVersion(System.currentTimeMillis());
|
||||
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2, sampleEntity3)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextCount(3L) //
|
||||
.verifyComplete();
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setMessage("[(hello)(hola)].*");
|
||||
repository
|
||||
.findAll(Example.of(probe,
|
||||
ExampleMatcher.matching().withMatcher("message",
|
||||
ExampleMatcher.GenericPropertyMatcher.of(ExampleMatcher.StringMatcher.REGEX))))
|
||||
// then
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextSequence(List.of(sampleEntity, sampleEntity3)) //
|
||||
.verifyComplete();
|
||||
}
|
||||
repository.saveAll(List.of(sampleEntity, sampleEntity2, sampleEntity3)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextCount(3L) //
|
||||
.verifyComplete();
|
||||
|
||||
// when
|
||||
SampleEntity probe = new SampleEntity();
|
||||
probe.setMessage("[(hello)(hola)].*");
|
||||
repository
|
||||
.findAll(Example.of(probe,
|
||||
ExampleMatcher.matching().withMatcher("message",
|
||||
ExampleMatcher.GenericPropertyMatcher.of(ExampleMatcher.StringMatcher.REGEX))))
|
||||
// then
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextSequence(List.of(sampleEntity, sampleEntity3)) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Document(indexName = "#{@indexNameProvider.indexName()}")
|
||||
|
||||
Binary file not shown.
-1
@@ -1 +0,0 @@
|
||||
f6bbf833798e7af0055b94865a46440e
|
||||
-1
@@ -1 +0,0 @@
|
||||
59ddfc2b714be7918808eacecc5739b8d277e60e
|
||||
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>999999</version>
|
||||
</project>
|
||||
-1
@@ -1 +0,0 @@
|
||||
63317ccd46b6663ff35cb142e05dce10
|
||||
-1
@@ -1 +0,0 @@
|
||||
db353983c68ade94ae7e08acfacc0fc21ed8b64b
|
||||
@@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<metadata>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<versioning>
|
||||
<release>999999</release>
|
||||
<versions>
|
||||
<version>999999</version>
|
||||
</versions>
|
||||
<lastUpdated>20210321155422</lastUpdated>
|
||||
</versioning>
|
||||
</metadata>
|
||||
@@ -1 +0,0 @@
|
||||
998d3b8876980a3ef5a90adc982cc727
|
||||
@@ -1 +0,0 @@
|
||||
f4090a49c6eec680c075130b68bf8ee48aac4e94
|
||||
@@ -15,7 +15,7 @@
|
||||
#
|
||||
#
|
||||
sde.testcontainers.image-name=docker.elastic.co/elasticsearch/elasticsearch
|
||||
sde.testcontainers.image-version=8.6.1
|
||||
sde.testcontainers.image-version=8.7.0
|
||||
#
|
||||
#
|
||||
# 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
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
#
|
||||
# properties defining the image, these are not passed to the container on startup
|
||||
#
|
||||
sde.testcontainers.image-name=opensearchproject/opensearch
|
||||
sde.testcontainers.image-version=1.0.0
|
||||
#
|
||||
#
|
||||
# Opensearch as default has TLS and Basic auth enabled, we do not want this here, Testcontainers cannot ignore self signed certificates
|
||||
#
|
||||
plugins.security.disabled=true
|
||||
Reference in New Issue
Block a user