mirror of
https://github.com/spring-projects/spring-data-elasticsearch.git
synced 2025-07-03 09:12:12 +00:00
Compare commits
64 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
c68f607374 | ||
|
fb9c70c51b | ||
|
0c4a641163 | ||
|
d7abbc719f | ||
|
bd99c90de1 | ||
|
b5ad00bccf | ||
|
01f39d6807 | ||
|
19970bacc6 | ||
|
d7aed4a8cc | ||
|
b708fc10db | ||
|
33c253b071 | ||
|
6bb18b9a0a | ||
|
e5252da066 | ||
|
a49b1b52a3 | ||
|
7982ff7986 | ||
|
1c9441a1b4 | ||
|
e0cc849952 | ||
|
1b50013fc2 | ||
|
5418ef9e03 | ||
|
8d81e499bc | ||
|
e457b1678b | ||
|
6c34dc53f3 | ||
|
85b6acebb2 | ||
|
00155c2b31 | ||
|
d0020be57d | ||
|
20a6140fe9 | ||
|
cdb48c8226 | ||
|
493476567a | ||
|
a7c148653f | ||
|
3092db9e7d | ||
|
d8917f1cb1 | ||
|
cc533b25f1 | ||
|
c5231d879d | ||
|
950ca0fc2a | ||
|
95a86f558b | ||
|
8117e5a174 | ||
|
3a9a959918 | ||
|
a179dd0643 | ||
|
310ea07c6f | ||
|
34a277cd7d | ||
|
878dc029ec | ||
|
c931812c6a | ||
|
c514e020b8 | ||
|
31a4ad715f | ||
|
03efe1b910 | ||
|
9d5d2efb40 | ||
|
b7266961d9 | ||
|
d96cd02572 | ||
|
ceb0225850 | ||
|
5c59f73e00 | ||
|
44b1c9e848 | ||
|
1770f98a74 | ||
|
bad0a80313 | ||
|
92dd6e8599 | ||
|
c793be8ab4 | ||
|
07ae79f9ce | ||
|
47c84b84af | ||
|
5ba1e5dc77 | ||
|
5ddcd55942 | ||
|
be4a77ad21 | ||
|
7fa3cb74a1 | ||
|
ba9edf8ec8 | ||
|
e4a39ae285 | ||
|
7392222793 |
@ -8,7 +8,3 @@
|
|||||||
--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
|
--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
|
||||||
--add-opens jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED
|
--add-opens jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED
|
||||||
--add-opens jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED
|
--add-opens jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED
|
||||||
--add-opens=java.base/java.util=ALL-UNNAMED
|
|
||||||
--add-opens=java.base/java.lang.reflect=ALL-UNNAMED
|
|
||||||
--add-opens=java.base/java.text=ALL-UNNAMED
|
|
||||||
--add-opens=java.desktop/java.awt.font=ALL-UNNAMED
|
|
||||||
|
2
.mvn/wrapper/maven-wrapper.properties
vendored
2
.mvn/wrapper/maven-wrapper.properties
vendored
@ -1,3 +1,3 @@
|
|||||||
#Thu Nov 07 09:47:28 CET 2024
|
#Thu Nov 07 09:49:32 CET 2024
|
||||||
wrapperUrl=https\://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
|
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.9.9/apache-maven-3.9.9-bin.zip
|
distributionUrl=https\://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip
|
||||||
|
2
Jenkinsfile
vendored
2
Jenkinsfile
vendored
@ -9,7 +9,7 @@ pipeline {
|
|||||||
|
|
||||||
triggers {
|
triggers {
|
||||||
pollSCM 'H/10 * * * *'
|
pollSCM 'H/10 * * * *'
|
||||||
upstream(upstreamProjects: "spring-data-commons/main", threshold: hudson.model.Result.SUCCESS)
|
upstream(upstreamProjects: "spring-data-commons/3.3.x", threshold: hudson.model.Result.SUCCESS)
|
||||||
}
|
}
|
||||||
|
|
||||||
options {
|
options {
|
||||||
|
@ -62,7 +62,7 @@ public class MyService {
|
|||||||
|
|
||||||
=== Using the RestClient
|
=== Using the RestClient
|
||||||
|
|
||||||
Please check the https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/#elasticsearch.clients.configuration[official documentation].
|
Please check the [official documentation](https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/#elasticsearch.clients.configuration).
|
||||||
|
|
||||||
=== Maven configuration
|
=== Maven configuration
|
||||||
|
|
||||||
@ -168,7 +168,7 @@ Building the documentation builds also the project without running tests.
|
|||||||
$ ./mvnw clean install -Pantora
|
$ ./mvnw clean install -Pantora
|
||||||
----
|
----
|
||||||
|
|
||||||
The generated documentation is available from `target/site/index.html`.
|
The generated documentation is available from `target/antora/site/index.html`.
|
||||||
|
|
||||||
== Examples
|
== Examples
|
||||||
|
|
||||||
|
@ -1,20 +1,24 @@
|
|||||||
# Java versions
|
# Java versions
|
||||||
java.main.tag=24.0.1_9-jdk-noble
|
java.main.tag=17.0.13_11-jdk-focal
|
||||||
java.next.tag=24.0.1_9-jdk-noble
|
java.next.tag=22.0.2_9-jdk-jammy
|
||||||
|
|
||||||
# Docker container images - standard
|
# Docker container images - standard
|
||||||
docker.java.main.image=library/eclipse-temurin:${java.main.tag}
|
docker.java.main.image=library/eclipse-temurin:${java.main.tag}
|
||||||
docker.java.next.image=library/eclipse-temurin:${java.next.tag}
|
docker.java.next.image=library/eclipse-temurin:${java.next.tag}
|
||||||
|
|
||||||
# Supported versions of MongoDB
|
# Supported versions of MongoDB
|
||||||
docker.mongodb.6.0.version=6.0.23
|
docker.mongodb.4.4.version=4.4.25
|
||||||
docker.mongodb.7.0.version=7.0.20
|
docker.mongodb.5.0.version=5.0.21
|
||||||
docker.mongodb.8.0.version=8.0.9
|
docker.mongodb.6.0.version=6.0.10
|
||||||
|
docker.mongodb.7.0.version=7.0.2
|
||||||
|
|
||||||
# Supported versions of Redis
|
# Supported versions of Redis
|
||||||
docker.redis.6.version=6.2.13
|
docker.redis.6.version=6.2.13
|
||||||
docker.redis.7.version=7.2.4
|
docker.redis.7.version=7.2.4
|
||||||
|
|
||||||
|
# Supported versions of Cassandra
|
||||||
|
docker.cassandra.3.version=3.11.16
|
||||||
|
|
||||||
# Docker environment settings
|
# Docker environment settings
|
||||||
docker.java.inside.basic=-v $HOME:/tmp/jenkins-home
|
docker.java.inside.basic=-v $HOME:/tmp/jenkins-home
|
||||||
docker.java.inside.docker=-u root -v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker -v $HOME:/tmp/jenkins-home
|
docker.java.inside.docker=-u root -v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker -v $HOME:/tmp/jenkins-home
|
||||||
|
50
pom.xml
50
pom.xml
@ -5,12 +5,12 @@
|
|||||||
|
|
||||||
<groupId>org.springframework.data</groupId>
|
<groupId>org.springframework.data</groupId>
|
||||||
<artifactId>spring-data-elasticsearch</artifactId>
|
<artifactId>spring-data-elasticsearch</artifactId>
|
||||||
<version>6.0.0-SNAPSHOT</version>
|
<version>5.3.10</version>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.data.build</groupId>
|
<groupId>org.springframework.data.build</groupId>
|
||||||
<artifactId>spring-data-parent</artifactId>
|
<artifactId>spring-data-parent</artifactId>
|
||||||
<version>4.0.0-SNAPSHOT</version>
|
<version>3.3.10</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<name>Spring Data Elasticsearch</name>
|
<name>Spring Data Elasticsearch</name>
|
||||||
@ -18,16 +18,16 @@
|
|||||||
<url>https://github.com/spring-projects/spring-data-elasticsearch</url>
|
<url>https://github.com/spring-projects/spring-data-elasticsearch</url>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<springdata.commons>4.0.0-SNAPSHOT</springdata.commons>
|
<springdata.commons>3.3.10</springdata.commons>
|
||||||
|
|
||||||
<!-- version of the ElasticsearchClient -->
|
<!-- version of the ElasticsearchClient -->
|
||||||
<elasticsearch-java>9.0.3</elasticsearch-java>
|
<elasticsearch-java>8.13.4</elasticsearch-java>
|
||||||
|
|
||||||
<hoverfly>0.19.0</hoverfly>
|
<hoverfly>0.14.4</hoverfly>
|
||||||
<log4j>2.23.1</log4j>
|
<log4j>2.18.0</log4j>
|
||||||
<jsonassert>1.5.3</jsonassert>
|
<jsonassert>1.5.1</jsonassert>
|
||||||
<testcontainers>1.20.0</testcontainers>
|
<testcontainers>1.18.0</testcontainers>
|
||||||
<wiremock>3.9.1</wiremock>
|
<wiremock>2.35.1</wiremock>
|
||||||
|
|
||||||
<java-module-name>spring.data.elasticsearch</java-module-name>
|
<java-module-name>spring.data.elasticsearch</java-module-name>
|
||||||
|
|
||||||
@ -131,11 +131,9 @@
|
|||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- the old RestCLient is an optional dependency for user that still want to use it-->
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.elasticsearch.client</groupId>
|
<groupId>org.elasticsearch.client</groupId>
|
||||||
<artifactId>elasticsearch-rest-client</artifactId>
|
<artifactId>elasticsearch-rest-client</artifactId> <!-- is Apache 2-->
|
||||||
<version>${elasticsearch-java}</version>
|
<version>${elasticsearch-java}</version>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
@ -143,14 +141,6 @@
|
|||||||
<artifactId>commons-logging</artifactId>
|
<artifactId>commons-logging</artifactId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.querydsl</groupId>
|
|
||||||
<artifactId>querydsl-core</artifactId>
|
|
||||||
<version>${querydsl}</version>
|
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Jackson JSON Mapper -->
|
<!-- Jackson JSON Mapper -->
|
||||||
@ -265,8 +255,8 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.wiremock</groupId>
|
<groupId>com.github.tomakehurst</groupId>
|
||||||
<artifactId>wiremock</artifactId>
|
<artifactId>wiremock-jre8</artifactId>
|
||||||
<version>${wiremock}</version>
|
<version>${wiremock}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
@ -471,20 +461,8 @@
|
|||||||
</profiles>
|
</profiles>
|
||||||
|
|
||||||
<repositories>
|
<repositories>
|
||||||
<repository>
|
|
||||||
<id>spring-snapshot</id>
|
|
||||||
<url>https://repo.spring.io/snapshot</url>
|
|
||||||
<snapshots>
|
|
||||||
<enabled>true</enabled>
|
|
||||||
</snapshots>
|
|
||||||
<releases>
|
|
||||||
<enabled>false</enabled>
|
|
||||||
</releases>
|
|
||||||
</repository>
|
|
||||||
<repository>
|
|
||||||
<id>spring-milestone</id>
|
|
||||||
<url>https://repo.spring.io/milestone</url>
|
|
||||||
</repository>
|
|
||||||
</repositories>
|
</repositories>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
@ -17,7 +17,7 @@ content:
|
|||||||
- url: https://github.com/spring-projects/spring-data-commons
|
- url: https://github.com/spring-projects/spring-data-commons
|
||||||
# Refname matching:
|
# Refname matching:
|
||||||
# https://docs.antora.org/antora/latest/playbook/content-refname-matching/
|
# https://docs.antora.org/antora/latest/playbook/content-refname-matching/
|
||||||
branches: [ main, 3.4.x, 3.3.x ]
|
branches: [ main, 3.2.x ]
|
||||||
start_path: src/main/antora
|
start_path: src/main/antora
|
||||||
asciidoc:
|
asciidoc:
|
||||||
attributes:
|
attributes:
|
||||||
|
@ -10,10 +10,6 @@
|
|||||||
*** xref:migration-guides/migration-guide-5.0-5.1.adoc[]
|
*** xref:migration-guides/migration-guide-5.0-5.1.adoc[]
|
||||||
*** xref:migration-guides/migration-guide-5.1-5.2.adoc[]
|
*** xref:migration-guides/migration-guide-5.1-5.2.adoc[]
|
||||||
*** xref:migration-guides/migration-guide-5.2-5.3.adoc[]
|
*** xref:migration-guides/migration-guide-5.2-5.3.adoc[]
|
||||||
*** xref:migration-guides/migration-guide-5.3-5.4.adoc[]
|
|
||||||
*** xref:migration-guides/migration-guide-5.4-5.5.adoc[]
|
|
||||||
*** xref:migration-guides/migration-guide-5.5-6.0.adoc[]
|
|
||||||
|
|
||||||
|
|
||||||
* xref:elasticsearch.adoc[]
|
* xref:elasticsearch.adoc[]
|
||||||
** xref:elasticsearch/clients.adoc[]
|
** xref:elasticsearch/clients.adoc[]
|
||||||
|
@ -10,7 +10,7 @@ In order for the auditing code to be able to decide whether an entity instance i
|
|||||||
----
|
----
|
||||||
package org.springframework.data.domain;
|
package org.springframework.data.domain;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
public interface Persistable<ID> {
|
public interface Persistable<ID> {
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@ -6,10 +6,10 @@ This chapter illustrates configuration and usage of supported Elasticsearch clie
|
|||||||
Spring Data Elasticsearch operates upon an Elasticsearch client (provided by Elasticsearch client libraries) that is connected to a single Elasticsearch node or a cluster.
|
Spring Data Elasticsearch operates upon an Elasticsearch client (provided by Elasticsearch client libraries) that is connected to a single Elasticsearch node or a cluster.
|
||||||
Although the Elasticsearch Client can be used directly to work with the cluster, applications using Spring Data Elasticsearch normally use the higher level abstractions of xref:elasticsearch/template.adoc[Elasticsearch Operations] and xref:elasticsearch/repositories/elasticsearch-repositories.adoc[Elasticsearch Repositories].
|
Although the Elasticsearch Client can be used directly to work with the cluster, applications using Spring Data Elasticsearch normally use the higher level abstractions of xref:elasticsearch/template.adoc[Elasticsearch Operations] and xref:elasticsearch/repositories/elasticsearch-repositories.adoc[Elasticsearch Repositories].
|
||||||
|
|
||||||
[[elasticsearch.clients.rest5client]]
|
[[elasticsearch.clients.restclient]]
|
||||||
== Imperative Rest5Client
|
== Imperative Rest Client
|
||||||
|
|
||||||
To use the imperative (non-reactive) Rest5Client, a configuration bean must be configured like this:
|
To use the imperative (non-reactive) client, a configuration bean must be configured like this:
|
||||||
|
|
||||||
====
|
====
|
||||||
[source,java]
|
[source,java]
|
||||||
@ -31,81 +31,7 @@ public class MyClientConfig extends ElasticsearchConfiguration {
|
|||||||
<.> for a detailed description of the builder methods see xref:elasticsearch/clients.adoc#elasticsearch.clients.configuration[Client Configuration]
|
<.> for a detailed description of the builder methods see xref:elasticsearch/clients.adoc#elasticsearch.clients.configuration[Client Configuration]
|
||||||
====
|
====
|
||||||
|
|
||||||
The javadoc:org.springframework.data.elasticsearch.client.elc.ElasticsearchConfiguration[] class allows further configuration by overriding for example the `jsonpMapper()` or `transportOptions()` methods.
|
The javadoc:org.springframework.data.elasticsearch.client.elc.ElasticsearchConfiguration[]] class allows further configuration by overriding for example the `jsonpMapper()` or `transportOptions()` methods.
|
||||||
|
|
||||||
|
|
||||||
The following beans can then be injected in other Spring components:
|
|
||||||
|
|
||||||
====
|
|
||||||
[source,java]
|
|
||||||
----
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;@Autowired
|
|
||||||
ElasticsearchOperations operations; <.>
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
ElasticsearchClient elasticsearchClient; <.>
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
Rest5Client rest5Client; <.>
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
JsonpMapper jsonpMapper; <.>
|
|
||||||
----
|
|
||||||
|
|
||||||
<.> an implementation of javadoc:org.springframework.data.elasticsearch.core.ElasticsearchOperations[]
|
|
||||||
<.> the `co.elastic.clients.elasticsearch.ElasticsearchClient` that is used.
|
|
||||||
<.> the low level `Rest5Client` from the Elasticsearch libraries
|
|
||||||
<.> the `JsonpMapper` user by the Elasticsearch `Transport`
|
|
||||||
====
|
|
||||||
|
|
||||||
Basically one should just use the javadoc:org.springframework.data.elasticsearch.core.ElasticsearchOperations[] to interact with the Elasticsearch cluster.
|
|
||||||
When using repositories, this instance is used under the hood as well.
|
|
||||||
|
|
||||||
[[elasticsearch.clients.restclient]]
|
|
||||||
== Deprecated Imperative RestClient
|
|
||||||
|
|
||||||
To use the imperative (non-reactive) RestClient - deprecated since version 6 - , the following dependency needs to be added, adapt the correct version. The exclusion is needed in a Spring Boot application:
|
|
||||||
====
|
|
||||||
[source,xml]
|
|
||||||
----
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.elasticsearch.client</groupId>
|
|
||||||
<artifactId>elasticsearch-rest-client</artifactId>
|
|
||||||
<version>${elasticsearch-client.version}</version>
|
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>commons-logging</groupId>
|
|
||||||
<artifactId>commons-logging</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
----
|
|
||||||
====
|
|
||||||
|
|
||||||
The configuration bean must be configured like this:
|
|
||||||
|
|
||||||
====
|
|
||||||
[source,java]
|
|
||||||
----
|
|
||||||
import org.springframework.data.elasticsearch.client.elc.ElasticsearchLegacyRestClientConfiguration;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
public class MyClientConfig extends ElasticsearchLegacyRestClientConfiguration {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ClientConfiguration clientConfiguration() {
|
|
||||||
return ClientConfiguration.builder() <.>
|
|
||||||
.connectedTo("localhost:9200")
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
----
|
|
||||||
|
|
||||||
<.> for a detailed description of the builder methods see xref:elasticsearch/clients.adoc#elasticsearch.clients.configuration[Client Configuration]
|
|
||||||
====
|
|
||||||
|
|
||||||
The javadoc:org.springframework.data.elasticsearch.client.elc.ElasticsearchConfiguration[] class allows further configuration by overriding for example the `jsonpMapper()` or `transportOptions()` methods.
|
|
||||||
|
|
||||||
|
|
||||||
The following beans can then be injected in other Spring components:
|
The following beans can then be injected in other Spring components:
|
||||||
@ -135,8 +61,8 @@ JsonpMapper jsonpMapper; <.>
|
|||||||
Basically one should just use the javadoc:org.springframework.data.elasticsearch.core.ElasticsearchOperations[] to interact with the Elasticsearch cluster.
|
Basically one should just use the javadoc:org.springframework.data.elasticsearch.core.ElasticsearchOperations[] to interact with the Elasticsearch cluster.
|
||||||
When using repositories, this instance is used under the hood as well.
|
When using repositories, this instance is used under the hood as well.
|
||||||
|
|
||||||
[[elasticsearch.clients.reactiverest5client]]
|
[[elasticsearch.clients.reactiverestclient]]
|
||||||
== Reactive Rest5Client
|
== Reactive Rest Client
|
||||||
|
|
||||||
When working with the reactive stack, the configuration must be derived from a different class:
|
When working with the reactive stack, the configuration must be derived from a different class:
|
||||||
|
|
||||||
@ -173,65 +99,6 @@ ReactiveElasticsearchOperations operations; <.>
|
|||||||
@Autowired
|
@Autowired
|
||||||
ReactiveElasticsearchClient elasticsearchClient; <.>
|
ReactiveElasticsearchClient elasticsearchClient; <.>
|
||||||
|
|
||||||
@Autowired
|
|
||||||
Rest5Client rest5Client; <.>
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
JsonpMapper jsonpMapper; <.>
|
|
||||||
----
|
|
||||||
|
|
||||||
the following can be injected:
|
|
||||||
|
|
||||||
<.> an implementation of javadoc:org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations[]
|
|
||||||
<.> the `org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchClient` that is used.
|
|
||||||
This is a reactive implementation based on the Elasticsearch client implementation.
|
|
||||||
<.> the low level `RestClient` from the Elasticsearch libraries
|
|
||||||
<.> the `JsonpMapper` user by the Elasticsearch `Transport`
|
|
||||||
====
|
|
||||||
|
|
||||||
Basically one should just use the javadoc:org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations[] to interact with the Elasticsearch cluster.
|
|
||||||
When using repositories, this instance is used under the hood as well.
|
|
||||||
|
|
||||||
[[elasticsearch.clients.reactiverestclient]]
|
|
||||||
== Deprecated Reactive RestClient
|
|
||||||
|
|
||||||
See the section above for the imperative code to use the deprecated RestClient for the necessary dependencies to include.
|
|
||||||
|
|
||||||
When working with the reactive stack, the configuration must be derived from a different class:
|
|
||||||
|
|
||||||
====
|
|
||||||
[source,java]
|
|
||||||
----
|
|
||||||
import org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchLegacyRestClientConfiguration;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
public class MyClientConfig extends ReactiveElasticsearchLegacyRestClientConfiguration {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ClientConfiguration clientConfiguration() {
|
|
||||||
return ClientConfiguration.builder() <.>
|
|
||||||
.connectedTo("localhost:9200")
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
----
|
|
||||||
|
|
||||||
<.> for a detailed description of the builder methods see xref:elasticsearch/clients.adoc#elasticsearch.clients.configuration[Client Configuration]
|
|
||||||
====
|
|
||||||
|
|
||||||
The javadoc:org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchConfiguration[] class allows further configuration by overriding for example the `jsonpMapper()` or `transportOptions()` methods.
|
|
||||||
|
|
||||||
The following beans can then be injected in other Spring components:
|
|
||||||
|
|
||||||
====
|
|
||||||
[source,java]
|
|
||||||
----
|
|
||||||
@Autowired
|
|
||||||
ReactiveElasticsearchOperations operations; <.>
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
ReactiveElasticsearchClient elasticsearchClient; <.>
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
RestClient restClient; <.>
|
RestClient restClient; <.>
|
||||||
|
|
||||||
@ -316,25 +183,8 @@ In the case this is not enough, the user can add callback functions by using the
|
|||||||
|
|
||||||
The following callbacks are provided:
|
The following callbacks are provided:
|
||||||
|
|
||||||
[[elasticsearch.clients.configuration.callbacks.rest5]]
|
|
||||||
==== Configuration of the low level Elasticsearch `Rest5Client`:
|
|
||||||
|
|
||||||
This callback provides a `org.elasticsearch.client.RestClientBuilder` that can be used to configure the Elasticsearch
|
|
||||||
`RestClient`:
|
|
||||||
====
|
|
||||||
[source,java]
|
|
||||||
----
|
|
||||||
ClientConfiguration.builder()
|
|
||||||
.connectedTo("localhost:9200", "localhost:9291")
|
|
||||||
.withClientConfigurer(Rest5Clients.ElasticsearchRest5ClientConfigurationCallback.from(restClientBuilder -> {
|
|
||||||
// configure the Elasticsearch Rest5Client
|
|
||||||
return restClientBuilder;
|
|
||||||
}))
|
|
||||||
.build();
|
|
||||||
----
|
|
||||||
====
|
|
||||||
[[elasticsearch.clients.configuration.callbacks.rest]]
|
[[elasticsearch.clients.configuration.callbacks.rest]]
|
||||||
==== Configuration of the deprecated low level Elasticsearch `RestClient`:
|
==== Configuration of the low level Elasticsearch `RestClient`:
|
||||||
|
|
||||||
This callback provides a `org.elasticsearch.client.RestClientBuilder` that can be used to configure the Elasticsearch
|
This callback provides a `org.elasticsearch.client.RestClientBuilder` that can be used to configure the Elasticsearch
|
||||||
`RestClient`:
|
`RestClient`:
|
||||||
@ -343,7 +193,7 @@ This callback provides a `org.elasticsearch.client.RestClientBuilder` that can b
|
|||||||
----
|
----
|
||||||
ClientConfiguration.builder()
|
ClientConfiguration.builder()
|
||||||
.connectedTo("localhost:9200", "localhost:9291")
|
.connectedTo("localhost:9200", "localhost:9291")
|
||||||
.withClientConfigurer(RestClients.ElasticsearchRestClientConfigurationCallback.from(restClientBuilder -> {
|
.withClientConfigurer(ElasticsearchClients.ElasticsearchRestClientConfigurationCallback.from(restClientBuilder -> {
|
||||||
// configure the Elasticsearch RestClient
|
// configure the Elasticsearch RestClient
|
||||||
return restClientBuilder;
|
return restClientBuilder;
|
||||||
}))
|
}))
|
||||||
@ -351,29 +201,10 @@ ClientConfiguration.builder()
|
|||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
[[elasticsearch.clients.configurationcallbacks.httpasync5]]
|
|
||||||
==== Configuration of the HttpAsyncClient used by the low level Elasticsearch `Rest5Client`:
|
|
||||||
|
|
||||||
This callback provides a `org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder` to configure the HttpClient that is
|
|
||||||
used by the `Rest5Client`.
|
|
||||||
|
|
||||||
====
|
|
||||||
[source,java]
|
|
||||||
----
|
|
||||||
ClientConfiguration.builder()
|
|
||||||
.connectedTo("localhost:9200", "localhost:9291")
|
|
||||||
.withClientConfigurer(Rest5Clients.ElasticsearchHttpClientConfigurationCallback.from(httpAsyncClientBuilder -> {
|
|
||||||
// configure the HttpAsyncClient
|
|
||||||
return httpAsyncClientBuilder;
|
|
||||||
}))
|
|
||||||
.build();
|
|
||||||
----
|
|
||||||
====
|
|
||||||
|
|
||||||
[[elasticsearch.clients.configurationcallbacks.httpasync]]
|
[[elasticsearch.clients.configurationcallbacks.httpasync]]
|
||||||
==== Configuration of the HttpAsyncClient used by the deprecated low level Elasticsearch `RestClient`:
|
==== Configuration of the HttpAsyncClient used by the low level Elasticsearch `RestClient`:
|
||||||
|
|
||||||
This callback provides a `org.apache.http.impl.nio.client.HttpAsyncClientBuilder` to configure the HttpClient that is
|
This callback provides a `org.apache.http.impl.nio.client.HttpAsyncClientBuilder` to configure the HttpCLient that is
|
||||||
used by the `RestClient`.
|
used by the `RestClient`.
|
||||||
|
|
||||||
====
|
====
|
||||||
@ -381,7 +212,7 @@ used by the `RestClient`.
|
|||||||
----
|
----
|
||||||
ClientConfiguration.builder()
|
ClientConfiguration.builder()
|
||||||
.connectedTo("localhost:9200", "localhost:9291")
|
.connectedTo("localhost:9200", "localhost:9291")
|
||||||
.withClientConfigurer(RestClients.ElasticsearchHttpClientConfigurationCallback.from(httpAsyncClientBuilder -> {
|
.withClientConfigurer(ElasticsearchClients.ElasticsearchHttpClientConfigurationCallback.from(httpAsyncClientBuilder -> {
|
||||||
// configure the HttpAsyncClient
|
// configure the HttpAsyncClient
|
||||||
return httpAsyncClientBuilder;
|
return httpAsyncClientBuilder;
|
||||||
}))
|
}))
|
||||||
|
@ -1,29 +1,10 @@
|
|||||||
[[new-features]]
|
[[new-features]]
|
||||||
= What's new
|
= What's new
|
||||||
|
|
||||||
[[new-features.6-0-0]]
|
[[new-features.5-3-1]]
|
||||||
== New in Spring Data Elasticsearch 6.0
|
== New in Spring Data Elasticsearch 5.3.1
|
||||||
|
|
||||||
* Upgarde to Spring 7
|
* Upgrade to Elasticsearch 8.13.4.
|
||||||
* Switch to jspecify nullability annotations
|
|
||||||
* Upgrade to Elasticsearch 9.0.3
|
|
||||||
* Use the new Elasticsearch Rest5Client as default
|
|
||||||
|
|
||||||
|
|
||||||
[[new-features.5-5-0]]
|
|
||||||
== New in Spring Data Elasticsearch 5.5
|
|
||||||
|
|
||||||
* Upgrade to Elasticsearch 8.18.1.
|
|
||||||
* Add support for the `@SearchTemplateQuery` annotation on repository methods.
|
|
||||||
* Scripted field properties of type collection can be populated from scripts returning arrays.
|
|
||||||
|
|
||||||
[[new-features.5-4-0]]
|
|
||||||
== New in Spring Data Elasticsearch 5.4
|
|
||||||
|
|
||||||
* Upgrade to Elasticsearch 8.15.3.
|
|
||||||
* Allow to customize the mapped type name for `@InnerField` and `@Field` annotations.
|
|
||||||
* Support for Elasticsearch SQL.
|
|
||||||
* Add support for retrieving request executionDuration.
|
|
||||||
|
|
||||||
[[new-features.5-3-0]]
|
[[new-features.5-3-0]]
|
||||||
== New in Spring Data Elasticsearch 5.3
|
== New in Spring Data Elasticsearch 5.3
|
||||||
|
@ -365,8 +365,6 @@ operations.putScript( <.>
|
|||||||
|
|
||||||
To use a search template in a search query, Spring Data Elasticsearch provides the `SearchTemplateQuery`, an implementation of the `org.springframework.data.elasticsearch.core.query.Query` interface.
|
To use a search template in a search query, Spring Data Elasticsearch provides the `SearchTemplateQuery`, an implementation of the `org.springframework.data.elasticsearch.core.query.Query` interface.
|
||||||
|
|
||||||
NOTE: Although `SearchTemplateQuery` is an implementation of the `Query` interface, not all of the functionality provided by the base class is available for a `SearchTemplateQuery` like setting a `Pageable` or a `Sort`. Values for this functionality must be added to the stored script like shown in the following example for paging parameters. If these values are set on the `Query` object, they will be ignored.
|
|
||||||
|
|
||||||
In the following code, we will add a call using a search template query to a custom repository implementation (see
|
In the following code, we will add a call using a search template query to a custom repository implementation (see
|
||||||
xref:repositories/custom-implementations.adoc[]) as an example how this can be integrated into a repository call.
|
xref:repositories/custom-implementations.adoc[]) as an example how this can be integrated into a repository call.
|
||||||
|
|
||||||
@ -451,3 +449,4 @@ var query = Query.findAll().addSort(Sort.by(order));
|
|||||||
About the filter query: It is not possible to use a `CriteriaQuery` here, as this query would be converted into a Elasticsearch nested query which does not work in the filter context. So only `StringQuery` or `NativeQuery` can be used here. When using one of these, like the term query above, the Elasticsearch field names must be used, so take care, when these are redefined with the `@Field(name="...")` definition.
|
About the filter query: It is not possible to use a `CriteriaQuery` here, as this query would be converted into a Elasticsearch nested query which does not work in the filter context. So only `StringQuery` or `NativeQuery` can be used here. When using one of these, like the term query above, the Elasticsearch field names must be used, so take care, when these are redefined with the `@Field(name="...")` definition.
|
||||||
|
|
||||||
For the definition of the order path and the nested paths, the Java entity property names should be used.
|
For the definition of the order path and the nested paths, the Java entity property names should be used.
|
||||||
|
|
||||||
|
@ -10,9 +10,7 @@ The Elasticsearch module supports all basic query building feature as string que
|
|||||||
=== Declared queries
|
=== Declared queries
|
||||||
|
|
||||||
Deriving the query from the method name is not always sufficient and/or may result in unreadable method names.
|
Deriving the query from the method name is not always sufficient and/or may result in unreadable method names.
|
||||||
In this case one might make use of the `@Query` annotation (see xref:elasticsearch/repositories/elasticsearch-repository-queries.adoc#elasticsearch.query-methods.at-query[Using the @Query Annotation] ).
|
In this case one might make use of the `@Query` annotation (see xref:elasticsearch/repositories/elasticsearch-repository-queries.adoc#elasticsearch.query-methods.at-query[Using @Query Annotation] ).
|
||||||
|
|
||||||
Another possibility is the use of a search-template, (see xref:elasticsearch/repositories/elasticsearch-repository-queries.adoc#elasticsearch.query-methods.at-searchtemplate-query[Using the @SearchTemplateQuery Annotation] ).
|
|
||||||
|
|
||||||
[[elasticsearch.query-methods.criterions]]
|
[[elasticsearch.query-methods.criterions]]
|
||||||
== Query creation
|
== Query creation
|
||||||
@ -314,13 +312,11 @@ Repository methods can be defined to have the following return types for returni
|
|||||||
* `SearchPage<T>`
|
* `SearchPage<T>`
|
||||||
|
|
||||||
[[elasticsearch.query-methods.at-query]]
|
[[elasticsearch.query-methods.at-query]]
|
||||||
== Using the @Query Annotation
|
== Using @Query Annotation
|
||||||
|
|
||||||
.Declare query on the method using the `@Query` annotation.
|
.Declare query on the method using the `@Query` annotation.
|
||||||
====
|
====
|
||||||
The arguments passed to the method can be inserted into placeholders in the query string.
|
The arguments passed to the method can be inserted into placeholders in the query string. The placeholders are of the form `?0`, `?1`, `?2` etc. for the first, second, third parameter and so on.
|
||||||
The placeholders are of the form `?0`, `?1`, `?2` etc. for the first, second, third parameter and so on.
|
|
||||||
|
|
||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
interface BookRepository extends ElasticsearchRepository<Book, String> {
|
interface BookRepository extends ElasticsearchRepository<Book, String> {
|
||||||
@ -345,20 +341,15 @@ It will be sent to Easticsearch as value of the query element; if for example th
|
|||||||
}
|
}
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
.`@Query` annotation on a method taking a Collection argument
|
.`@Query` annotation on a method taking a Collection argument
|
||||||
====
|
====
|
||||||
A repository method such as
|
A repository method such as
|
||||||
|
|
||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
@Query("{\"ids\": {\"values\": ?0 }}")
|
@Query("{\"ids\": {\"values\": ?0 }}")
|
||||||
List<SampleEntity> getByIds(Collection<String> ids);
|
List<SampleEntity> getByIds(Collection<String> ids);
|
||||||
----
|
----
|
||||||
|
would make an https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-ids-query.html[IDs query] to return all the matching documents. So calling the method with a `List` of `["id1", "id2", "id3"]` would produce the query body
|
||||||
would make an https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-ids-query.html[IDs query] to return all the matching documents.
|
|
||||||
So calling the method with a `List` of `["id1", "id2", "id3"]` would produce the query body
|
|
||||||
|
|
||||||
[source,json]
|
[source,json]
|
||||||
----
|
----
|
||||||
{
|
{
|
||||||
@ -378,6 +369,7 @@ So calling the method with a `List` of `["id1", "id2", "id3"]` would produce the
|
|||||||
====
|
====
|
||||||
https://docs.spring.io/spring-framework/reference/core/expressions.html[SpEL expression] is also supported when defining query in `@Query`.
|
https://docs.spring.io/spring-framework/reference/core/expressions.html[SpEL expression] is also supported when defining query in `@Query`.
|
||||||
|
|
||||||
|
|
||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
interface BookRepository extends ElasticsearchRepository<Book, String> {
|
interface BookRepository extends ElasticsearchRepository<Book, String> {
|
||||||
@ -419,7 +411,6 @@ If for example the function is called with the parameter _John_, it would produc
|
|||||||
.accessing parameter property.
|
.accessing parameter property.
|
||||||
====
|
====
|
||||||
Supposing that we have the following class as query parameter type:
|
Supposing that we have the following class as query parameter type:
|
||||||
|
|
||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
public record QueryParameter(String value) {
|
public record QueryParameter(String value) {
|
||||||
@ -453,9 +444,7 @@ We can pass `new QueryParameter("John")` as the parameter now, and it will produ
|
|||||||
|
|
||||||
.accessing bean property.
|
.accessing bean property.
|
||||||
====
|
====
|
||||||
https://docs.spring.io/spring-framework/reference/core/expressions/language-ref/bean-references.html[Bean property] is also supported to access.
|
https://docs.spring.io/spring-framework/reference/core/expressions/language-ref/bean-references.html[Bean property] is also supported to access. Given that there is a bean named `queryParameter` of type `QueryParameter`, we can access the bean with symbol `@` rather than `#`, and there is no need to declare a parameter of type `QueryParameter` in the query method:
|
||||||
Given that there is a bean named `queryParameter` of type `QueryParameter`, we can access the bean with symbol `@` rather than `#`, and there is no need to declare a parameter of type `QueryParameter` in the query method:
|
|
||||||
|
|
||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
interface BookRepository extends ElasticsearchRepository<Book, String> {
|
interface BookRepository extends ElasticsearchRepository<Book, String> {
|
||||||
@ -504,7 +493,6 @@ interface BookRepository extends ElasticsearchRepository<Book, String> {
|
|||||||
NOTE: collection values should not be quoted when declaring the elasticsearch json query.
|
NOTE: collection values should not be quoted when declaring the elasticsearch json query.
|
||||||
|
|
||||||
A collection of `names` like `List.of("name1", "name2")` will produce the following terms query:
|
A collection of `names` like `List.of("name1", "name2")` will produce the following terms query:
|
||||||
|
|
||||||
[source,json]
|
[source,json]
|
||||||
----
|
----
|
||||||
{
|
{
|
||||||
@ -544,7 +532,6 @@ interface BookRepository extends ElasticsearchRepository<Book, String> {
|
|||||||
Page<Book> findByName(Collection<QueryParameter> parameters, Pageable pageable);
|
Page<Book> findByName(Collection<QueryParameter> parameters, Pageable pageable);
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
This will extract all the `value` property values as a new `Collection` from `QueryParameter` collection, thus takes the same effect as above.
|
This will extract all the `value` property values as a new `Collection` from `QueryParameter` collection, thus takes the same effect as above.
|
||||||
====
|
====
|
||||||
|
|
||||||
@ -573,20 +560,3 @@ interface BookRepository extends ElasticsearchRepository<Book, String> {
|
|||||||
----
|
----
|
||||||
|
|
||||||
====
|
====
|
||||||
|
|
||||||
[[elasticsearch.query-methods.at-searchtemplate-query]]
|
|
||||||
== Using the @SearchTemplateQuery Annotation
|
|
||||||
|
|
||||||
When using Elasticsearch search templates - (see xref:elasticsearch/misc.adoc#elasticsearch.misc.searchtemplates [Search Template support]) it is possible to specify that a repository method should use a template by adding the `@SearchTemplateQuery` annotation to that method.
|
|
||||||
|
|
||||||
Let's assume that there is a search template stored with the name "book-by-title" and this template need a parameter named "title", then a repository method using that search template can be defined like this:
|
|
||||||
|
|
||||||
[source,java]
|
|
||||||
----
|
|
||||||
interface BookRepository extends ElasticsearchRepository<Book, String> {
|
|
||||||
@SearchTemplateQuery(id = "book-by-title")
|
|
||||||
SearchHits<Book> findByTitle(String title);
|
|
||||||
}
|
|
||||||
----
|
|
||||||
|
|
||||||
The parameters of the repository method are sent to the seacrh template as key/value pairs where the key is the parameter name and the value is taken from the actual value when the method is invoked.
|
|
||||||
|
@ -20,12 +20,12 @@ Whereas the birthdate is fix, the age depends on the time when a query is issued
|
|||||||
====
|
====
|
||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.data.annotation.Id;
|
import org.springframework.data.annotation.Id;
|
||||||
import org.springframework.data.elasticsearch.annotations.DateFormat;
|
import org.springframework.data.elasticsearch.annotations.DateFormat;
|
||||||
import org.springframework.data.elasticsearch.annotations.Document;
|
import org.springframework.data.elasticsearch.annotations.Document;
|
||||||
import org.springframework.data.elasticsearch.annotations.Field;
|
import org.springframework.data.elasticsearch.annotations.Field;
|
||||||
import org.springframework.data.elasticsearch.annotations.ScriptedField;
|
import org.springframework.data.elasticsearch.annotations.ScriptedField;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
|
@ -81,7 +81,7 @@ When a document is retrieved with the methods of the `DocumentOperations` inter
|
|||||||
When searching with the methods of the `SearchOperations` interface, additional information is available for each entity, for example the _score_ or the _sortValues_ of the found entity.
|
When searching with the methods of the `SearchOperations` interface, additional information is available for each entity, for example the _score_ or the _sortValues_ of the found entity.
|
||||||
|
|
||||||
In order to return this information, each entity is wrapped in a `SearchHit` object that contains this entity-specific additional information.
|
In order to return this information, each entity is wrapped in a `SearchHit` object that contains this entity-specific additional information.
|
||||||
These `SearchHit` objects themselves are returned within a `SearchHits` object which additionally contains informations about the whole search like the _maxScore_ or requested aggregations or the execution duration it took to complete the request.
|
These `SearchHit` objects themselves are returned within a `SearchHits` object which additionally contains informations about the whole search like the _maxScore_ or requested aggregations.
|
||||||
The following classes and interfaces are now available:
|
The following classes and interfaces are now available:
|
||||||
|
|
||||||
.SearchHit<T>
|
.SearchHit<T>
|
||||||
|
@ -6,12 +6,9 @@ The following table shows the Elasticsearch and Spring versions that are used by
|
|||||||
[cols="^,^,^,^",options="header"]
|
[cols="^,^,^,^",options="header"]
|
||||||
|===
|
|===
|
||||||
| Spring Data Release Train | Spring Data Elasticsearch | Elasticsearch | Spring Framework
|
| Spring Data Release Train | Spring Data Elasticsearch | Elasticsearch | Spring Framework
|
||||||
| 2025.1 (in development) | 6.0.x | 9.0.3 | 7.0.x
|
| 2024.0 | 5.3.3 | 8.13.4 | 6.1.x
|
||||||
| 2025.0 | 5.5.x | 8.18.1 | 6.2.x
|
| 2023.1 (Vaughan) | 5.2.x | 8.11.1 | 6.1.x
|
||||||
| 2024.1 | 5.4.x | 8.15.5 | 6.1.x
|
| 2023.0 (Ullmann) | 5.1.xfootnote:oom[Out of maintenance] | 8.7.1 | 6.0.x
|
||||||
| 2024.0 | 5.3.xfootnote:oom[Out of maintenance] | 8.13.4 | 6.1.x
|
|
||||||
| 2023.1 (Vaughan) | 5.2.xfootnote:oom[] | 8.11.1 | 6.1.x
|
|
||||||
| 2023.0 (Ullmann) | 5.1.xfootnote:oom[] | 8.7.1 | 6.0.x
|
|
||||||
| 2022.0 (Turing) | 5.0.xfootnote:oom[] | 8.5.3 | 6.0.x
|
| 2022.0 (Turing) | 5.0.xfootnote:oom[] | 8.5.3 | 6.0.x
|
||||||
| 2021.2 (Raj) | 4.4.xfootnote:oom[] | 7.17.3 | 5.3.x
|
| 2021.2 (Raj) | 4.4.xfootnote:oom[] | 7.17.3 | 5.3.x
|
||||||
| 2021.1 (Q) | 4.3.xfootnote:oom[] | 7.15.2 | 5.3.x
|
| 2021.1 (Q) | 4.3.xfootnote:oom[] | 7.15.2 | 5.3.x
|
||||||
|
@ -5,17 +5,14 @@ This section describes breaking changes from version 5.2.x to 5.3.x and how remo
|
|||||||
|
|
||||||
[[elasticsearch-migration-guide-5.2-5.3.breaking-changes]]
|
[[elasticsearch-migration-guide-5.2-5.3.breaking-changes]]
|
||||||
== Breaking Changes
|
== Breaking Changes
|
||||||
|
During the parameter replacement in `@Query` annotated repository methods previous versions wrote the String _"null"_ into the query that was sent to Elasticsearch
|
||||||
During the parameter replacement in `@Query` annotated repository methods previous versions wrote the String `"null"` into the query that was sent to Elasticsearch when the actual parameter value was `null`.
|
when the actual parameter value was `null`. As Elasticsearch does not store `null` values, this behaviour could lead to problems, for example whent the fields to be
|
||||||
As Elasticsearch does not store `null` values, this behaviour could lead to problems, for example whent the fields to be searched contains the string `"null"`.
|
searched contains the string `"null"`. In Version 5.3 a `null` value in a parameter will cause a `ConversionException` to be thrown. If you are using `"null"` as the
|
||||||
In Version 5.3 a `null` value in a parameter will cause a `ConversionException` to be thrown.
|
|
||||||
If you are using `"null"` as the
|
|
||||||
`null_value` defined in a field mapping, then pass that string into the query instead of a Java `null`.
|
`null_value` defined in a field mapping, then pass that string into the query instead of a Java `null`.
|
||||||
|
|
||||||
[[elasticsearch-migration-guide-5.2-5.3.deprecations]]
|
[[elasticsearch-migration-guide-5.2-5.3.deprecations]]
|
||||||
== Deprecations
|
== Deprecations
|
||||||
|
|
||||||
=== Removals
|
=== Removals
|
||||||
|
|
||||||
The deprecated classes `org.springframework.data.elasticsearch.ELCQueries`
|
The deprecated classes `org.springframework.data.elasticsearch.ELCQueries`
|
||||||
and `org.springframework.data.elasticsearch.client.elc.QueryBuilders` have been removed, use `org.springframework.data.elasticsearch.client.elc.Queries` instead.
|
and `org.springframework.data.elasticsearch.client.elc.QueryBuilders` have been removed, use `org.springframework.data.elasticsearch.client.elc.Queries` instead.
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
[[elasticsearch-migration-guide-5.3-5.4]]
|
|
||||||
= Upgrading from 5.3.x to 5.4.x
|
|
||||||
|
|
||||||
This section describes breaking changes from version 5.3.x to 5.4.x and how removed features can be replaced by new introduced features.
|
|
||||||
|
|
||||||
[[elasticsearch-migration-guide-5.3-5.4.breaking-changes]]
|
|
||||||
== Breaking Changes
|
|
||||||
|
|
||||||
[[elasticsearch-migration-guide-5.3-5.4.breaking-changes.knn-search]]
|
|
||||||
=== knn search
|
|
||||||
The `withKnnQuery` method in `NativeQueryBuilder` has been replaced with `withKnnSearches` to build a `NativeQuery` with knn search.
|
|
||||||
|
|
||||||
`KnnQuery` and `KnnSearch` are two different classes in elasticsearch java client and are used for different queries, with different parameters supported:
|
|
||||||
|
|
||||||
- `KnnSearch`: is https://www.elastic.co/guide/en/elasticsearch/reference/8.13/search-search.html#search-api-knn[the top level `knn` query] in the elasticsearch request;
|
|
||||||
- `KnnQuery`: is https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-knn-query.html[the `knn` query inside `query` clause];
|
|
||||||
|
|
||||||
If `KnnQuery` is still preferable, please be sure to construct it inside `query` clause manually, by means of `withQuery(co.elastic.clients.elasticsearch._types.query_dsl.Query query)` clause in `NativeQueryBuilder`.
|
|
||||||
|
|
||||||
[[elasticsearch-migration-guide-5.3-5.4.deprecations]]
|
|
||||||
== Deprecations
|
|
||||||
|
|
||||||
=== Removals
|
|
@ -1,30 +0,0 @@
|
|||||||
[[elasticsearch-migration-guide-5.4-5.5]]
|
|
||||||
= Upgrading from 5.4.x to 5.5.x
|
|
||||||
|
|
||||||
This section describes breaking changes from version 5.4.x to 5.5.x and how removed features can be replaced by new introduced features.
|
|
||||||
|
|
||||||
[[elasticsearch-migration-guide-5.4-5.5.breaking-changes]]
|
|
||||||
== Breaking Changes
|
|
||||||
|
|
||||||
[[elasticsearch-migration-guide-5.4-5.5.deprecations]]
|
|
||||||
== Deprecations
|
|
||||||
|
|
||||||
Some classes that probably are not used by a library user have been renamed, the classes with the old names are still there, but are deprecated:
|
|
||||||
|
|
||||||
|===
|
|
||||||
|old name|new name
|
|
||||||
|
|
||||||
|ElasticsearchPartQuery|RepositoryPartQuery
|
|
||||||
|ElasticsearchStringQuery|RepositoryStringQuery
|
|
||||||
|ReactiveElasticsearchStringQuery|ReactiveRepositoryStringQuery
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Removals
|
|
||||||
|
|
||||||
The following methods that had been deprecated since release 5.3 have been removed:
|
|
||||||
```
|
|
||||||
DocumentOperations.delete(Query, Class<?>)
|
|
||||||
DocumentOperations.delete(Query, Class<?>, IndexCoordinates)
|
|
||||||
ReactiveDocumentOperations.delete(Query, Class<?>)
|
|
||||||
ReactiveDocumentOperations.delete(Query, Class<?>, IndexCoordinates)
|
|
||||||
```
|
|
@ -1,25 +0,0 @@
|
|||||||
[[elasticsearch-migration-guide-5.5-6.0]]
|
|
||||||
= Upgrading from 5.5.x to 6.0.x
|
|
||||||
|
|
||||||
This section describes breaking changes from version 5.5.x to 6.0.x and how removed features can be replaced by new introduced features.
|
|
||||||
|
|
||||||
[[elasticsearch-migration-guide-5.5-6.0.breaking-changes]]
|
|
||||||
== Breaking Changes
|
|
||||||
|
|
||||||
From version 6.0 on, Spring Data Elasticsearch uses the Elasticsearch 9 libraries and as default the new `Rest5Client` provided by these libraries. It is still possible to use the old `RestClient`, check xref:elasticsearch/clients.adoc[Elasticsearch clients] for information. The configuration callbacks for this `RestClient` have been moved from `org.springframework.data.elasticsearch.client.elc.ElasticsearchClients` to the `org.springframework.data.elasticsearch.client.elc.rest_client.RestClients` class.
|
|
||||||
|
|
||||||
[[elasticsearch-migration-guide-5.5-6.0.deprecations]]
|
|
||||||
== Deprecations
|
|
||||||
|
|
||||||
All the code using the old `RestClient` has been moved to the `org.springframework.data.elasticsearch.client.elc.rest_client` package and has been deprecated. Users should switch to the classes from the `org.springframework.data.elasticsearch.client.elc.rest5_client` package.
|
|
||||||
|
|
||||||
|
|
||||||
=== Removals
|
|
||||||
|
|
||||||
The `org.springframework.data.elasticsearch.core.query.ScriptType` enum has been removed. To distinguish between an inline and a stored script set the appropriate values in the `org.springframework.data.elasticsearch.core.query.ScriptData` record.
|
|
||||||
|
|
||||||
These methods have been removed because the Elasticsearch Client 9 does not support them anymore:
|
|
||||||
```
|
|
||||||
org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchIndicesClient.unfreeze(UnfreezeRequest)
|
|
||||||
org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchIndicesClient.unfreeze(Function<UnfreezeRequest.Builder, ObjectBuilder<UnfreezeRequest>>)
|
|
||||||
```
|
|
@ -15,9 +15,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.elasticsearch;
|
package org.springframework.data.elasticsearch;
|
||||||
|
|
||||||
import java.util.List;
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Object describing an Elasticsearch error
|
* Object describing an Elasticsearch error
|
||||||
@ -26,7 +26,8 @@ import org.jspecify.annotations.Nullable;
|
|||||||
* @since 4.4
|
* @since 4.4
|
||||||
*/
|
*/
|
||||||
public class ElasticsearchErrorCause {
|
public class ElasticsearchErrorCause {
|
||||||
@Nullable private final String type;
|
@Nullable
|
||||||
|
private final String type;
|
||||||
|
|
||||||
private final String reason;
|
private final String reason;
|
||||||
|
|
||||||
|
@ -15,8 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.elasticsearch;
|
package org.springframework.data.elasticsearch;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.dao.UncategorizedDataAccessException;
|
import org.springframework.dao.UncategorizedDataAccessException;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Peter-Josef Meisch
|
* @author Peter-Josef Meisch
|
||||||
|
@ -1,79 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2024-2025 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.springframework.data.elasticsearch.annotations;
|
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Inherited;
|
|
||||||
import java.lang.annotation.Repeatable;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
import org.springframework.core.annotation.AliasFor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Identifies an alias for the index.
|
|
||||||
*
|
|
||||||
* @author Youssef Aouichaoui
|
|
||||||
* @since 5.4
|
|
||||||
*/
|
|
||||||
@Inherited
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target({ ElementType.TYPE })
|
|
||||||
@Repeatable(Aliases.class)
|
|
||||||
public @interface Alias {
|
|
||||||
/**
|
|
||||||
* @return Index alias name. Alias for {@link #alias}.
|
|
||||||
*/
|
|
||||||
@AliasFor("alias")
|
|
||||||
String value() default "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Index alias name. Alias for {@link #value}.
|
|
||||||
*/
|
|
||||||
@AliasFor("value")
|
|
||||||
String alias() default "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Query used to limit documents the alias can access.
|
|
||||||
*/
|
|
||||||
Filter filter() default @Filter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Used to route indexing operations to a specific shard.
|
|
||||||
*/
|
|
||||||
String indexRouting() default "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Used to route indexing and search operations to a specific shard.
|
|
||||||
*/
|
|
||||||
String routing() default "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Used to route search operations to a specific shard.
|
|
||||||
*/
|
|
||||||
String searchRouting() default "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Is the alias hidden?
|
|
||||||
*/
|
|
||||||
boolean isHidden() default false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Is it the 'write index' for the alias?
|
|
||||||
*/
|
|
||||||
boolean isWriteIndex() default false;
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2024-2025 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.springframework.data.elasticsearch.annotations;
|
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Inherited;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Container annotation that aggregates several {@link Alias} annotations.
|
|
||||||
*
|
|
||||||
* @author Youssef Aouichaoui
|
|
||||||
* @see Alias
|
|
||||||
* @since 5.4
|
|
||||||
*/
|
|
||||||
@Inherited
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target({ ElementType.TYPE })
|
|
||||||
public @interface Aliases {
|
|
||||||
Alias[] value();
|
|
||||||
}
|
|
@ -100,13 +100,6 @@ public @interface Document {
|
|||||||
*/
|
*/
|
||||||
boolean storeVersionInSource() default true;
|
boolean storeVersionInSource() default true;
|
||||||
|
|
||||||
/**
|
|
||||||
* Aliases for the index.
|
|
||||||
*
|
|
||||||
* @since 5.4
|
|
||||||
*/
|
|
||||||
Alias[] aliases() default {};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.3
|
* @since 4.3
|
||||||
*/
|
*/
|
||||||
|
@ -37,8 +37,6 @@ import org.springframework.core.annotation.AliasFor;
|
|||||||
* @author Brian Kimmig
|
* @author Brian Kimmig
|
||||||
* @author Morgan Lutz
|
* @author Morgan Lutz
|
||||||
* @author Sascha Woo
|
* @author Sascha Woo
|
||||||
* @author Haibo Liu
|
|
||||||
* @author Andriy Redko
|
|
||||||
*/
|
*/
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target({ ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.METHOD })
|
@Target({ ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.METHOD })
|
||||||
@ -130,10 +128,6 @@ public @interface Field {
|
|||||||
boolean norms() default true;
|
boolean norms() default true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOte that null_value setting are not supported in Elasticsearch for all types. For example setting a null_value on
|
|
||||||
* a field with type text will throw an exception in the server when the mapping is written to Elasticsearch. Alas,
|
|
||||||
* the Elasticsearch documentation does not specify on which types it is allowed on which it is not.
|
|
||||||
*
|
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
String nullValue() default "";
|
String nullValue() default "";
|
||||||
@ -201,27 +195,6 @@ public @interface Field {
|
|||||||
*/
|
*/
|
||||||
int dims() default -1;
|
int dims() default -1;
|
||||||
|
|
||||||
/**
|
|
||||||
* to be used in combination with {@link FieldType#Dense_Vector}
|
|
||||||
*
|
|
||||||
* @since 5.4
|
|
||||||
*/
|
|
||||||
String elementType() default FieldElementType.DEFAULT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* to be used in combination with {@link FieldType#Dense_Vector}
|
|
||||||
*
|
|
||||||
* @since 5.4
|
|
||||||
*/
|
|
||||||
KnnSimilarity knnSimilarity() default KnnSimilarity.DEFAULT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* to be used in combination with {@link FieldType#Dense_Vector}
|
|
||||||
*
|
|
||||||
* @since 5.4
|
|
||||||
*/
|
|
||||||
KnnIndexOptions[] knnIndexOptions() default {};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controls how Elasticsearch dynamically adds fields to the inner object within the document.<br>
|
* Controls how Elasticsearch dynamically adds fields to the inner object within the document.<br>
|
||||||
* To be used in combination with {@link FieldType#Object} or {@link FieldType#Nested}
|
* To be used in combination with {@link FieldType#Object} or {@link FieldType#Nested}
|
||||||
@ -245,11 +218,4 @@ public @interface Field {
|
|||||||
* @since 5.1
|
* @since 5.1
|
||||||
*/
|
*/
|
||||||
boolean storeEmptyValue() default true;
|
boolean storeEmptyValue() default true;
|
||||||
|
|
||||||
/**
|
|
||||||
* overrides the field type in the mapping which otherwise will be taken from corresponding {@link FieldType}
|
|
||||||
*
|
|
||||||
* @since 5.4
|
|
||||||
*/
|
|
||||||
String mappedTypeName() default "";
|
|
||||||
}
|
}
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2024-2025 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.springframework.data.elasticsearch.annotations;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Haibo Liu
|
|
||||||
* @since 5.4
|
|
||||||
*/
|
|
||||||
public final class FieldElementType {
|
|
||||||
public final static String DEFAULT = "";
|
|
||||||
public final static String FLOAT = "float";
|
|
||||||
public final static String BYTE = "byte";
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2024-2025 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.springframework.data.elasticsearch.annotations;
|
|
||||||
|
|
||||||
import org.springframework.core.annotation.AliasFor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Query used to limit documents.
|
|
||||||
*
|
|
||||||
* @author Youssef Aouichaoui
|
|
||||||
* @since 5.4
|
|
||||||
*/
|
|
||||||
public @interface Filter {
|
|
||||||
/**
|
|
||||||
* @return Query used to limit documents. Alias for {@link #query}.
|
|
||||||
*/
|
|
||||||
@AliasFor("query")
|
|
||||||
String value() default "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Query used to limit documents. Alias for {@link #value}.
|
|
||||||
*/
|
|
||||||
@AliasFor("value")
|
|
||||||
String query() default "";
|
|
||||||
}
|
|
@ -29,8 +29,6 @@ import java.lang.annotation.Target;
|
|||||||
* @author Aleksei Arsenev
|
* @author Aleksei Arsenev
|
||||||
* @author Brian Kimmig
|
* @author Brian Kimmig
|
||||||
* @author Morgan Lutz
|
* @author Morgan Lutz
|
||||||
* @author Haibo Liu
|
|
||||||
* @author Andriy Redko
|
|
||||||
*/
|
*/
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.ANNOTATION_TYPE)
|
@Target(ElementType.ANNOTATION_TYPE)
|
||||||
@ -151,32 +149,4 @@ public @interface InnerField {
|
|||||||
* @since 4.2
|
* @since 4.2
|
||||||
*/
|
*/
|
||||||
int dims() default -1;
|
int dims() default -1;
|
||||||
|
|
||||||
/**
|
|
||||||
* to be used in combination with {@link FieldType#Dense_Vector}
|
|
||||||
*
|
|
||||||
* @since 5.4
|
|
||||||
*/
|
|
||||||
String elementType() default FieldElementType.DEFAULT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* to be used in combination with {@link FieldType#Dense_Vector}
|
|
||||||
*
|
|
||||||
* @since 5.4
|
|
||||||
*/
|
|
||||||
KnnSimilarity knnSimilarity() default KnnSimilarity.DEFAULT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* to be used in combination with {@link FieldType#Dense_Vector}
|
|
||||||
*
|
|
||||||
* @since 5.4
|
|
||||||
*/
|
|
||||||
KnnIndexOptions[] knnIndexOptions() default {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* overrides the field type in the mapping which otherwise will be taken from corresponding {@link FieldType}
|
|
||||||
*
|
|
||||||
* @since 5.4
|
|
||||||
*/
|
|
||||||
String mappedTypeName() default "";
|
|
||||||
}
|
}
|
||||||
|
@ -1,38 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2024-2025 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.springframework.data.elasticsearch.annotations;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Haibo Liu
|
|
||||||
* @since 5.4
|
|
||||||
*/
|
|
||||||
public enum KnnAlgorithmType {
|
|
||||||
HNSW("hnsw"),
|
|
||||||
INT8_HNSW("int8_hnsw"),
|
|
||||||
FLAT("flat"),
|
|
||||||
INT8_FLAT("int8_flat"),
|
|
||||||
DEFAULT("");
|
|
||||||
|
|
||||||
private final String type;
|
|
||||||
|
|
||||||
KnnAlgorithmType(String type) {
|
|
||||||
this.type = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2024-2025 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.springframework.data.elasticsearch.annotations;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Haibo Liu
|
|
||||||
* @since 5.4
|
|
||||||
*/
|
|
||||||
public @interface KnnIndexOptions {
|
|
||||||
|
|
||||||
KnnAlgorithmType type() default KnnAlgorithmType.DEFAULT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Only applicable to {@link KnnAlgorithmType#HNSW} and {@link KnnAlgorithmType#INT8_HNSW} index types.
|
|
||||||
*/
|
|
||||||
int m() default -1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Only applicable to {@link KnnAlgorithmType#HNSW} and {@link KnnAlgorithmType#INT8_HNSW} index types.
|
|
||||||
*/
|
|
||||||
int efConstruction() default -1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Only applicable to {@link KnnAlgorithmType#INT8_HNSW} and {@link KnnAlgorithmType#INT8_FLAT} index types.
|
|
||||||
*/
|
|
||||||
float confidenceInterval() default -1F;
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2024-2025 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.springframework.data.elasticsearch.annotations;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Haibo Liu
|
|
||||||
* @since 5.4
|
|
||||||
*/
|
|
||||||
public enum KnnSimilarity {
|
|
||||||
L2_NORM("l2_norm"),
|
|
||||||
DOT_PRODUCT("dot_product"),
|
|
||||||
COSINE("cosine"),
|
|
||||||
MAX_INNER_PRODUCT("max_inner_product"),
|
|
||||||
DEFAULT("");
|
|
||||||
|
|
||||||
private final String similarity;
|
|
||||||
|
|
||||||
KnnSimilarity(String similarity) {
|
|
||||||
this.similarity = similarity;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSimilarity() {
|
|
||||||
return similarity;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2025 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.springframework.data.elasticsearch.annotations;
|
|
||||||
|
|
||||||
import org.springframework.data.annotation.QueryAnnotation;
|
|
||||||
|
|
||||||
import java.lang.annotation.Documented;
|
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Annotation to mark a repository method as a search template method. The annotation defines the search template id,
|
|
||||||
* the parameters for the search template are taken from the method's arguments.
|
|
||||||
*
|
|
||||||
* @author P.J. Meisch (pj.meisch@sothawo.com)
|
|
||||||
* @since 5.5
|
|
||||||
*/
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
|
|
||||||
@Documented
|
|
||||||
@QueryAnnotation
|
|
||||||
public @interface SearchTemplateQuery {
|
|
||||||
/**
|
|
||||||
* The id of the search template. Must not be empt or null.
|
|
||||||
*/
|
|
||||||
String id();
|
|
||||||
}
|
|
@ -1,2 +1,3 @@
|
|||||||
@org.jspecify.annotations.NullMarked
|
@org.springframework.lang.NonNullApi
|
||||||
|
@org.springframework.lang.NonNullFields
|
||||||
package org.springframework.data.elasticsearch.annotations;
|
package org.springframework.data.elasticsearch.annotations;
|
||||||
|
@ -19,7 +19,6 @@ import static org.springframework.data.elasticsearch.aot.ElasticsearchAotPredica
|
|||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.aot.hint.MemberCategory;
|
import org.springframework.aot.hint.MemberCategory;
|
||||||
import org.springframework.aot.hint.RuntimeHints;
|
import org.springframework.aot.hint.RuntimeHints;
|
||||||
import org.springframework.aot.hint.RuntimeHintsRegistrar;
|
import org.springframework.aot.hint.RuntimeHintsRegistrar;
|
||||||
@ -33,6 +32,7 @@ import org.springframework.data.elasticsearch.core.event.ReactiveAfterConvertCal
|
|||||||
import org.springframework.data.elasticsearch.core.event.ReactiveAfterLoadCallback;
|
import org.springframework.data.elasticsearch.core.event.ReactiveAfterLoadCallback;
|
||||||
import org.springframework.data.elasticsearch.core.event.ReactiveAfterSaveCallback;
|
import org.springframework.data.elasticsearch.core.event.ReactiveAfterSaveCallback;
|
||||||
import org.springframework.data.elasticsearch.core.event.ReactiveBeforeConvertCallback;
|
import org.springframework.data.elasticsearch.core.event.ReactiveBeforeConvertCallback;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Peter-Josef Meisch
|
* @author Peter-Josef Meisch
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
@org.jspecify.annotations.NullMarked
|
@org.springframework.lang.NonNullApi
|
||||||
|
@org.springframework.lang.NonNullFields
|
||||||
package org.springframework.data.elasticsearch.aot;
|
package org.springframework.data.elasticsearch.aot;
|
||||||
|
@ -25,8 +25,8 @@ import java.util.function.Supplier;
|
|||||||
import javax.net.ssl.HostnameVerifier;
|
import javax.net.ssl.HostnameVerifier;
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.data.elasticsearch.support.HttpHeaders;
|
import org.springframework.data.elasticsearch.support.HttpHeaders;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration interface exposing common client configuration properties for Elasticsearch clients.
|
* Configuration interface exposing common client configuration properties for Elasticsearch clients.
|
||||||
@ -127,16 +127,10 @@ public interface ClientConfiguration {
|
|||||||
Optional<String> getCaFingerprint();
|
Optional<String> getCaFingerprint();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link HostnameVerifier} to use. Must be {@link Optional#empty()} if not configured.
|
* Returns the {@link HostnameVerifier} to use. Can be {@link Optional#empty()} if not configured.
|
||||||
* Cannot be used with the Rest5Client used from Elasticsearch 9 on as the underlying Apache http components 5 does not offer a way
|
|
||||||
* to set this. Users that need a hostname verifier must integrate this in a SSLContext.
|
|
||||||
* Returning a value here is ignored in this case
|
|
||||||
*
|
*
|
||||||
* @return the {@link HostnameVerifier} to use. Can be {@link Optional#empty()} if not configured.
|
* @return the {@link HostnameVerifier} to use. Can be {@link Optional#empty()} if not configured.
|
||||||
* @deprecated since 6.0
|
|
||||||
*/
|
*/
|
||||||
// todo #3117 document this
|
|
||||||
@Deprecated(since = "6.0", forRemoval=true)
|
|
||||||
Optional<HostnameVerifier> getHostNameVerifier();
|
Optional<HostnameVerifier> getHostNameVerifier();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,11 +25,11 @@ import java.util.function.Supplier;
|
|||||||
import javax.net.ssl.HostnameVerifier;
|
import javax.net.ssl.HostnameVerifier;
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.data.elasticsearch.client.ClientConfiguration.ClientConfigurationBuilderWithRequiredEndpoint;
|
import org.springframework.data.elasticsearch.client.ClientConfiguration.ClientConfigurationBuilderWithRequiredEndpoint;
|
||||||
import org.springframework.data.elasticsearch.client.ClientConfiguration.MaybeSecureClientConfigurationBuilder;
|
import org.springframework.data.elasticsearch.client.ClientConfiguration.MaybeSecureClientConfigurationBuilder;
|
||||||
import org.springframework.data.elasticsearch.client.ClientConfiguration.TerminalClientConfigurationBuilder;
|
import org.springframework.data.elasticsearch.client.ClientConfiguration.TerminalClientConfigurationBuilder;
|
||||||
import org.springframework.data.elasticsearch.support.HttpHeaders;
|
import org.springframework.data.elasticsearch.support.HttpHeaders;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -24,8 +24,9 @@ import java.util.function.Supplier;
|
|||||||
import javax.net.ssl.HostnameVerifier;
|
import javax.net.ssl.HostnameVerifier;
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.elasticsearch.client.RestClientBuilder.HttpClientConfigCallback;
|
||||||
import org.springframework.data.elasticsearch.support.HttpHeaders;
|
import org.springframework.data.elasticsearch.support.HttpHeaders;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default {@link ClientConfiguration} implementation.
|
* Default {@link ClientConfiguration} implementation.
|
||||||
|
@ -17,10 +17,10 @@ package org.springframework.data.elasticsearch.client.elc;
|
|||||||
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
|
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
|
||||||
import org.springframework.data.elasticsearch.core.query.Query;
|
import org.springframework.data.elasticsearch.core.query.Query;
|
||||||
import org.springframework.data.elasticsearch.core.query.StringQuery;
|
import org.springframework.data.elasticsearch.core.query.StringQuery;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An abstract class that serves as a base for query processors. It provides a common interface and basic functionality
|
* An abstract class that serves as a base for query processors. It provides a common interface and basic functionality
|
||||||
@ -38,8 +38,8 @@ public abstract class AbstractQueryProcessor {
|
|||||||
* @param queryConverter correct mapped field names and the values to the converted values.
|
* @param queryConverter correct mapped field names and the values to the converted values.
|
||||||
* @return an Elasticsearch {@literal query}.
|
* @return an Elasticsearch {@literal query}.
|
||||||
*/
|
*/
|
||||||
|
@Nullable
|
||||||
static co.elastic.clients.elasticsearch._types.query_dsl.@Nullable Query getEsQuery(@Nullable Query query,
|
static co.elastic.clients.elasticsearch._types.query_dsl.Query getEsQuery(@Nullable Query query,
|
||||||
@Nullable Consumer<Query> queryConverter) {
|
@Nullable Consumer<Query> queryConverter) {
|
||||||
if (query == null) {
|
if (query == null) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -18,8 +18,6 @@ package org.springframework.data.elasticsearch.client.elc;
|
|||||||
import co.elastic.clients.elasticsearch.ElasticsearchClient;
|
import co.elastic.clients.elasticsearch.ElasticsearchClient;
|
||||||
import co.elastic.clients.transport.ElasticsearchTransport;
|
import co.elastic.clients.transport.ElasticsearchTransport;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.elasticsearch.client.RestClient;
|
import org.elasticsearch.client.RestClient;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
@ -38,10 +36,7 @@ public class AutoCloseableElasticsearchClient extends ElasticsearchClient implem
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() throws Exception {
|
||||||
// since Elasticsearch 8.16 the ElasticsearchClient implements (through ApiClient) the Closeable interface and
|
transport.close();
|
||||||
// handles closing of the underlying transport. We now just call the base class, but keep this as we
|
|
||||||
// have been implementing AutoCloseable since 4.4 and won't change that to a mere Closeable
|
|
||||||
super.close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,13 +31,13 @@ import java.util.Iterator;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.data.elasticsearch.annotations.FieldType;
|
import org.springframework.data.elasticsearch.annotations.FieldType;
|
||||||
import org.springframework.data.elasticsearch.core.query.Criteria;
|
import org.springframework.data.elasticsearch.core.query.Criteria;
|
||||||
import org.springframework.data.elasticsearch.core.query.Field;
|
import org.springframework.data.elasticsearch.core.query.Field;
|
||||||
import org.springframework.data.elasticsearch.core.query.HasChildQuery;
|
import org.springframework.data.elasticsearch.core.query.HasChildQuery;
|
||||||
import org.springframework.data.elasticsearch.core.query.HasParentQuery;
|
import org.springframework.data.elasticsearch.core.query.HasParentQuery;
|
||||||
import org.springframework.data.elasticsearch.core.query.InnerHitsQuery;
|
import org.springframework.data.elasticsearch.core.query.InnerHitsQuery;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -249,54 +249,49 @@ class CriteriaQueryProcessor extends AbstractQueryProcessor {
|
|||||||
queryBuilder.queryString(queryStringQuery(fieldName, Objects.requireNonNull(value).toString(), boost));
|
queryBuilder.queryString(queryStringQuery(fieldName, Objects.requireNonNull(value).toString(), boost));
|
||||||
break;
|
break;
|
||||||
case LESS:
|
case LESS:
|
||||||
queryBuilder
|
queryBuilder //
|
||||||
.range(rb -> rb
|
.range(rb -> rb //
|
||||||
.untyped(ut -> ut
|
.field(fieldName) //
|
||||||
.field(fieldName)
|
.lt(JsonData.of(value)) //
|
||||||
.lt(JsonData.of(value))
|
.boost(boost)); //
|
||||||
.boost(boost)));
|
|
||||||
break;
|
break;
|
||||||
case LESS_EQUAL:
|
case LESS_EQUAL:
|
||||||
queryBuilder
|
queryBuilder //
|
||||||
.range(rb -> rb
|
.range(rb -> rb //
|
||||||
.untyped(ut -> ut
|
.field(fieldName) //
|
||||||
.field(fieldName)
|
.lte(JsonData.of(value)) //
|
||||||
.lte(JsonData.of(value))
|
.boost(boost)); //
|
||||||
.boost(boost)));
|
|
||||||
break;
|
break;
|
||||||
case GREATER:
|
case GREATER:
|
||||||
queryBuilder
|
queryBuilder //
|
||||||
.range(rb -> rb
|
.range(rb -> rb //
|
||||||
.untyped(ut -> ut
|
.field(fieldName) //
|
||||||
.field(fieldName)
|
.gt(JsonData.of(value)) //
|
||||||
.gt(JsonData.of(value))
|
.boost(boost)); //
|
||||||
.boost(boost)));
|
|
||||||
break;
|
break;
|
||||||
case GREATER_EQUAL:
|
case GREATER_EQUAL:
|
||||||
queryBuilder
|
queryBuilder //
|
||||||
.range(rb -> rb
|
.range(rb -> rb //
|
||||||
.untyped(ut -> ut
|
.field(fieldName) //
|
||||||
.field(fieldName)
|
.gte(JsonData.of(value)) //
|
||||||
.gte(JsonData.of(value))
|
.boost(boost)); //
|
||||||
.boost(boost)));
|
|
||||||
break;
|
break;
|
||||||
case BETWEEN:
|
case BETWEEN:
|
||||||
Object[] ranges = (Object[]) value;
|
Object[] ranges = (Object[]) value;
|
||||||
Assert.notNull(value, "value for a between condition must not be null");
|
Assert.notNull(value, "value for a between condition must not be null");
|
||||||
queryBuilder
|
queryBuilder //
|
||||||
.range(rb -> rb
|
.range(rb -> {
|
||||||
.untyped(ut -> {
|
rb.field(fieldName);
|
||||||
ut.field(fieldName);
|
|
||||||
if (ranges[0] != null) {
|
if (ranges[0] != null) {
|
||||||
ut.gte(JsonData.of(ranges[0]));
|
rb.gte(JsonData.of(ranges[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ranges[1] != null) {
|
if (ranges[1] != null) {
|
||||||
ut.lte(JsonData.of(ranges[1]));
|
rb.lte(JsonData.of(ranges[1]));
|
||||||
}
|
}
|
||||||
ut.boost(boost); //
|
rb.boost(boost); //
|
||||||
return ut;
|
return rb;
|
||||||
}));
|
}); //
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case FUZZY:
|
case FUZZY:
|
||||||
|
@ -24,17 +24,6 @@ import co.elastic.clients.elasticsearch.core.search.Hit;
|
|||||||
import co.elastic.clients.elasticsearch.core.search.NestedIdentity;
|
import co.elastic.clients.elasticsearch.core.search.NestedIdentity;
|
||||||
import co.elastic.clients.json.JsonData;
|
import co.elastic.clients.json.JsonData;
|
||||||
import co.elastic.clients.json.JsonpMapper;
|
import co.elastic.clients.json.JsonpMapper;
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.data.elasticsearch.core.MultiGetItem;
|
|
||||||
import org.springframework.data.elasticsearch.core.document.Document;
|
|
||||||
import org.springframework.data.elasticsearch.core.document.Explanation;
|
|
||||||
import org.springframework.data.elasticsearch.core.document.NestedMetaData;
|
|
||||||
import org.springframework.data.elasticsearch.core.document.SearchDocument;
|
|
||||||
import org.springframework.data.elasticsearch.core.document.SearchDocumentAdapter;
|
|
||||||
import org.springframework.data.elasticsearch.core.document.SearchDocumentResponse;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
@ -43,21 +32,31 @@ import java.util.Map;
|
|||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.springframework.data.elasticsearch.core.MultiGetItem;
|
||||||
|
import org.springframework.data.elasticsearch.core.document.Document;
|
||||||
|
import org.springframework.data.elasticsearch.core.document.Explanation;
|
||||||
|
import org.springframework.data.elasticsearch.core.document.NestedMetaData;
|
||||||
|
import org.springframework.data.elasticsearch.core.document.SearchDocument;
|
||||||
|
import org.springframework.data.elasticsearch.core.document.SearchDocumentAdapter;
|
||||||
|
import org.springframework.data.elasticsearch.core.document.SearchDocumentResponse;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility class to adapt different Elasticsearch responses to a
|
* Utility class to adapt different Elasticsearch responses to a
|
||||||
* {@link org.springframework.data.elasticsearch.core.document.Document}
|
* {@link org.springframework.data.elasticsearch.core.document.Document}
|
||||||
*
|
*
|
||||||
* @author Peter-Josef Meisch
|
* @author Peter-Josef Meisch
|
||||||
* @author Haibo Liu
|
* @author Haibo Liu
|
||||||
* @author Mohamed El Harrougui
|
|
||||||
* @since 4.4
|
* @since 4.4
|
||||||
*/
|
*/
|
||||||
final class DocumentAdapters {
|
final class DocumentAdapters {
|
||||||
|
|
||||||
private static final Log LOGGER = LogFactory.getLog(DocumentAdapters.class);
|
private static final Log LOGGER = LogFactory.getLog(DocumentAdapters.class);
|
||||||
|
|
||||||
private DocumentAdapters() {
|
private DocumentAdapters() {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@link SearchDocument} from a {@link Hit} returned by the Elasticsearch client.
|
* Creates a {@link SearchDocument} from a {@link Hit} returned by the Elasticsearch client.
|
||||||
@ -75,7 +74,7 @@ final class DocumentAdapters {
|
|||||||
Map<String, SearchDocumentResponse> innerHits = new LinkedHashMap<>();
|
Map<String, SearchDocumentResponse> innerHits = new LinkedHashMap<>();
|
||||||
hit.innerHits().forEach((name, innerHitsResult) -> {
|
hit.innerHits().forEach((name, innerHitsResult) -> {
|
||||||
// noinspection ReturnOfNull
|
// noinspection ReturnOfNull
|
||||||
innerHits.put(name, SearchDocumentResponseBuilder.from(innerHitsResult.hits(), null, null, null, 0, null, null,
|
innerHits.put(name, SearchDocumentResponseBuilder.from(innerHitsResult.hits(), null, null, null, null, null,
|
||||||
searchDocument -> null, jsonpMapper));
|
searchDocument -> null, jsonpMapper));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -83,11 +82,11 @@ final class DocumentAdapters {
|
|||||||
|
|
||||||
Explanation explanation = from(hit.explanation());
|
Explanation explanation = from(hit.explanation());
|
||||||
|
|
||||||
Map<String, Double> matchedQueries = hit.matchedQueries();
|
List<String> matchedQueries = hit.matchedQueries();
|
||||||
|
|
||||||
Function<Map<String, JsonData>, EntityAsMap> fromFields = fields -> {
|
Function<Map<String, JsonData>, EntityAsMap> fromFields = fields -> {
|
||||||
StringBuilder sb = new StringBuilder("{");
|
StringBuilder sb = new StringBuilder("{");
|
||||||
final boolean[] firstField = {true};
|
final boolean[] firstField = { true };
|
||||||
hit.fields().forEach((key, jsonData) -> {
|
hit.fields().forEach((key, jsonData) -> {
|
||||||
if (!firstField[0]) {
|
if (!firstField[0]) {
|
||||||
sb.append(',');
|
sb.append(',');
|
||||||
@ -155,12 +154,12 @@ final class DocumentAdapters {
|
|||||||
}
|
}
|
||||||
|
|
||||||
float score = completionSuggestOption.score() != null ? completionSuggestOption.score().floatValue() : Float.NaN;
|
float score = completionSuggestOption.score() != null ? completionSuggestOption.score().floatValue() : Float.NaN;
|
||||||
return new SearchDocumentAdapter(document, score, new Object[]{}, Collections.emptyMap(), Collections.emptyMap(),
|
return new SearchDocumentAdapter(document, score, new Object[] {}, Collections.emptyMap(), Collections.emptyMap(),
|
||||||
Collections.emptyMap(), null, null, null, completionSuggestOption.routing());
|
Collections.emptyMap(), null, null, null, completionSuggestOption.routing());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static Explanation from(co.elastic.clients.elasticsearch.core.explain.@Nullable Explanation explanation) {
|
private static Explanation from(@Nullable co.elastic.clients.elasticsearch.core.explain.Explanation explanation) {
|
||||||
|
|
||||||
if (explanation == null) {
|
if (explanation == null) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -22,8 +22,8 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.data.elasticsearch.core.AggregationsContainer;
|
import org.springframework.data.elasticsearch.core.AggregationsContainer;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -19,12 +19,12 @@ import co.elastic.clients.elasticsearch.ElasticsearchClient;
|
|||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.beans.factory.DisposableBean;
|
import org.springframework.beans.factory.DisposableBean;
|
||||||
import org.springframework.beans.factory.FactoryBean;
|
import org.springframework.beans.factory.FactoryBean;
|
||||||
import org.springframework.beans.factory.FactoryBeanNotInitializedException;
|
import org.springframework.beans.factory.FactoryBeanNotInitializedException;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
import org.springframework.data.elasticsearch.client.ClientConfiguration;
|
import org.springframework.data.elasticsearch.client.ClientConfiguration;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -15,38 +15,44 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.elasticsearch.client.elc;
|
package org.springframework.data.elasticsearch.client.elc;
|
||||||
|
|
||||||
import static org.springframework.data.elasticsearch.client.elc.rest5_client.Rest5Clients.*;
|
|
||||||
import static org.springframework.data.elasticsearch.client.elc.rest_client.RestClients.*;
|
|
||||||
|
|
||||||
import co.elastic.clients.elasticsearch.ElasticsearchClient;
|
import co.elastic.clients.elasticsearch.ElasticsearchClient;
|
||||||
import co.elastic.clients.json.JsonpMapper;
|
import co.elastic.clients.json.JsonpMapper;
|
||||||
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
|
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
|
||||||
import co.elastic.clients.transport.ElasticsearchTransport;
|
import co.elastic.clients.transport.ElasticsearchTransport;
|
||||||
import co.elastic.clients.transport.TransportOptions;
|
import co.elastic.clients.transport.TransportOptions;
|
||||||
|
import co.elastic.clients.transport.TransportUtils;
|
||||||
import co.elastic.clients.transport.Version;
|
import co.elastic.clients.transport.Version;
|
||||||
import co.elastic.clients.transport.rest5_client.Rest5ClientOptions;
|
|
||||||
import co.elastic.clients.transport.rest5_client.Rest5ClientTransport;
|
|
||||||
import co.elastic.clients.transport.rest5_client.low_level.RequestOptions;
|
|
||||||
import co.elastic.clients.transport.rest5_client.low_level.Rest5Client;
|
|
||||||
import co.elastic.clients.transport.rest_client.RestClientOptions;
|
import co.elastic.clients.transport.rest_client.RestClientOptions;
|
||||||
import co.elastic.clients.transport.rest_client.RestClientTransport;
|
import co.elastic.clients.transport.rest_client.RestClientTransport;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.apache.http.HttpHost;
|
||||||
|
import org.apache.http.HttpRequest;
|
||||||
|
import org.apache.http.HttpRequestInterceptor;
|
||||||
|
import org.apache.http.client.config.RequestConfig;
|
||||||
import org.apache.http.entity.ContentType;
|
import org.apache.http.entity.ContentType;
|
||||||
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
|
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
|
||||||
|
import org.apache.http.message.BasicHeader;
|
||||||
import org.apache.http.message.BasicNameValuePair;
|
import org.apache.http.message.BasicNameValuePair;
|
||||||
|
import org.apache.http.protocol.HttpContext;
|
||||||
|
import org.elasticsearch.client.RequestOptions;
|
||||||
import org.elasticsearch.client.RestClient;
|
import org.elasticsearch.client.RestClient;
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.elasticsearch.client.RestClientBuilder;
|
||||||
import org.springframework.data.elasticsearch.client.ClientConfiguration;
|
import org.springframework.data.elasticsearch.client.ClientConfiguration;
|
||||||
import org.springframework.data.elasticsearch.support.VersionInfo;
|
import org.springframework.data.elasticsearch.support.HttpHeaders;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility class to create the different Elasticsearch clients. The RestClient class is the one used in Elasticsearch
|
* Utility class to create the different Elasticsearch clients
|
||||||
* until version 9, it is still available, but it's use is deprecated. The Rest5Client class is the one that should be
|
|
||||||
* used from Elasticsearch 9 on.
|
|
||||||
*
|
*
|
||||||
* @author Peter-Josef Meisch
|
* @author Peter-Josef Meisch
|
||||||
* @since 4.4
|
* @since 4.4
|
||||||
@ -113,32 +119,18 @@ public final class ElasticsearchClients {
|
|||||||
*
|
*
|
||||||
* @param restClient the underlying {@link RestClient}
|
* @param restClient the underlying {@link RestClient}
|
||||||
* @return the {@link ReactiveElasticsearchClient}
|
* @return the {@link ReactiveElasticsearchClient}
|
||||||
* @deprecated since 6.0, use the version with a Rest5Client.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated(since = "6.0", forRemoval = true)
|
|
||||||
public static ReactiveElasticsearchClient createReactive(RestClient restClient) {
|
public static ReactiveElasticsearchClient createReactive(RestClient restClient) {
|
||||||
return createReactive(restClient, null, DEFAULT_JSONP_MAPPER);
|
return createReactive(restClient, null, DEFAULT_JSONP_MAPPER);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link ReactiveElasticsearchClient}.
|
|
||||||
*
|
|
||||||
* @param rest5Client the underlying {@link RestClient}
|
|
||||||
* @return the {@link ReactiveElasticsearchClient}
|
|
||||||
*/
|
|
||||||
public static ReactiveElasticsearchClient createReactive(Rest5Client rest5Client) {
|
|
||||||
return createReactive(rest5Client, null, DEFAULT_JSONP_MAPPER);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link ReactiveElasticsearchClient}.
|
* Creates a new {@link ReactiveElasticsearchClient}.
|
||||||
*
|
*
|
||||||
* @param restClient the underlying {@link RestClient}
|
* @param restClient the underlying {@link RestClient}
|
||||||
* @param transportOptions options to be added to each request.
|
* @param transportOptions options to be added to each request.
|
||||||
* @return the {@link ReactiveElasticsearchClient}
|
* @return the {@link ReactiveElasticsearchClient}
|
||||||
* @deprecated since 6.0, use the version with a Rest5Client.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated(since = "6.0", forRemoval = true)
|
|
||||||
public static ReactiveElasticsearchClient createReactive(RestClient restClient,
|
public static ReactiveElasticsearchClient createReactive(RestClient restClient,
|
||||||
@Nullable TransportOptions transportOptions, JsonpMapper jsonpMapper) {
|
@Nullable TransportOptions transportOptions, JsonpMapper jsonpMapper) {
|
||||||
|
|
||||||
@ -147,21 +139,6 @@ public final class ElasticsearchClients {
|
|||||||
var transport = getElasticsearchTransport(restClient, REACTIVE_CLIENT, transportOptions, jsonpMapper);
|
var transport = getElasticsearchTransport(restClient, REACTIVE_CLIENT, transportOptions, jsonpMapper);
|
||||||
return createReactive(transport);
|
return createReactive(transport);
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Creates a new {@link ReactiveElasticsearchClient}.
|
|
||||||
*
|
|
||||||
* @param rest5Client the underlying {@link RestClient}
|
|
||||||
* @param transportOptions options to be added to each request.
|
|
||||||
* @return the {@link ReactiveElasticsearchClient}
|
|
||||||
*/
|
|
||||||
public static ReactiveElasticsearchClient createReactive(Rest5Client rest5Client,
|
|
||||||
@Nullable TransportOptions transportOptions, JsonpMapper jsonpMapper) {
|
|
||||||
|
|
||||||
Assert.notNull(rest5Client, "restClient must not be null");
|
|
||||||
|
|
||||||
var transport = getElasticsearchTransport(rest5Client, REACTIVE_CLIENT, transportOptions, jsonpMapper);
|
|
||||||
return createReactive(transport);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link ReactiveElasticsearchClient} that uses the given {@link ElasticsearchTransport}.
|
* Creates a new {@link ReactiveElasticsearchClient} that uses the given {@link ElasticsearchTransport}.
|
||||||
@ -179,21 +156,17 @@ public final class ElasticsearchClients {
|
|||||||
|
|
||||||
// region imperative client
|
// region imperative client
|
||||||
/**
|
/**
|
||||||
* Creates a new imperative {@link ElasticsearchClient}. This uses a RestClient, if the old RestClient is needed, this
|
* Creates a new imperative {@link ElasticsearchClient}
|
||||||
* must be created with the {@link org.springframework.data.elasticsearch.client.elc.rest_client.RestClients} class
|
|
||||||
* and passed in as parameter.
|
|
||||||
*
|
*
|
||||||
* @param clientConfiguration configuration options, must not be {@literal null}.
|
* @param clientConfiguration configuration options, must not be {@literal null}.
|
||||||
* @return the {@link ElasticsearchClient}
|
* @return the {@link ElasticsearchClient}
|
||||||
*/
|
*/
|
||||||
public static ElasticsearchClient createImperative(ClientConfiguration clientConfiguration) {
|
public static ElasticsearchClient createImperative(ClientConfiguration clientConfiguration) {
|
||||||
return createImperative(getRest5Client(clientConfiguration), null, DEFAULT_JSONP_MAPPER);
|
return createImperative(getRestClient(clientConfiguration), null, DEFAULT_JSONP_MAPPER);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new imperative {@link ElasticsearchClient}. This uses a RestClient, if the old RestClient is needed, this
|
* Creates a new imperative {@link ElasticsearchClient}
|
||||||
* must be created with the {@link org.springframework.data.elasticsearch.client.elc.rest_client.RestClients} class
|
|
||||||
* and passed in as parameter.
|
|
||||||
*
|
*
|
||||||
* @param clientConfiguration configuration options, must not be {@literal null}.
|
* @param clientConfiguration configuration options, must not be {@literal null}.
|
||||||
* @param transportOptions options to be added to each request.
|
* @param transportOptions options to be added to each request.
|
||||||
@ -201,7 +174,7 @@ public final class ElasticsearchClients {
|
|||||||
*/
|
*/
|
||||||
public static ElasticsearchClient createImperative(ClientConfiguration clientConfiguration,
|
public static ElasticsearchClient createImperative(ClientConfiguration clientConfiguration,
|
||||||
TransportOptions transportOptions) {
|
TransportOptions transportOptions) {
|
||||||
return createImperative(getRest5Client(clientConfiguration), transportOptions, DEFAULT_JSONP_MAPPER);
|
return createImperative(getRestClient(clientConfiguration), transportOptions, DEFAULT_JSONP_MAPPER);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -209,23 +182,11 @@ public final class ElasticsearchClients {
|
|||||||
*
|
*
|
||||||
* @param restClient the RestClient to use
|
* @param restClient the RestClient to use
|
||||||
* @return the {@link ElasticsearchClient}
|
* @return the {@link ElasticsearchClient}
|
||||||
* @deprecated since 6.0, use the version with a Rest5Client.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated(since = "6.0", forRemoval = true)
|
|
||||||
public static ElasticsearchClient createImperative(RestClient restClient) {
|
public static ElasticsearchClient createImperative(RestClient restClient) {
|
||||||
return createImperative(restClient, null, DEFAULT_JSONP_MAPPER);
|
return createImperative(restClient, null, DEFAULT_JSONP_MAPPER);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new imperative {@link ElasticsearchClient}
|
|
||||||
*
|
|
||||||
* @param rest5Client the Rest5Client to use
|
|
||||||
* @return the {@link ElasticsearchClient}
|
|
||||||
*/
|
|
||||||
public static ElasticsearchClient createImperative(Rest5Client rest5Client) {
|
|
||||||
return createImperative(rest5Client, null, DEFAULT_JSONP_MAPPER);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new imperative {@link ElasticsearchClient}
|
* Creates a new imperative {@link ElasticsearchClient}
|
||||||
*
|
*
|
||||||
@ -233,9 +194,7 @@ public final class ElasticsearchClients {
|
|||||||
* @param transportOptions options to be added to each request.
|
* @param transportOptions options to be added to each request.
|
||||||
* @param jsonpMapper the mapper for the transport to use
|
* @param jsonpMapper the mapper for the transport to use
|
||||||
* @return the {@link ElasticsearchClient}
|
* @return the {@link ElasticsearchClient}
|
||||||
* @deprecated since 6.0, use the version with a Rest5Client.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated(since = "6.0", forRemoval = true)
|
|
||||||
public static ElasticsearchClient createImperative(RestClient restClient, @Nullable TransportOptions transportOptions,
|
public static ElasticsearchClient createImperative(RestClient restClient, @Nullable TransportOptions transportOptions,
|
||||||
JsonpMapper jsonpMapper) {
|
JsonpMapper jsonpMapper) {
|
||||||
|
|
||||||
@ -247,27 +206,6 @@ public final class ElasticsearchClients {
|
|||||||
return createImperative(transport);
|
return createImperative(transport);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new imperative {@link ElasticsearchClient}
|
|
||||||
*
|
|
||||||
* @param rest5Client the Rest5Client to use
|
|
||||||
* @param transportOptions options to be added to each request.
|
|
||||||
* @param jsonpMapper the mapper for the transport to use
|
|
||||||
* @return the {@link ElasticsearchClient}
|
|
||||||
* @since 6.0
|
|
||||||
*/
|
|
||||||
public static ElasticsearchClient createImperative(Rest5Client rest5Client,
|
|
||||||
@Nullable TransportOptions transportOptions,
|
|
||||||
JsonpMapper jsonpMapper) {
|
|
||||||
|
|
||||||
Assert.notNull(rest5Client, "restClient must not be null");
|
|
||||||
|
|
||||||
ElasticsearchTransport transport = getElasticsearchTransport(rest5Client, IMPERATIVE_CLIENT, transportOptions,
|
|
||||||
jsonpMapper);
|
|
||||||
|
|
||||||
return createImperative(transport);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link ElasticsearchClient} that uses the given {@link ElasticsearchTransport}.
|
* Creates a new {@link ElasticsearchClient} that uses the given {@link ElasticsearchTransport}.
|
||||||
*
|
*
|
||||||
@ -282,6 +220,96 @@ public final class ElasticsearchClients {
|
|||||||
}
|
}
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
|
// region low level RestClient
|
||||||
|
private static RestClientOptions.Builder getRestClientOptionsBuilder(@Nullable TransportOptions transportOptions) {
|
||||||
|
|
||||||
|
if (transportOptions instanceof RestClientOptions restClientOptions) {
|
||||||
|
return restClientOptions.toBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
var builder = new RestClientOptions.Builder(RequestOptions.DEFAULT.toBuilder());
|
||||||
|
|
||||||
|
if (transportOptions != null) {
|
||||||
|
transportOptions.headers().forEach(header -> builder.addHeader(header.getKey(), header.getValue()));
|
||||||
|
transportOptions.queryParameters().forEach(builder::setParameter);
|
||||||
|
builder.onWarnings(transportOptions.onWarnings());
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a low level {@link RestClient} for the given configuration.
|
||||||
|
*
|
||||||
|
* @param clientConfiguration must not be {@literal null}
|
||||||
|
* @return the {@link RestClient}
|
||||||
|
*/
|
||||||
|
public static RestClient getRestClient(ClientConfiguration clientConfiguration) {
|
||||||
|
return getRestClientBuilder(clientConfiguration).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RestClientBuilder getRestClientBuilder(ClientConfiguration clientConfiguration) {
|
||||||
|
HttpHost[] httpHosts = formattedHosts(clientConfiguration.getEndpoints(), clientConfiguration.useSsl()).stream()
|
||||||
|
.map(HttpHost::create).toArray(HttpHost[]::new);
|
||||||
|
RestClientBuilder builder = RestClient.builder(httpHosts);
|
||||||
|
|
||||||
|
if (clientConfiguration.getPathPrefix() != null) {
|
||||||
|
builder.setPathPrefix(clientConfiguration.getPathPrefix());
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpHeaders headers = clientConfiguration.getDefaultHeaders();
|
||||||
|
|
||||||
|
if (!headers.isEmpty()) {
|
||||||
|
builder.setDefaultHeaders(toHeaderArray(headers));
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.setHttpClientConfigCallback(clientBuilder -> {
|
||||||
|
if (clientConfiguration.getCaFingerprint().isPresent()) {
|
||||||
|
clientBuilder
|
||||||
|
.setSSLContext(TransportUtils.sslContextFromCaFingerprint(clientConfiguration.getCaFingerprint().get()));
|
||||||
|
}
|
||||||
|
clientConfiguration.getSslContext().ifPresent(clientBuilder::setSSLContext);
|
||||||
|
clientConfiguration.getHostNameVerifier().ifPresent(clientBuilder::setSSLHostnameVerifier);
|
||||||
|
clientBuilder.addInterceptorLast(new CustomHeaderInjector(clientConfiguration.getHeadersSupplier()));
|
||||||
|
|
||||||
|
RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();
|
||||||
|
Duration connectTimeout = clientConfiguration.getConnectTimeout();
|
||||||
|
|
||||||
|
if (!connectTimeout.isNegative()) {
|
||||||
|
requestConfigBuilder.setConnectTimeout(Math.toIntExact(connectTimeout.toMillis()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Duration socketTimeout = clientConfiguration.getSocketTimeout();
|
||||||
|
|
||||||
|
if (!socketTimeout.isNegative()) {
|
||||||
|
requestConfigBuilder.setSocketTimeout(Math.toIntExact(socketTimeout.toMillis()));
|
||||||
|
requestConfigBuilder.setConnectionRequestTimeout(Math.toIntExact(socketTimeout.toMillis()));
|
||||||
|
}
|
||||||
|
|
||||||
|
clientBuilder.setDefaultRequestConfig(requestConfigBuilder.build());
|
||||||
|
|
||||||
|
clientConfiguration.getProxy().map(HttpHost::create).ifPresent(clientBuilder::setProxy);
|
||||||
|
|
||||||
|
for (ClientConfiguration.ClientConfigurationCallback<?> clientConfigurer : clientConfiguration
|
||||||
|
.getClientConfigurers()) {
|
||||||
|
if (clientConfigurer instanceof ElasticsearchHttpClientConfigurationCallback restClientConfigurationCallback) {
|
||||||
|
clientBuilder = restClientConfigurationCallback.configure(clientBuilder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return clientBuilder;
|
||||||
|
});
|
||||||
|
|
||||||
|
for (ClientConfiguration.ClientConfigurationCallback<?> clientConfigurationCallback : clientConfiguration
|
||||||
|
.getClientConfigurers()) {
|
||||||
|
if (clientConfigurationCallback instanceof ElasticsearchRestClientConfigurationCallback configurationCallback) {
|
||||||
|
builder = configurationCallback.configure(builder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
// endregion
|
||||||
|
|
||||||
// region Elasticsearch transport
|
// region Elasticsearch transport
|
||||||
/**
|
/**
|
||||||
* Creates an {@link ElasticsearchTransport} that will use the given client that additionally is customized with a
|
* Creates an {@link ElasticsearchTransport} that will use the given client that additionally is customized with a
|
||||||
@ -292,9 +320,7 @@ public final class ElasticsearchClients {
|
|||||||
* @param transportOptions options for the transport
|
* @param transportOptions options for the transport
|
||||||
* @param jsonpMapper mapper for the transport
|
* @param jsonpMapper mapper for the transport
|
||||||
* @return ElasticsearchTransport
|
* @return ElasticsearchTransport
|
||||||
* @deprecated since 6.0, use the version taking a Rest5Client
|
|
||||||
*/
|
*/
|
||||||
@Deprecated(since = "6.0", forRemoval = true)
|
|
||||||
public static ElasticsearchTransport getElasticsearchTransport(RestClient restClient, String clientType,
|
public static ElasticsearchTransport getElasticsearchTransport(RestClient restClient, String clientType,
|
||||||
@Nullable TransportOptions transportOptions, JsonpMapper jsonpMapper) {
|
@Nullable TransportOptions transportOptions, JsonpMapper jsonpMapper) {
|
||||||
|
|
||||||
@ -303,7 +329,7 @@ public final class ElasticsearchClients {
|
|||||||
Assert.notNull(jsonpMapper, "jsonpMapper must not be null");
|
Assert.notNull(jsonpMapper, "jsonpMapper must not be null");
|
||||||
|
|
||||||
TransportOptions.Builder transportOptionsBuilder = transportOptions != null ? transportOptions.toBuilder()
|
TransportOptions.Builder transportOptionsBuilder = transportOptions != null ? transportOptions.toBuilder()
|
||||||
: new RestClientOptions(org.elasticsearch.client.RequestOptions.DEFAULT, false).toBuilder();
|
: new RestClientOptions(RequestOptions.DEFAULT).toBuilder();
|
||||||
|
|
||||||
RestClientOptions.Builder restClientOptionsBuilder = getRestClientOptionsBuilder(transportOptions);
|
RestClientOptions.Builder restClientOptionsBuilder = getRestClientOptionsBuilder(transportOptions);
|
||||||
|
|
||||||
@ -327,35 +353,70 @@ public final class ElasticsearchClients {
|
|||||||
|
|
||||||
return new RestClientTransport(restClient, jsonpMapper, restClientOptionsBuilder.build());
|
return new RestClientTransport(restClient, jsonpMapper, restClientOptionsBuilder.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an {@link ElasticsearchTransport} that will use the given client that additionally is customized with a
|
|
||||||
* header to contain the clientType
|
|
||||||
*
|
|
||||||
* @param rest5Client the client to use
|
|
||||||
* @param clientType the client type to pass in each request as header
|
|
||||||
* @param transportOptions options for the transport
|
|
||||||
* @param jsonpMapper mapper for the transport
|
|
||||||
* @return ElasticsearchTransport
|
|
||||||
*/
|
|
||||||
public static ElasticsearchTransport getElasticsearchTransport(Rest5Client rest5Client, String clientType,
|
|
||||||
@Nullable TransportOptions transportOptions, JsonpMapper jsonpMapper) {
|
|
||||||
|
|
||||||
Assert.notNull(rest5Client, "restClient must not be null");
|
|
||||||
Assert.notNull(clientType, "clientType must not be null");
|
|
||||||
Assert.notNull(jsonpMapper, "jsonpMapper must not be null");
|
|
||||||
|
|
||||||
TransportOptions.Builder transportOptionsBuilder = transportOptions != null ? transportOptions.toBuilder()
|
|
||||||
: new Rest5ClientOptions(RequestOptions.DEFAULT, false).toBuilder();
|
|
||||||
|
|
||||||
Rest5ClientOptions.Builder rest5ClientOptionsBuilder = getRest5ClientOptionsBuilder(transportOptions);
|
|
||||||
|
|
||||||
rest5ClientOptionsBuilder.addHeader(X_SPRING_DATA_ELASTICSEARCH_CLIENT,
|
|
||||||
VersionInfo.clientVersions() + " / " + clientType);
|
|
||||||
|
|
||||||
return new Rest5ClientTransport(rest5Client, jsonpMapper, rest5ClientOptionsBuilder.build());
|
|
||||||
}
|
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// todo #3117 remove and document that ElasticsearchHttpClientConfigurationCallback has been move to RestClients.
|
private static List<String> formattedHosts(List<InetSocketAddress> hosts, boolean useSsl) {
|
||||||
|
return hosts.stream().map(it -> (useSsl ? "https" : "http") + "://" + it.getHostString() + ':' + it.getPort())
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static org.apache.http.Header[] toHeaderArray(HttpHeaders headers) {
|
||||||
|
return headers.entrySet().stream() //
|
||||||
|
.flatMap(entry -> entry.getValue().stream() //
|
||||||
|
.map(value -> new BasicHeader(entry.getKey(), value))) //
|
||||||
|
.toArray(org.apache.http.Header[]::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interceptor to inject custom supplied headers.
|
||||||
|
*
|
||||||
|
* @since 4.4
|
||||||
|
*/
|
||||||
|
private record CustomHeaderInjector(Supplier<HttpHeaders> headersSupplier) implements HttpRequestInterceptor {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(HttpRequest request, HttpContext context) {
|
||||||
|
HttpHeaders httpHeaders = headersSupplier.get();
|
||||||
|
|
||||||
|
if (httpHeaders != null && !httpHeaders.isEmpty()) {
|
||||||
|
Arrays.stream(toHeaderArray(httpHeaders)).forEach(request::addHeader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link org.springframework.data.elasticsearch.client.ClientConfiguration.ClientConfigurationCallback} to configure
|
||||||
|
* the Elasticsearch RestClient's Http client with a {@link HttpAsyncClientBuilder}
|
||||||
|
*
|
||||||
|
* @since 4.4
|
||||||
|
*/
|
||||||
|
public interface ElasticsearchHttpClientConfigurationCallback
|
||||||
|
extends ClientConfiguration.ClientConfigurationCallback<HttpAsyncClientBuilder> {
|
||||||
|
|
||||||
|
static ElasticsearchHttpClientConfigurationCallback from(
|
||||||
|
Function<HttpAsyncClientBuilder, HttpAsyncClientBuilder> httpClientBuilderCallback) {
|
||||||
|
|
||||||
|
Assert.notNull(httpClientBuilderCallback, "httpClientBuilderCallback must not be null");
|
||||||
|
|
||||||
|
return httpClientBuilderCallback::apply;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link org.springframework.data.elasticsearch.client.ClientConfiguration.ClientConfigurationCallback} to configure
|
||||||
|
* the RestClient client with a {@link RestClientBuilder}
|
||||||
|
*
|
||||||
|
* @since 5.0
|
||||||
|
*/
|
||||||
|
public interface ElasticsearchRestClientConfigurationCallback
|
||||||
|
extends ClientConfiguration.ClientConfigurationCallback<RestClientBuilder> {
|
||||||
|
|
||||||
|
static ElasticsearchRestClientConfigurationCallback from(
|
||||||
|
Function<RestClientBuilder, RestClientBuilder> restClientBuilderCallback) {
|
||||||
|
|
||||||
|
Assert.notNull(restClientBuilderCallback, "restClientBuilderCallback must not be null");
|
||||||
|
|
||||||
|
return restClientBuilderCallback::apply;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,13 +20,12 @@ import co.elastic.clients.json.JsonpMapper;
|
|||||||
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
|
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
|
||||||
import co.elastic.clients.transport.ElasticsearchTransport;
|
import co.elastic.clients.transport.ElasticsearchTransport;
|
||||||
import co.elastic.clients.transport.TransportOptions;
|
import co.elastic.clients.transport.TransportOptions;
|
||||||
import co.elastic.clients.transport.rest5_client.Rest5ClientOptions;
|
import co.elastic.clients.transport.rest_client.RestClientOptions;
|
||||||
import co.elastic.clients.transport.rest5_client.low_level.RequestOptions;
|
|
||||||
import co.elastic.clients.transport.rest5_client.low_level.Rest5Client;
|
|
||||||
|
|
||||||
|
import org.elasticsearch.client.RequestOptions;
|
||||||
|
import org.elasticsearch.client.RestClient;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.data.elasticsearch.client.ClientConfiguration;
|
import org.springframework.data.elasticsearch.client.ClientConfiguration;
|
||||||
import org.springframework.data.elasticsearch.client.elc.rest5_client.Rest5Clients;
|
|
||||||
import org.springframework.data.elasticsearch.config.ElasticsearchConfigurationSupport;
|
import org.springframework.data.elasticsearch.config.ElasticsearchConfigurationSupport;
|
||||||
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
||||||
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
||||||
@ -39,9 +38,7 @@ import com.fasterxml.jackson.databind.SerializationFeature;
|
|||||||
/**
|
/**
|
||||||
* Base class for a @{@link org.springframework.context.annotation.Configuration} class to set up the Elasticsearch
|
* Base class for a @{@link org.springframework.context.annotation.Configuration} class to set up the Elasticsearch
|
||||||
* connection using the Elasticsearch Client. This class exposes different parts of the setup as Spring beans. Deriving
|
* connection using the Elasticsearch Client. This class exposes different parts of the setup as Spring beans. Deriving
|
||||||
* classes must provide the {@link ClientConfiguration} to use. From Version 6.0 on, this class uses the new Rest5Client
|
* classes must provide the {@link ClientConfiguration} to use.
|
||||||
* from Elasticsearch 9. The old implementation using the RestClient is still available under the name
|
|
||||||
* {@link ElasticsearchLegacyRestClientConfiguration}.
|
|
||||||
*
|
*
|
||||||
* @author Peter-Josef Meisch
|
* @author Peter-Josef Meisch
|
||||||
* @since 4.4
|
* @since 4.4
|
||||||
@ -63,27 +60,27 @@ public abstract class ElasticsearchConfiguration extends ElasticsearchConfigurat
|
|||||||
* @return RestClient
|
* @return RestClient
|
||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
public Rest5Client elasticsearchRest5Client(ClientConfiguration clientConfiguration) {
|
public RestClient elasticsearchRestClient(ClientConfiguration clientConfiguration) {
|
||||||
|
|
||||||
Assert.notNull(clientConfiguration, "clientConfiguration must not be null");
|
Assert.notNull(clientConfiguration, "clientConfiguration must not be null");
|
||||||
|
|
||||||
return Rest5Clients.getRest5Client(clientConfiguration);
|
return ElasticsearchClients.getRestClient(clientConfiguration);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides the Elasticsearch transport to be used. The default implementation uses the {@link Rest5Client} bean and
|
* Provides the Elasticsearch transport to be used. The default implementation uses the {@link RestClient} bean and
|
||||||
* the {@link JsonpMapper} bean provided in this class.
|
* the {@link JsonpMapper} bean provided in this class.
|
||||||
*
|
*
|
||||||
* @return the {@link ElasticsearchTransport}
|
* @return the {@link ElasticsearchTransport}
|
||||||
* @since 5.2
|
* @since 5.2
|
||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
public ElasticsearchTransport elasticsearchTransport(Rest5Client rest5Client, JsonpMapper jsonpMapper) {
|
public ElasticsearchTransport elasticsearchTransport(RestClient restClient, JsonpMapper jsonpMapper) {
|
||||||
|
|
||||||
Assert.notNull(rest5Client, "restClient must not be null");
|
Assert.notNull(restClient, "restClient must not be null");
|
||||||
Assert.notNull(jsonpMapper, "jsonpMapper must not be null");
|
Assert.notNull(jsonpMapper, "jsonpMapper must not be null");
|
||||||
|
|
||||||
return ElasticsearchClients.getElasticsearchTransport(rest5Client, ElasticsearchClients.IMPERATIVE_CLIENT,
|
return ElasticsearchClients.getElasticsearchTransport(restClient, ElasticsearchClients.IMPERATIVE_CLIENT,
|
||||||
transportOptions(), jsonpMapper);
|
transportOptions(), jsonpMapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,7 +115,7 @@ public abstract class ElasticsearchConfiguration extends ElasticsearchConfigurat
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides the JsonpMapper bean that is used in the {@link #elasticsearchTransport(Rest5Client, JsonpMapper)} method.
|
* Provides the JsonpMapper bean that is used in the {@link #elasticsearchTransport(RestClient, JsonpMapper)} method.
|
||||||
*
|
*
|
||||||
* @return the {@link JsonpMapper} to use
|
* @return the {@link JsonpMapper} to use
|
||||||
* @since 5.2
|
* @since 5.2
|
||||||
@ -138,6 +135,6 @@ public abstract class ElasticsearchConfiguration extends ElasticsearchConfigurat
|
|||||||
* @return the options that should be added to every request. Must not be {@literal null}
|
* @return the options that should be added to every request. Must not be {@literal null}
|
||||||
*/
|
*/
|
||||||
public TransportOptions transportOptions() {
|
public TransportOptions transportOptions() {
|
||||||
return new Rest5ClientOptions(RequestOptions.DEFAULT, false);
|
return new RestClientOptions(RequestOptions.DEFAULT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -119,19 +119,14 @@ public class ElasticsearchExceptionTranslator implements PersistenceExceptionTra
|
|||||||
String message = null;
|
String message = null;
|
||||||
|
|
||||||
if (exception instanceof ResponseException responseException) {
|
if (exception instanceof ResponseException responseException) {
|
||||||
// this code is for the old RestClient
|
|
||||||
status = responseException.getResponse().getStatusLine().getStatusCode();
|
status = responseException.getResponse().getStatusLine().getStatusCode();
|
||||||
message = responseException.getMessage();
|
message = responseException.getMessage();
|
||||||
} else if (exception instanceof ElasticsearchException elasticsearchException) {
|
|
||||||
// using the RestClient throws this
|
|
||||||
status = elasticsearchException.status();
|
|
||||||
message = elasticsearchException.getMessage();
|
|
||||||
} else if (exception.getCause() != null) {
|
} else if (exception.getCause() != null) {
|
||||||
checkForConflictException(exception.getCause());
|
checkForConflictException(exception.getCause());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status != null && message != null) {
|
if (status != null && message != null) {
|
||||||
if (status == 409 && message.contains("version_conflict_engine_exception"))
|
if (status == 409 && message.contains("type\":\"version_conflict_engine_exception"))
|
||||||
if (message.contains("version conflict, required seqNo")) {
|
if (message.contains("version conflict, required seqNo")) {
|
||||||
throw new OptimisticLockingFailureException("Cannot index a document due to seq_no+primary_term conflict",
|
throw new OptimisticLockingFailureException("Cannot index a document due to seq_no+primary_term conflict",
|
||||||
exception);
|
exception);
|
||||||
|
@ -1,144 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2021-2025 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.springframework.data.elasticsearch.client.elc;
|
|
||||||
|
|
||||||
import co.elastic.clients.elasticsearch.ElasticsearchClient;
|
|
||||||
import co.elastic.clients.json.JsonpMapper;
|
|
||||||
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
|
|
||||||
import co.elastic.clients.transport.ElasticsearchTransport;
|
|
||||||
import co.elastic.clients.transport.TransportOptions;
|
|
||||||
import co.elastic.clients.transport.rest_client.RestClientOptions;
|
|
||||||
|
|
||||||
import org.elasticsearch.client.RequestOptions;
|
|
||||||
import org.elasticsearch.client.RestClient;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.data.elasticsearch.client.ClientConfiguration;
|
|
||||||
import org.springframework.data.elasticsearch.client.elc.rest_client.RestClients;
|
|
||||||
import org.springframework.data.elasticsearch.config.ElasticsearchConfigurationSupport;
|
|
||||||
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
|
||||||
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base class for a @{@link org.springframework.context.annotation.Configuration} class to set up the Elasticsearch
|
|
||||||
* connection using the Elasticsearch Client. This class exposes different parts of the setup as Spring beans. Deriving
|
|
||||||
* classes must provide the {@link ClientConfiguration} to use. <br/>
|
|
||||||
* This class uses the Elasticsearch RestClient which was replaced by the Rest5Client in Elasticsearch 9. It is still
|
|
||||||
* available here but deprecated.
|
|
||||||
*
|
|
||||||
* @author Peter-Josef Meisch
|
|
||||||
* @since 4.4
|
|
||||||
* @deprecated since 6.0, use {@link ElasticsearchConfiguration}
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.0", forRemoval=true)
|
|
||||||
public abstract class ElasticsearchLegacyRestClientConfiguration extends ElasticsearchConfigurationSupport {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Must be implemented by deriving classes to provide the {@link ClientConfiguration}.
|
|
||||||
*
|
|
||||||
* @return configuration, must not be {@literal null}
|
|
||||||
*/
|
|
||||||
@Bean(name = "elasticsearchClientConfiguration")
|
|
||||||
public abstract ClientConfiguration clientConfiguration();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides the underlying low level Elasticsearch RestClient.
|
|
||||||
*
|
|
||||||
* @param clientConfiguration configuration for the client, must not be {@literal null}
|
|
||||||
* @return RestClient
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public RestClient elasticsearchRestClient(ClientConfiguration clientConfiguration) {
|
|
||||||
|
|
||||||
Assert.notNull(clientConfiguration, "clientConfiguration must not be null");
|
|
||||||
|
|
||||||
return RestClients.getRestClient(clientConfiguration);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides the Elasticsearch transport to be used. The default implementation uses the {@link RestClient} bean and
|
|
||||||
* the {@link JsonpMapper} bean provided in this class.
|
|
||||||
*
|
|
||||||
* @return the {@link ElasticsearchTransport}
|
|
||||||
* @since 5.2
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public ElasticsearchTransport elasticsearchTransport(RestClient restClient, JsonpMapper jsonpMapper) {
|
|
||||||
|
|
||||||
Assert.notNull(restClient, "restClient must not be null");
|
|
||||||
Assert.notNull(jsonpMapper, "jsonpMapper must not be null");
|
|
||||||
|
|
||||||
return ElasticsearchClients.getElasticsearchTransport(restClient, ElasticsearchClients.IMPERATIVE_CLIENT,
|
|
||||||
transportOptions(), jsonpMapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides the {@link ElasticsearchClient} to be used.
|
|
||||||
*
|
|
||||||
* @param transport the {@link ElasticsearchTransport} to use
|
|
||||||
* @return ElasticsearchClient instance
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public ElasticsearchClient elasticsearchClient(ElasticsearchTransport transport) {
|
|
||||||
|
|
||||||
Assert.notNull(transport, "transport must not be null");
|
|
||||||
|
|
||||||
return ElasticsearchClients.createImperative(transport);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a {@link ElasticsearchOperations} implementation using an {@link ElasticsearchClient}.
|
|
||||||
*
|
|
||||||
* @return never {@literal null}.
|
|
||||||
*/
|
|
||||||
@Bean(name = { "elasticsearchOperations", "elasticsearchTemplate" })
|
|
||||||
public ElasticsearchOperations elasticsearchOperations(ElasticsearchConverter elasticsearchConverter,
|
|
||||||
ElasticsearchClient elasticsearchClient) {
|
|
||||||
|
|
||||||
ElasticsearchTemplate template = new ElasticsearchTemplate(elasticsearchClient, elasticsearchConverter);
|
|
||||||
template.setRefreshPolicy(refreshPolicy());
|
|
||||||
|
|
||||||
return template;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides the JsonpMapper bean that is used in the {@link #elasticsearchTransport(RestClient, JsonpMapper)} method.
|
|
||||||
*
|
|
||||||
* @return the {@link JsonpMapper} to use
|
|
||||||
* @since 5.2
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public JsonpMapper jsonpMapper() {
|
|
||||||
// we need to create our own objectMapper that keeps null values in order to provide the storeNullValue
|
|
||||||
// functionality. The one Elasticsearch would provide removes the nulls. We remove unwanted nulls before they get
|
|
||||||
// into this mapper, so we can safely keep them here.
|
|
||||||
var objectMapper = (new ObjectMapper())
|
|
||||||
.configure(SerializationFeature.INDENT_OUTPUT, false)
|
|
||||||
.setSerializationInclusion(JsonInclude.Include.ALWAYS);
|
|
||||||
return new JacksonJsonpMapper(objectMapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the options that should be added to every request. Must not be {@literal null}
|
|
||||||
*/
|
|
||||||
public TransportOptions transportOptions() {
|
|
||||||
return new RestClientOptions(RequestOptions.DEFAULT, false);
|
|
||||||
}
|
|
||||||
}
|
|
@ -23,8 +23,6 @@ import co.elastic.clients.elasticsearch.core.*;
|
|||||||
import co.elastic.clients.elasticsearch.core.bulk.BulkResponseItem;
|
import co.elastic.clients.elasticsearch.core.bulk.BulkResponseItem;
|
||||||
import co.elastic.clients.elasticsearch.core.msearch.MultiSearchResponseItem;
|
import co.elastic.clients.elasticsearch.core.msearch.MultiSearchResponseItem;
|
||||||
import co.elastic.clients.elasticsearch.core.search.ResponseBody;
|
import co.elastic.clients.elasticsearch.core.search.ResponseBody;
|
||||||
import co.elastic.clients.elasticsearch.sql.ElasticsearchSqlClient;
|
|
||||||
import co.elastic.clients.elasticsearch.sql.QueryResponse;
|
|
||||||
import co.elastic.clients.json.JsonpMapper;
|
import co.elastic.clients.json.JsonpMapper;
|
||||||
import co.elastic.clients.transport.Version;
|
import co.elastic.clients.transport.Version;
|
||||||
|
|
||||||
@ -40,7 +38,6 @@ import java.util.stream.Collectors;
|
|||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.data.elasticsearch.BulkFailureException;
|
import org.springframework.data.elasticsearch.BulkFailureException;
|
||||||
import org.springframework.data.elasticsearch.client.UnsupportedBackendOperation;
|
import org.springframework.data.elasticsearch.client.UnsupportedBackendOperation;
|
||||||
import org.springframework.data.elasticsearch.core.AbstractElasticsearchTemplate;
|
import org.springframework.data.elasticsearch.core.AbstractElasticsearchTemplate;
|
||||||
@ -59,7 +56,7 @@ import org.springframework.data.elasticsearch.core.query.UpdateResponse;
|
|||||||
import org.springframework.data.elasticsearch.core.reindex.ReindexRequest;
|
import org.springframework.data.elasticsearch.core.reindex.ReindexRequest;
|
||||||
import org.springframework.data.elasticsearch.core.reindex.ReindexResponse;
|
import org.springframework.data.elasticsearch.core.reindex.ReindexResponse;
|
||||||
import org.springframework.data.elasticsearch.core.script.Script;
|
import org.springframework.data.elasticsearch.core.script.Script;
|
||||||
import org.springframework.data.elasticsearch.core.sql.SqlResponse;
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -77,7 +74,6 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate {
|
|||||||
private static final Log LOGGER = LogFactory.getLog(ElasticsearchTemplate.class);
|
private static final Log LOGGER = LogFactory.getLog(ElasticsearchTemplate.class);
|
||||||
|
|
||||||
private final ElasticsearchClient client;
|
private final ElasticsearchClient client;
|
||||||
private final ElasticsearchSqlClient sqlClient;
|
|
||||||
private final RequestConverter requestConverter;
|
private final RequestConverter requestConverter;
|
||||||
private final ResponseConverter responseConverter;
|
private final ResponseConverter responseConverter;
|
||||||
private final JsonpMapper jsonpMapper;
|
private final JsonpMapper jsonpMapper;
|
||||||
@ -89,7 +85,6 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate {
|
|||||||
Assert.notNull(client, "client must not be null");
|
Assert.notNull(client, "client must not be null");
|
||||||
|
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.sqlClient = client.sql();
|
|
||||||
this.jsonpMapper = client._transport().jsonpMapper();
|
this.jsonpMapper = client._transport().jsonpMapper();
|
||||||
requestConverter = new RequestConverter(elasticsearchConverter, jsonpMapper);
|
requestConverter = new RequestConverter(elasticsearchConverter, jsonpMapper);
|
||||||
responseConverter = new ResponseConverter(jsonpMapper);
|
responseConverter = new ResponseConverter(jsonpMapper);
|
||||||
@ -102,7 +97,6 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate {
|
|||||||
Assert.notNull(client, "client must not be null");
|
Assert.notNull(client, "client must not be null");
|
||||||
|
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.sqlClient = client.sql();
|
|
||||||
this.jsonpMapper = client._transport().jsonpMapper();
|
this.jsonpMapper = client._transport().jsonpMapper();
|
||||||
requestConverter = new RequestConverter(elasticsearchConverter, jsonpMapper);
|
requestConverter = new RequestConverter(elasticsearchConverter, jsonpMapper);
|
||||||
responseConverter = new ResponseConverter(jsonpMapper);
|
responseConverter = new ResponseConverter(jsonpMapper);
|
||||||
@ -181,6 +175,19 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate {
|
|||||||
return delete(query, clazz, getIndexCoordinatesFor(clazz));
|
return delete(query, clazz, getIndexCoordinatesFor(clazz));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByQueryResponse delete(Query query, Class<?> clazz, IndexCoordinates index) {
|
||||||
|
|
||||||
|
Assert.notNull(query, "query must not be null");
|
||||||
|
|
||||||
|
DeleteByQueryRequest request = requestConverter.documentDeleteByQueryRequest(query, routingResolver.getRouting(),
|
||||||
|
clazz, index, getRefreshPolicy());
|
||||||
|
|
||||||
|
DeleteByQueryResponse response = execute(client -> client.deleteByQuery(request));
|
||||||
|
|
||||||
|
return responseConverter.byQueryResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByQueryResponse delete(DeleteQuery query, Class<?> clazz, IndexCoordinates index) {
|
public ByQueryResponse delete(DeleteQuery query, Class<?> clazz, IndexCoordinates index) {
|
||||||
Assert.notNull(query, "query must not be null");
|
Assert.notNull(query, "query must not be null");
|
||||||
@ -649,19 +656,6 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate {
|
|||||||
DeleteScriptRequest request = requestConverter.scriptDelete(name);
|
DeleteScriptRequest request = requestConverter.scriptDelete(name);
|
||||||
return execute(client -> client.deleteScript(request)).acknowledged();
|
return execute(client -> client.deleteScript(request)).acknowledged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public SqlResponse search(SqlQuery query) {
|
|
||||||
Assert.notNull(query, "Query must not be null.");
|
|
||||||
|
|
||||||
try {
|
|
||||||
QueryResponse response = sqlClient.query(requestConverter.sqlQueryRequest(query));
|
|
||||||
|
|
||||||
return responseConverter.sqlResponse(response);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw exceptionTranslator.translateException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region client callback
|
// region client callback
|
||||||
|
@ -20,7 +20,6 @@ import static org.springframework.data.elasticsearch.client.elc.TypeUtils.*;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
|
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
|
||||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
|
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
|
||||||
import org.springframework.data.elasticsearch.core.query.highlight.Highlight;
|
import org.springframework.data.elasticsearch.core.query.highlight.Highlight;
|
||||||
@ -28,6 +27,7 @@ import org.springframework.data.elasticsearch.core.query.highlight.HighlightFiel
|
|||||||
import org.springframework.data.elasticsearch.core.query.highlight.HighlightFieldParameters;
|
import org.springframework.data.elasticsearch.core.query.highlight.HighlightFieldParameters;
|
||||||
import org.springframework.data.elasticsearch.core.query.highlight.HighlightParameters;
|
import org.springframework.data.elasticsearch.core.query.highlight.HighlightParameters;
|
||||||
import org.springframework.data.mapping.context.MappingContext;
|
import org.springframework.data.mapping.context.MappingContext;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -43,8 +43,7 @@ class HighlightQueryBuilder {
|
|||||||
private final RequestConverter requestConverter;
|
private final RequestConverter requestConverter;
|
||||||
|
|
||||||
HighlightQueryBuilder(
|
HighlightQueryBuilder(
|
||||||
MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext,
|
MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext, RequestConverter requestConverter) {
|
||||||
RequestConverter requestConverter) {
|
|
||||||
this.mappingContext = mappingContext;
|
this.mappingContext = mappingContext;
|
||||||
this.requestConverter = requestConverter;
|
this.requestConverter = requestConverter;
|
||||||
}
|
}
|
||||||
|
@ -21,13 +21,13 @@ import co.elastic.clients.elasticsearch.indices.*;
|
|||||||
import co.elastic.clients.transport.ElasticsearchTransport;
|
import co.elastic.clients.transport.ElasticsearchTransport;
|
||||||
import co.elastic.clients.transport.endpoints.BooleanResponse;
|
import co.elastic.clients.transport.endpoints.BooleanResponse;
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||||
import org.springframework.data.elasticsearch.UncategorizedElasticsearchException;
|
import org.springframework.data.elasticsearch.UncategorizedElasticsearchException;
|
||||||
@ -46,10 +46,9 @@ import org.springframework.data.elasticsearch.core.index.GetIndexTemplateRequest
|
|||||||
import org.springframework.data.elasticsearch.core.index.GetTemplateRequest;
|
import org.springframework.data.elasticsearch.core.index.GetTemplateRequest;
|
||||||
import org.springframework.data.elasticsearch.core.index.PutIndexTemplateRequest;
|
import org.springframework.data.elasticsearch.core.index.PutIndexTemplateRequest;
|
||||||
import org.springframework.data.elasticsearch.core.index.PutTemplateRequest;
|
import org.springframework.data.elasticsearch.core.index.PutTemplateRequest;
|
||||||
import org.springframework.data.elasticsearch.core.mapping.Alias;
|
|
||||||
import org.springframework.data.elasticsearch.core.mapping.CreateIndexSettings;
|
|
||||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
|
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
|
||||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -61,6 +60,8 @@ import org.springframework.util.Assert;
|
|||||||
public class IndicesTemplate extends ChildTemplate<ElasticsearchTransport, ElasticsearchIndicesClient>
|
public class IndicesTemplate extends ChildTemplate<ElasticsearchTransport, ElasticsearchIndicesClient>
|
||||||
implements IndexOperations {
|
implements IndexOperations {
|
||||||
|
|
||||||
|
private static final Log LOGGER = LogFactory.getLog(IndicesTemplate.class);
|
||||||
|
|
||||||
// we need a cluster client as well because ES has put some methods from the indices API into the cluster client
|
// we need a cluster client as well because ES has put some methods from the indices API into the cluster client
|
||||||
// (component templates)
|
// (component templates)
|
||||||
private final ClusterTemplate clusterTemplate;
|
private final ClusterTemplate clusterTemplate;
|
||||||
@ -136,14 +137,11 @@ public class IndicesTemplate extends ChildTemplate<ElasticsearchTransport, Elast
|
|||||||
|
|
||||||
protected boolean doCreate(IndexCoordinates indexCoordinates, Map<String, Object> settings,
|
protected boolean doCreate(IndexCoordinates indexCoordinates, Map<String, Object> settings,
|
||||||
@Nullable Document mapping) {
|
@Nullable Document mapping) {
|
||||||
Set<Alias> aliases = (boundClass != null) ? getAliasesFor(boundClass) : new HashSet<>();
|
|
||||||
CreateIndexSettings indexSettings = CreateIndexSettings.builder(indexCoordinates)
|
|
||||||
.withAliases(aliases)
|
|
||||||
.withSettings(settings)
|
|
||||||
.withMapping(mapping)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
CreateIndexRequest createIndexRequest = requestConverter.indicesCreateRequest(indexSettings);
|
Assert.notNull(indexCoordinates, "indexCoordinates must not be null");
|
||||||
|
Assert.notNull(settings, "settings must not be null");
|
||||||
|
|
||||||
|
CreateIndexRequest createIndexRequest = requestConverter.indicesCreateRequest(indexCoordinates, settings, mapping);
|
||||||
CreateIndexResponse createIndexResponse = execute(client -> client.create(createIndexRequest));
|
CreateIndexResponse createIndexResponse = execute(client -> client.create(createIndexRequest));
|
||||||
return Boolean.TRUE.equals(createIndexResponse.acknowledged());
|
return Boolean.TRUE.equals(createIndexResponse.acknowledged());
|
||||||
}
|
}
|
||||||
@ -238,7 +236,8 @@ public class IndicesTemplate extends ChildTemplate<ElasticsearchTransport, Elast
|
|||||||
GetMappingRequest getMappingRequest = requestConverter.indicesGetMappingRequest(indexCoordinates);
|
GetMappingRequest getMappingRequest = requestConverter.indicesGetMappingRequest(indexCoordinates);
|
||||||
GetMappingResponse getMappingResponse = execute(client -> client.getMapping(getMappingRequest));
|
GetMappingResponse getMappingResponse = execute(client -> client.getMapping(getMappingRequest));
|
||||||
|
|
||||||
return responseConverter.indicesGetMapping(getMappingResponse, indexCoordinates);
|
Document mappingResponse = responseConverter.indicesGetMapping(getMappingResponse, indexCoordinates);
|
||||||
|
return mappingResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -450,14 +449,5 @@ public class IndicesTemplate extends ChildTemplate<ElasticsearchTransport, Elast
|
|||||||
public IndexCoordinates getIndexCoordinatesFor(Class<?> clazz) {
|
public IndexCoordinates getIndexCoordinatesFor(Class<?> clazz) {
|
||||||
return getRequiredPersistentEntity(clazz).getIndexCoordinates();
|
return getRequiredPersistentEntity(clazz).getIndexCoordinates();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the {@link Alias} of the provided class.
|
|
||||||
*
|
|
||||||
* @param clazz provided class that can be used to extract aliases.
|
|
||||||
*/
|
|
||||||
public Set<Alias> getAliasesFor(Class<?> clazz) {
|
|
||||||
return getRequiredPersistentEntity(clazz).getAliases();
|
|
||||||
}
|
|
||||||
// endregion
|
// endregion
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ import java.nio.charset.StandardCharsets;
|
|||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Peter-Josef Meisch
|
* @author Peter-Josef Meisch
|
||||||
@ -48,7 +48,7 @@ final class JsonUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static String queryToJson(co.elastic.clients.elasticsearch._types.query_dsl.@Nullable Query query,
|
public static String queryToJson(@Nullable co.elastic.clients.elasticsearch._types.query_dsl.Query query,
|
||||||
JsonpMapper mapper) {
|
JsonpMapper mapper) {
|
||||||
|
|
||||||
if (query == null) {
|
if (query == null) {
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.elasticsearch.client.elc;
|
package org.springframework.data.elasticsearch.client.elc;
|
||||||
|
|
||||||
|
import co.elastic.clients.elasticsearch._types.KnnQuery;
|
||||||
import co.elastic.clients.elasticsearch._types.KnnSearch;
|
import co.elastic.clients.elasticsearch._types.KnnSearch;
|
||||||
import co.elastic.clients.elasticsearch._types.SortOptions;
|
import co.elastic.clients.elasticsearch._types.SortOptions;
|
||||||
import co.elastic.clients.elasticsearch._types.aggregations.Aggregation;
|
import co.elastic.clients.elasticsearch._types.aggregations.Aggregation;
|
||||||
@ -28,8 +29,9 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.data.elasticsearch.core.query.BaseQuery;
|
import org.springframework.data.elasticsearch.core.query.BaseQuery;
|
||||||
|
import org.springframework.data.elasticsearch.core.query.ScriptedField;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,13 +40,12 @@ import org.springframework.util.Assert;
|
|||||||
*
|
*
|
||||||
* @author Peter-Josef Meisch
|
* @author Peter-Josef Meisch
|
||||||
* @author Sascha Woo
|
* @author Sascha Woo
|
||||||
* @author Haibo Liu
|
|
||||||
* @since 4.4
|
* @since 4.4
|
||||||
*/
|
*/
|
||||||
public class NativeQuery extends BaseQuery {
|
public class NativeQuery extends BaseQuery {
|
||||||
|
|
||||||
@Nullable private final Query query;
|
@Nullable private final Query query;
|
||||||
private org.springframework.data.elasticsearch.core.query.@Nullable Query springDataQuery;
|
@Nullable private org.springframework.data.elasticsearch.core.query.Query springDataQuery;
|
||||||
@Nullable private Query filter;
|
@Nullable private Query filter;
|
||||||
// note: the new client does not have pipeline aggs, these are just set up as normal aggs
|
// note: the new client does not have pipeline aggs, these are just set up as normal aggs
|
||||||
private final Map<String, Aggregation> aggregations = new LinkedHashMap<>();
|
private final Map<String, Aggregation> aggregations = new LinkedHashMap<>();
|
||||||
@ -53,6 +54,7 @@ public class NativeQuery extends BaseQuery {
|
|||||||
private List<SortOptions> sortOptions = Collections.emptyList();
|
private List<SortOptions> sortOptions = Collections.emptyList();
|
||||||
|
|
||||||
private Map<String, JsonData> searchExtensions = Collections.emptyMap();
|
private Map<String, JsonData> searchExtensions = Collections.emptyMap();
|
||||||
|
@Nullable private KnnQuery knnQuery;
|
||||||
@Nullable private List<KnnSearch> knnSearches = Collections.emptyList();
|
@Nullable private List<KnnSearch> knnSearches = Collections.emptyList();
|
||||||
|
|
||||||
public NativeQuery(NativeQueryBuilder builder) {
|
public NativeQuery(NativeQueryBuilder builder) {
|
||||||
@ -70,6 +72,7 @@ public class NativeQuery extends BaseQuery {
|
|||||||
"Cannot add an NativeQuery in a NativeQuery");
|
"Cannot add an NativeQuery in a NativeQuery");
|
||||||
}
|
}
|
||||||
this.springDataQuery = builder.getSpringDataQuery();
|
this.springDataQuery = builder.getSpringDataQuery();
|
||||||
|
this.knnQuery = builder.getKnnQuery();
|
||||||
this.knnSearches = builder.getKnnSearches();
|
this.knnSearches = builder.getKnnSearches();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,10 +120,18 @@ public class NativeQuery extends BaseQuery {
|
|||||||
* @see NativeQueryBuilder#withQuery(org.springframework.data.elasticsearch.core.query.Query).
|
* @see NativeQueryBuilder#withQuery(org.springframework.data.elasticsearch.core.query.Query).
|
||||||
* @since 5.1
|
* @since 5.1
|
||||||
*/
|
*/
|
||||||
public void setSpringDataQuery(org.springframework.data.elasticsearch.core.query.@Nullable Query springDataQuery) {
|
public void setSpringDataQuery(@Nullable org.springframework.data.elasticsearch.core.query.Query springDataQuery) {
|
||||||
this.springDataQuery = springDataQuery;
|
this.springDataQuery = springDataQuery;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 5.1
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public KnnQuery getKnnQuery() {
|
||||||
|
return knnQuery;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 5.3.1
|
* @since 5.3.1
|
||||||
*/
|
*/
|
||||||
@ -129,7 +140,8 @@ public class NativeQuery extends BaseQuery {
|
|||||||
return knnSearches;
|
return knnSearches;
|
||||||
}
|
}
|
||||||
|
|
||||||
public org.springframework.data.elasticsearch.core.query.@Nullable Query getSpringDataQuery() {
|
@Nullable
|
||||||
|
public org.springframework.data.elasticsearch.core.query.Query getSpringDataQuery() {
|
||||||
return springDataQuery;
|
return springDataQuery;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,14 +33,13 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.data.elasticsearch.core.query.BaseQueryBuilder;
|
import org.springframework.data.elasticsearch.core.query.BaseQueryBuilder;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Peter-Josef Meisch
|
* @author Peter-Josef Meisch
|
||||||
* @author Sascha Woo
|
* @author Sascha Woo
|
||||||
* @author Haibo Liu
|
|
||||||
* @since 4.4
|
* @since 4.4
|
||||||
*/
|
*/
|
||||||
public class NativeQueryBuilder extends BaseQueryBuilder<NativeQuery, NativeQueryBuilder> {
|
public class NativeQueryBuilder extends BaseQueryBuilder<NativeQuery, NativeQueryBuilder> {
|
||||||
@ -53,7 +52,7 @@ public class NativeQueryBuilder extends BaseQueryBuilder<NativeQuery, NativeQuer
|
|||||||
private final List<SortOptions> sortOptions = new ArrayList<>();
|
private final List<SortOptions> sortOptions = new ArrayList<>();
|
||||||
private final Map<String, JsonData> searchExtensions = new LinkedHashMap<>();
|
private final Map<String, JsonData> searchExtensions = new LinkedHashMap<>();
|
||||||
|
|
||||||
private org.springframework.data.elasticsearch.core.query.@Nullable Query springDataQuery;
|
@Nullable private org.springframework.data.elasticsearch.core.query.Query springDataQuery;
|
||||||
@Nullable private KnnQuery knnQuery;
|
@Nullable private KnnQuery knnQuery;
|
||||||
@Nullable private List<KnnSearch> knnSearches = Collections.emptyList();
|
@Nullable private List<KnnSearch> knnSearches = Collections.emptyList();
|
||||||
|
|
||||||
@ -104,7 +103,8 @@ public class NativeQueryBuilder extends BaseQueryBuilder<NativeQuery, NativeQuer
|
|||||||
return knnSearches;
|
return knnSearches;
|
||||||
}
|
}
|
||||||
|
|
||||||
public org.springframework.data.elasticsearch.core.query.@Nullable Query getSpringDataQuery() {
|
@Nullable
|
||||||
|
public org.springframework.data.elasticsearch.core.query.Query getSpringDataQuery() {
|
||||||
return springDataQuery;
|
return springDataQuery;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,30 +213,13 @@ public class NativeQueryBuilder extends BaseQueryBuilder<NativeQuery, NativeQuer
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 5.4
|
* @since 5.1
|
||||||
*/
|
*/
|
||||||
public NativeQueryBuilder withKnnSearches(List<KnnSearch> knnSearches) {
|
public NativeQueryBuilder withKnnQuery(KnnQuery knnQuery) {
|
||||||
this.knnSearches = knnSearches;
|
this.knnQuery = knnQuery;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @since 5.4
|
|
||||||
*/
|
|
||||||
public NativeQueryBuilder withKnnSearches(Function<KnnSearch.Builder, ObjectBuilder<KnnSearch>> fn) {
|
|
||||||
|
|
||||||
Assert.notNull(fn, "fn must not be null");
|
|
||||||
|
|
||||||
return withKnnSearches(fn.apply(new KnnSearch.Builder()).build());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @since 5.4
|
|
||||||
*/
|
|
||||||
public NativeQueryBuilder withKnnSearches(KnnSearch knnSearch) {
|
|
||||||
return withKnnSearches(List.of(knnSearch));
|
|
||||||
}
|
|
||||||
|
|
||||||
public NativeQuery build() {
|
public NativeQuery build() {
|
||||||
Assert.isTrue(query == null || springDataQuery == null, "Cannot have both a native query and a Spring Data query");
|
Assert.isTrue(query == null || springDataQuery == null, "Cannot have both a native query and a Spring Data query");
|
||||||
return new NativeQuery(this);
|
return new NativeQuery(this);
|
||||||
|
@ -34,9 +34,9 @@ import java.util.Base64;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
|
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
|
||||||
import org.springframework.data.elasticsearch.core.query.BaseQueryBuilder;
|
import org.springframework.data.elasticsearch.core.query.BaseQueryBuilder;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -27,17 +27,15 @@ import co.elastic.clients.transport.endpoints.EndpointWithResponseMapperAttr;
|
|||||||
import co.elastic.clients.util.ObjectBuilder;
|
import co.elastic.clients.util.ObjectBuilder;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reactive version of {@link co.elastic.clients.elasticsearch.ElasticsearchClient}.
|
* Reactive version of {@link co.elastic.clients.elasticsearch.ElasticsearchClient}.
|
||||||
*
|
*
|
||||||
* @author Peter-Josef Meisch
|
* @author Peter-Josef Meisch
|
||||||
* @author maryantocinn
|
|
||||||
* @since 4.4
|
* @since 4.4
|
||||||
*/
|
*/
|
||||||
public class ReactiveElasticsearchClient extends ApiClient<ElasticsearchTransport, ReactiveElasticsearchClient>
|
public class ReactiveElasticsearchClient extends ApiClient<ElasticsearchTransport, ReactiveElasticsearchClient>
|
||||||
@ -57,11 +55,8 @@ public class ReactiveElasticsearchClient extends ApiClient<ElasticsearchTranspor
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() throws Exception {
|
||||||
// since Elasticsearch 8.16 the ElasticsearchClient implements (through ApiClient) the Closeable interface and
|
transport.close();
|
||||||
// handles closing of the underlying transport. We now just call the base class, but keep this as we
|
|
||||||
// have been implementing AutoCloseable since 4.4 and won't change that to a mere Closeable
|
|
||||||
super.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// region child clients
|
// region child clients
|
||||||
@ -74,10 +69,6 @@ public class ReactiveElasticsearchClient extends ApiClient<ElasticsearchTranspor
|
|||||||
return new ReactiveElasticsearchIndicesClient(transport, transportOptions);
|
return new ReactiveElasticsearchIndicesClient(transport, transportOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReactiveElasticsearchSqlClient sql() {
|
|
||||||
return new ReactiveElasticsearchSqlClient(transport, transportOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
// region info
|
// region info
|
||||||
|
|
||||||
@ -131,8 +122,7 @@ public class ReactiveElasticsearchClient extends ApiClient<ElasticsearchTranspor
|
|||||||
// java.lang.Class<TDocument>)
|
// java.lang.Class<TDocument>)
|
||||||
// noinspection unchecked
|
// noinspection unchecked
|
||||||
JsonEndpoint<GetRequest, GetResponse<T>, ErrorResponse> endpoint = (JsonEndpoint<GetRequest, GetResponse<T>, ErrorResponse>) GetRequest._ENDPOINT;
|
JsonEndpoint<GetRequest, GetResponse<T>, ErrorResponse> endpoint = (JsonEndpoint<GetRequest, GetResponse<T>, ErrorResponse>) GetRequest._ENDPOINT;
|
||||||
endpoint = new EndpointWithResponseMapperAttr<>(endpoint,
|
endpoint = new EndpointWithResponseMapperAttr<>(endpoint, "co.elastic.clients:Deserializer:_global.get.TDocument",
|
||||||
"co.elastic.clients:Deserializer:_global.get.Response.TDocument",
|
|
||||||
getDeserializer(tClass));
|
getDeserializer(tClass));
|
||||||
|
|
||||||
return Mono.fromFuture(transport.performRequestAsync(request, endpoint, transportOptions));
|
return Mono.fromFuture(transport.performRequestAsync(request, endpoint, transportOptions));
|
||||||
@ -151,7 +141,7 @@ public class ReactiveElasticsearchClient extends ApiClient<ElasticsearchTranspor
|
|||||||
|
|
||||||
// noinspection unchecked
|
// noinspection unchecked
|
||||||
JsonEndpoint<UpdateRequest<?, ?>, UpdateResponse<T>, ErrorResponse> endpoint = new EndpointWithResponseMapperAttr(
|
JsonEndpoint<UpdateRequest<?, ?>, UpdateResponse<T>, ErrorResponse> endpoint = new EndpointWithResponseMapperAttr(
|
||||||
UpdateRequest._ENDPOINT, "co.elastic.clients:Deserializer:_global.update.Response.TDocument",
|
UpdateRequest._ENDPOINT, "co.elastic.clients:Deserializer:_global.update.TDocument",
|
||||||
this.getDeserializer(clazz));
|
this.getDeserializer(clazz));
|
||||||
return Mono.fromFuture(transport.performRequestAsync(request, endpoint, this.transportOptions));
|
return Mono.fromFuture(transport.performRequestAsync(request, endpoint, this.transportOptions));
|
||||||
}
|
}
|
||||||
@ -177,8 +167,7 @@ public class ReactiveElasticsearchClient extends ApiClient<ElasticsearchTranspor
|
|||||||
|
|
||||||
// noinspection unchecked
|
// noinspection unchecked
|
||||||
JsonEndpoint<MgetRequest, MgetResponse<T>, ErrorResponse> endpoint = (JsonEndpoint<MgetRequest, MgetResponse<T>, ErrorResponse>) MgetRequest._ENDPOINT;
|
JsonEndpoint<MgetRequest, MgetResponse<T>, ErrorResponse> endpoint = (JsonEndpoint<MgetRequest, MgetResponse<T>, ErrorResponse>) MgetRequest._ENDPOINT;
|
||||||
endpoint = new EndpointWithResponseMapperAttr<>(endpoint,
|
endpoint = new EndpointWithResponseMapperAttr<>(endpoint, "co.elastic.clients:Deserializer:_global.mget.TDocument",
|
||||||
"co.elastic.clients:Deserializer:_global.mget.Response.TDocument",
|
|
||||||
this.getDeserializer(clazz));
|
this.getDeserializer(clazz));
|
||||||
|
|
||||||
return Mono.fromFuture(transport.performRequestAsync(request, endpoint, transportOptions));
|
return Mono.fromFuture(transport.performRequestAsync(request, endpoint, transportOptions));
|
||||||
@ -234,26 +223,6 @@ public class ReactiveElasticsearchClient extends ApiClient<ElasticsearchTranspor
|
|||||||
return deleteByQuery(fn.apply(new DeleteByQueryRequest.Builder()).build());
|
return deleteByQuery(fn.apply(new DeleteByQueryRequest.Builder()).build());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @since 5.4
|
|
||||||
*/
|
|
||||||
public Mono<CountResponse> count(CountRequest request) {
|
|
||||||
|
|
||||||
Assert.notNull(request, "request must not be null");
|
|
||||||
|
|
||||||
return Mono.fromFuture(transport.performRequestAsync(request, CountRequest._ENDPOINT, transportOptions));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @since 5.4
|
|
||||||
*/
|
|
||||||
public Mono<CountResponse> count(Function<CountRequest.Builder, ObjectBuilder<CountRequest>> fn) {
|
|
||||||
|
|
||||||
Assert.notNull(fn, "fn must not be null");
|
|
||||||
|
|
||||||
return count(fn.apply(new CountRequest.Builder()).build());
|
|
||||||
}
|
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
// region search
|
// region search
|
||||||
|
|
||||||
@ -309,7 +278,7 @@ public class ReactiveElasticsearchClient extends ApiClient<ElasticsearchTranspor
|
|||||||
// noinspection unchecked
|
// noinspection unchecked
|
||||||
JsonEndpoint<ScrollRequest, ScrollResponse<T>, ErrorResponse> endpoint = (JsonEndpoint<ScrollRequest, ScrollResponse<T>, ErrorResponse>) ScrollRequest._ENDPOINT;
|
JsonEndpoint<ScrollRequest, ScrollResponse<T>, ErrorResponse> endpoint = (JsonEndpoint<ScrollRequest, ScrollResponse<T>, ErrorResponse>) ScrollRequest._ENDPOINT;
|
||||||
endpoint = new EndpointWithResponseMapperAttr<>(endpoint,
|
endpoint = new EndpointWithResponseMapperAttr<>(endpoint,
|
||||||
"co.elastic.clients:Deserializer:_global.scroll.Response.TDocument", getDeserializer(tDocumentClass));
|
"co.elastic.clients:Deserializer:_global.scroll.TDocument", getDeserializer(tDocumentClass));
|
||||||
|
|
||||||
return Mono.fromFuture(transport.performRequestAsync(request, endpoint, transportOptions));
|
return Mono.fromFuture(transport.performRequestAsync(request, endpoint, transportOptions));
|
||||||
}
|
}
|
||||||
|
@ -16,15 +16,7 @@
|
|||||||
package org.springframework.data.elasticsearch.client.elc;
|
package org.springframework.data.elasticsearch.client.elc;
|
||||||
|
|
||||||
import co.elastic.clients.ApiClient;
|
import co.elastic.clients.ApiClient;
|
||||||
import co.elastic.clients.elasticsearch.cluster.DeleteComponentTemplateRequest;
|
import co.elastic.clients.elasticsearch.cluster.*;
|
||||||
import co.elastic.clients.elasticsearch.cluster.DeleteComponentTemplateResponse;
|
|
||||||
import co.elastic.clients.elasticsearch.cluster.ExistsComponentTemplateRequest;
|
|
||||||
import co.elastic.clients.elasticsearch.cluster.GetComponentTemplateRequest;
|
|
||||||
import co.elastic.clients.elasticsearch.cluster.GetComponentTemplateResponse;
|
|
||||||
import co.elastic.clients.elasticsearch.cluster.HealthRequest;
|
|
||||||
import co.elastic.clients.elasticsearch.cluster.HealthResponse;
|
|
||||||
import co.elastic.clients.elasticsearch.cluster.PutComponentTemplateRequest;
|
|
||||||
import co.elastic.clients.elasticsearch.cluster.PutComponentTemplateResponse;
|
|
||||||
import co.elastic.clients.transport.ElasticsearchTransport;
|
import co.elastic.clients.transport.ElasticsearchTransport;
|
||||||
import co.elastic.clients.transport.TransportOptions;
|
import co.elastic.clients.transport.TransportOptions;
|
||||||
import co.elastic.clients.transport.endpoints.BooleanResponse;
|
import co.elastic.clients.transport.endpoints.BooleanResponse;
|
||||||
@ -33,7 +25,7 @@ import reactor.core.publisher.Mono;
|
|||||||
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reactive version of the {@link co.elastic.clients.elasticsearch.cluster.ElasticsearchClusterClient}
|
* Reactive version of the {@link co.elastic.clients.elasticsearch.cluster.ElasticsearchClusterClient}
|
||||||
|
@ -19,18 +19,12 @@ import co.elastic.clients.json.JsonpMapper;
|
|||||||
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
|
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
|
||||||
import co.elastic.clients.transport.ElasticsearchTransport;
|
import co.elastic.clients.transport.ElasticsearchTransport;
|
||||||
import co.elastic.clients.transport.TransportOptions;
|
import co.elastic.clients.transport.TransportOptions;
|
||||||
import co.elastic.clients.transport.rest5_client.Rest5ClientOptions;
|
|
||||||
import co.elastic.clients.transport.rest5_client.low_level.RequestOptions;
|
|
||||||
import co.elastic.clients.transport.rest5_client.low_level.Rest5Client;
|
|
||||||
import co.elastic.clients.transport.rest_client.RestClientOptions;
|
import co.elastic.clients.transport.rest_client.RestClientOptions;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import org.elasticsearch.client.RequestOptions;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
|
||||||
import org.elasticsearch.client.RestClient;
|
import org.elasticsearch.client.RestClient;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.data.elasticsearch.client.ClientConfiguration;
|
import org.springframework.data.elasticsearch.client.ClientConfiguration;
|
||||||
import org.springframework.data.elasticsearch.client.elc.rest5_client.Rest5Clients;
|
|
||||||
import org.springframework.data.elasticsearch.config.ElasticsearchConfigurationSupport;
|
import org.springframework.data.elasticsearch.config.ElasticsearchConfigurationSupport;
|
||||||
import org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations;
|
import org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations;
|
||||||
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
||||||
@ -61,11 +55,11 @@ public abstract class ReactiveElasticsearchConfiguration extends ElasticsearchCo
|
|||||||
* @return RestClient
|
* @return RestClient
|
||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
public Rest5Client elasticsearchRestClient(ClientConfiguration clientConfiguration) {
|
public RestClient elasticsearchRestClient(ClientConfiguration clientConfiguration) {
|
||||||
|
|
||||||
Assert.notNull(clientConfiguration, "clientConfiguration must not be null");
|
Assert.notNull(clientConfiguration, "clientConfiguration must not be null");
|
||||||
|
|
||||||
return Rest5Clients.getRest5Client(clientConfiguration);
|
return ElasticsearchClients.getRestClient(clientConfiguration);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -76,12 +70,12 @@ public abstract class ReactiveElasticsearchConfiguration extends ElasticsearchCo
|
|||||||
* @since 5.2
|
* @since 5.2
|
||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
public ElasticsearchTransport elasticsearchTransport(Rest5Client rest5Client, JsonpMapper jsonpMapper) {
|
public ElasticsearchTransport elasticsearchTransport(RestClient restClient, JsonpMapper jsonpMapper) {
|
||||||
|
|
||||||
Assert.notNull(rest5Client, "restClient must not be null");
|
Assert.notNull(restClient, "restClient must not be null");
|
||||||
Assert.notNull(jsonpMapper, "jsonpMapper must not be null");
|
Assert.notNull(jsonpMapper, "jsonpMapper must not be null");
|
||||||
|
|
||||||
return ElasticsearchClients.getElasticsearchTransport(rest5Client, ElasticsearchClients.REACTIVE_CLIENT,
|
return ElasticsearchClients.getElasticsearchTransport(restClient, ElasticsearchClients.REACTIVE_CLIENT,
|
||||||
transportOptions(), jsonpMapper);
|
transportOptions(), jsonpMapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,7 +110,7 @@ public abstract class ReactiveElasticsearchConfiguration extends ElasticsearchCo
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides the JsonpMapper that is used in the {@link #elasticsearchTransport(Rest5Client, JsonpMapper)} method and
|
* Provides the JsonpMapper that is used in the {@link #elasticsearchTransport(RestClient, JsonpMapper)} method and
|
||||||
* exposes it as a bean.
|
* exposes it as a bean.
|
||||||
*
|
*
|
||||||
* @return the {@link JsonpMapper} to use
|
* @return the {@link JsonpMapper} to use
|
||||||
@ -124,19 +118,13 @@ public abstract class ReactiveElasticsearchConfiguration extends ElasticsearchCo
|
|||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
public JsonpMapper jsonpMapper() {
|
public JsonpMapper jsonpMapper() {
|
||||||
// we need to create our own objectMapper that keeps null values in order to provide the storeNullValue
|
return new JacksonJsonpMapper();
|
||||||
// functionality. The one Elasticsearch would provide removes the nulls. We remove unwanted nulls before they get
|
|
||||||
// into this mapper, so we can safely keep them here.
|
|
||||||
var objectMapper = (new ObjectMapper())
|
|
||||||
.configure(SerializationFeature.INDENT_OUTPUT, false)
|
|
||||||
.setSerializationInclusion(JsonInclude.Include.ALWAYS);
|
|
||||||
return new JacksonJsonpMapper(objectMapper);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the options that should be added to every request. Must not be {@literal null}
|
* @return the options that should be added to every request. Must not be {@literal null}
|
||||||
*/
|
*/
|
||||||
public TransportOptions transportOptions() {
|
public TransportOptions transportOptions() {
|
||||||
return new Rest5ClientOptions(RequestOptions.DEFAULT, false);
|
return new RestClientOptions(RequestOptions.DEFAULT).toBuilder().build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ import reactor.core.publisher.Mono;
|
|||||||
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reactive version of the {@link co.elastic.clients.elasticsearch.indices.ElasticsearchIndicesClient}
|
* Reactive version of the {@link co.elastic.clients.elasticsearch.indices.ElasticsearchIndicesClient}
|
||||||
@ -539,6 +539,14 @@ public class ReactiveElasticsearchIndicesClient
|
|||||||
return stats(builder -> builder);
|
return stats(builder -> builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Mono<UnfreezeResponse> unfreeze(UnfreezeRequest request) {
|
||||||
|
return Mono.fromFuture(transport.performRequestAsync(request, UnfreezeRequest._ENDPOINT, transportOptions));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Mono<UnfreezeResponse> unfreeze(Function<UnfreezeRequest.Builder, ObjectBuilder<UnfreezeRequest>> fn) {
|
||||||
|
return unfreeze(fn.apply(new UnfreezeRequest.Builder()).build());
|
||||||
|
}
|
||||||
|
|
||||||
public Mono<UpdateAliasesResponse> updateAliases(UpdateAliasesRequest request) {
|
public Mono<UpdateAliasesResponse> updateAliases(UpdateAliasesRequest request) {
|
||||||
return Mono.fromFuture(transport.performRequestAsync(request, UpdateAliasesRequest._ENDPOINT, transportOptions));
|
return Mono.fromFuture(transport.performRequestAsync(request, UpdateAliasesRequest._ENDPOINT, transportOptions));
|
||||||
}
|
}
|
||||||
|
@ -1,144 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2021-2025 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.springframework.data.elasticsearch.client.elc;
|
|
||||||
|
|
||||||
import co.elastic.clients.json.JsonpMapper;
|
|
||||||
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
|
|
||||||
import co.elastic.clients.transport.ElasticsearchTransport;
|
|
||||||
import co.elastic.clients.transport.TransportOptions;
|
|
||||||
import co.elastic.clients.transport.rest_client.RestClientOptions;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
|
||||||
import org.elasticsearch.client.RequestOptions;
|
|
||||||
import org.elasticsearch.client.RestClient;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.data.elasticsearch.client.ClientConfiguration;
|
|
||||||
import org.springframework.data.elasticsearch.client.elc.rest_client.RestClients;
|
|
||||||
import org.springframework.data.elasticsearch.config.ElasticsearchConfigurationSupport;
|
|
||||||
import org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations;
|
|
||||||
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base class for a @{@link org.springframework.context.annotation.Configuration} class to set up the Elasticsearch
|
|
||||||
* connection using the {@link ReactiveElasticsearchClient}. This class exposes different parts of the setup as Spring
|
|
||||||
* beans. Deriving * classes must provide the {@link ClientConfiguration} to use. <br/>
|
|
||||||
* This class uses the Elasticsearch RestClient which was replaced b y the Rest5Client in Elasticsearch 9. It is still
|
|
||||||
* available here but deprecated. *
|
|
||||||
*
|
|
||||||
* @author Peter-Josef Meisch
|
|
||||||
* @since 4.4
|
|
||||||
* @deprecated since 6.0 use {@link ReactiveElasticsearchConfiguration}
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.0", forRemoval=true)
|
|
||||||
public abstract class ReactiveElasticsearchLegacyRestClientConfiguration extends ElasticsearchConfigurationSupport {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Must be implemented by deriving classes to provide the {@link ClientConfiguration}.
|
|
||||||
*
|
|
||||||
* @return configuration, must not be {@literal null}
|
|
||||||
*/
|
|
||||||
@Bean(name = "elasticsearchClientConfiguration")
|
|
||||||
public abstract ClientConfiguration clientConfiguration();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides the underlying low level RestClient.
|
|
||||||
*
|
|
||||||
* @param clientConfiguration configuration for the client, must not be {@literal null}
|
|
||||||
* @return RestClient
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public RestClient elasticsearchRestClient(ClientConfiguration clientConfiguration) {
|
|
||||||
|
|
||||||
Assert.notNull(clientConfiguration, "clientConfiguration must not be null");
|
|
||||||
|
|
||||||
return RestClients.getRestClient(clientConfiguration);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides the Elasticsearch transport to be used. The default implementation uses the {@link RestClient} bean and
|
|
||||||
* the {@link JsonpMapper} bean provided in this class.
|
|
||||||
*
|
|
||||||
* @return the {@link ElasticsearchTransport}
|
|
||||||
* @since 5.2
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public ElasticsearchTransport elasticsearchTransport(RestClient restClient, JsonpMapper jsonpMapper) {
|
|
||||||
|
|
||||||
Assert.notNull(restClient, "restClient must not be null");
|
|
||||||
Assert.notNull(jsonpMapper, "jsonpMapper must not be null");
|
|
||||||
|
|
||||||
return ElasticsearchClients.getElasticsearchTransport(restClient, ElasticsearchClients.REACTIVE_CLIENT,
|
|
||||||
transportOptions(), jsonpMapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides the {@link ReactiveElasticsearchClient} instance used.
|
|
||||||
*
|
|
||||||
* @param transport the ElasticsearchTransport to use
|
|
||||||
* @return ReactiveElasticsearchClient instance.
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public ReactiveElasticsearchClient reactiveElasticsearchClient(ElasticsearchTransport transport) {
|
|
||||||
|
|
||||||
Assert.notNull(transport, "transport must not be null");
|
|
||||||
|
|
||||||
return ElasticsearchClients.createReactive(transport);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates {@link ReactiveElasticsearchOperations}.
|
|
||||||
*
|
|
||||||
* @return never {@literal null}.
|
|
||||||
*/
|
|
||||||
@Bean(name = { "reactiveElasticsearchOperations", "reactiveElasticsearchTemplate" })
|
|
||||||
public ReactiveElasticsearchOperations reactiveElasticsearchOperations(ElasticsearchConverter elasticsearchConverter,
|
|
||||||
ReactiveElasticsearchClient reactiveElasticsearchClient) {
|
|
||||||
|
|
||||||
ReactiveElasticsearchTemplate template = new ReactiveElasticsearchTemplate(reactiveElasticsearchClient,
|
|
||||||
elasticsearchConverter);
|
|
||||||
template.setRefreshPolicy(refreshPolicy());
|
|
||||||
|
|
||||||
return template;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides the JsonpMapper that is used in the {@link #elasticsearchTransport(RestClient, JsonpMapper)} method and
|
|
||||||
* exposes it as a bean.
|
|
||||||
*
|
|
||||||
* @return the {@link JsonpMapper} to use
|
|
||||||
* @since 5.2
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public JsonpMapper jsonpMapper() {
|
|
||||||
// we need to create our own objectMapper that keeps null values in order to provide the storeNullValue
|
|
||||||
// functionality. The one Elasticsearch would provide removes the nulls. We remove unwanted nulls before they get
|
|
||||||
// into this mapper, so we can safely keep them here.
|
|
||||||
var objectMapper = (new ObjectMapper())
|
|
||||||
.configure(SerializationFeature.INDENT_OUTPUT, false)
|
|
||||||
.setSerializationInclusion(JsonInclude.Include.ALWAYS);
|
|
||||||
return new JacksonJsonpMapper(objectMapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the options that should be added to every request. Must not be {@literal null}
|
|
||||||
*/
|
|
||||||
public TransportOptions transportOptions() {
|
|
||||||
return new RestClientOptions(RequestOptions.DEFAULT, false).toBuilder().build();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,72 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2024-2025 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.springframework.data.elasticsearch.client.elc;
|
|
||||||
|
|
||||||
import co.elastic.clients.ApiClient;
|
|
||||||
import co.elastic.clients.elasticsearch._types.ElasticsearchException;
|
|
||||||
import co.elastic.clients.elasticsearch.sql.QueryRequest;
|
|
||||||
import co.elastic.clients.elasticsearch.sql.QueryResponse;
|
|
||||||
import co.elastic.clients.transport.ElasticsearchTransport;
|
|
||||||
import co.elastic.clients.transport.TransportOptions;
|
|
||||||
import co.elastic.clients.util.ObjectBuilder;
|
|
||||||
import reactor.core.publisher.Mono;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reactive version of {@link co.elastic.clients.elasticsearch.sql.ElasticsearchSqlClient}.
|
|
||||||
*
|
|
||||||
* @author Aouichaoui Youssef
|
|
||||||
* @since 5.4
|
|
||||||
*/
|
|
||||||
public class ReactiveElasticsearchSqlClient extends ApiClient<ElasticsearchTransport, ReactiveElasticsearchSqlClient> {
|
|
||||||
public ReactiveElasticsearchSqlClient(ElasticsearchTransport transport, @Nullable TransportOptions transportOptions) {
|
|
||||||
super(transport, transportOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ReactiveElasticsearchSqlClient withTransportOptions(@Nullable TransportOptions transportOptions) {
|
|
||||||
return new ReactiveElasticsearchSqlClient(transport, transportOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executes a SQL request
|
|
||||||
*
|
|
||||||
* @param fn a function that initializes a builder to create the {@link QueryRequest}.
|
|
||||||
*/
|
|
||||||
public final Mono<QueryResponse> query(Function<QueryRequest.Builder, ObjectBuilder<QueryRequest>> fn)
|
|
||||||
throws IOException, ElasticsearchException {
|
|
||||||
return query(fn.apply(new QueryRequest.Builder()).build());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executes a SQL request.
|
|
||||||
*/
|
|
||||||
public Mono<QueryResponse> query(QueryRequest query) {
|
|
||||||
return Mono.fromFuture(transport.performRequestAsync(query, QueryRequest._ENDPOINT, transportOptions));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executes a SQL request.
|
|
||||||
*/
|
|
||||||
public Mono<QueryResponse> query() {
|
|
||||||
return Mono.fromFuture(
|
|
||||||
transport.performRequestAsync(new QueryRequest.Builder().build(), QueryRequest._ENDPOINT, transportOptions));
|
|
||||||
}
|
|
||||||
}
|
|
@ -40,7 +40,6 @@ import java.util.stream.Collectors;
|
|||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.reactivestreams.Publisher;
|
import org.reactivestreams.Publisher;
|
||||||
import org.springframework.data.domain.Sort;
|
import org.springframework.data.domain.Sort;
|
||||||
import org.springframework.data.elasticsearch.BulkFailureException;
|
import org.springframework.data.elasticsearch.BulkFailureException;
|
||||||
@ -58,12 +57,19 @@ import org.springframework.data.elasticsearch.core.document.Document;
|
|||||||
import org.springframework.data.elasticsearch.core.document.SearchDocument;
|
import org.springframework.data.elasticsearch.core.document.SearchDocument;
|
||||||
import org.springframework.data.elasticsearch.core.document.SearchDocumentResponse;
|
import org.springframework.data.elasticsearch.core.document.SearchDocumentResponse;
|
||||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||||
import org.springframework.data.elasticsearch.core.query.*;
|
import org.springframework.data.elasticsearch.core.query.BaseQuery;
|
||||||
|
import org.springframework.data.elasticsearch.core.query.BaseQueryBuilder;
|
||||||
|
import org.springframework.data.elasticsearch.core.query.BulkOptions;
|
||||||
|
import org.springframework.data.elasticsearch.core.query.ByQueryResponse;
|
||||||
|
import org.springframework.data.elasticsearch.core.query.DeleteQuery;
|
||||||
|
import org.springframework.data.elasticsearch.core.query.Query;
|
||||||
|
import org.springframework.data.elasticsearch.core.query.SearchTemplateQuery;
|
||||||
|
import org.springframework.data.elasticsearch.core.query.UpdateQuery;
|
||||||
import org.springframework.data.elasticsearch.core.query.UpdateResponse;
|
import org.springframework.data.elasticsearch.core.query.UpdateResponse;
|
||||||
import org.springframework.data.elasticsearch.core.reindex.ReindexRequest;
|
import org.springframework.data.elasticsearch.core.reindex.ReindexRequest;
|
||||||
import org.springframework.data.elasticsearch.core.reindex.ReindexResponse;
|
import org.springframework.data.elasticsearch.core.reindex.ReindexResponse;
|
||||||
import org.springframework.data.elasticsearch.core.script.Script;
|
import org.springframework.data.elasticsearch.core.script.Script;
|
||||||
import org.springframework.data.elasticsearch.core.sql.SqlResponse;
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
@ -82,7 +88,6 @@ public class ReactiveElasticsearchTemplate extends AbstractReactiveElasticsearch
|
|||||||
private static final Log LOGGER = LogFactory.getLog(ReactiveElasticsearchTemplate.class);
|
private static final Log LOGGER = LogFactory.getLog(ReactiveElasticsearchTemplate.class);
|
||||||
|
|
||||||
private final ReactiveElasticsearchClient client;
|
private final ReactiveElasticsearchClient client;
|
||||||
private final ReactiveElasticsearchSqlClient sqlClient;
|
|
||||||
private final RequestConverter requestConverter;
|
private final RequestConverter requestConverter;
|
||||||
private final ResponseConverter responseConverter;
|
private final ResponseConverter responseConverter;
|
||||||
private final JsonpMapper jsonpMapper;
|
private final JsonpMapper jsonpMapper;
|
||||||
@ -94,7 +99,6 @@ public class ReactiveElasticsearchTemplate extends AbstractReactiveElasticsearch
|
|||||||
Assert.notNull(client, "client must not be null");
|
Assert.notNull(client, "client must not be null");
|
||||||
|
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.sqlClient = client.sql();
|
|
||||||
this.jsonpMapper = client._transport().jsonpMapper();
|
this.jsonpMapper = client._transport().jsonpMapper();
|
||||||
requestConverter = new RequestConverter(converter, jsonpMapper);
|
requestConverter = new RequestConverter(converter, jsonpMapper);
|
||||||
responseConverter = new ResponseConverter(jsonpMapper);
|
responseConverter = new ResponseConverter(jsonpMapper);
|
||||||
@ -167,6 +171,16 @@ public class ReactiveElasticsearchTemplate extends AbstractReactiveElasticsearch
|
|||||||
.onErrorReturn(NoSuchIndexException.class, false);
|
.onErrorReturn(NoSuchIndexException.class, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Mono<ByQueryResponse> delete(Query query, Class<?> entityType, IndexCoordinates index) {
|
||||||
|
|
||||||
|
Assert.notNull(query, "query must not be null");
|
||||||
|
|
||||||
|
DeleteByQueryRequest request = requestConverter.documentDeleteByQueryRequest(query, routingResolver.getRouting(),
|
||||||
|
entityType, index, getRefreshPolicy());
|
||||||
|
return Mono.from(execute(client -> client.deleteByQuery(request))).map(responseConverter::byQueryResponse);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<ByQueryResponse> delete(DeleteQuery query, Class<?> entityType, IndexCoordinates index) {
|
public Mono<ByQueryResponse> delete(DeleteQuery query, Class<?> entityType, IndexCoordinates index) {
|
||||||
Assert.notNull(query, "query must not be null");
|
Assert.notNull(query, "query must not be null");
|
||||||
@ -632,14 +646,6 @@ public class ReactiveElasticsearchTemplate extends AbstractReactiveElasticsearch
|
|||||||
return NativeQuery.builder().withIds(ids);
|
return NativeQuery.builder().withIds(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<SqlResponse> search(SqlQuery query) {
|
|
||||||
Assert.notNull(query, "Query must not be null.");
|
|
||||||
|
|
||||||
co.elastic.clients.elasticsearch.sql.QueryRequest request = requestConverter.sqlQueryRequest(query);
|
|
||||||
return sqlClient.query(request).onErrorMap(this::translateException).map(responseConverter::sqlResponse);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback interface to be used with {@link #execute(ReactiveElasticsearchTemplate.ClientCallback<>)} for operating
|
* Callback interface to be used with {@link #execute(ReactiveElasticsearchTemplate.ClientCallback<>)} for operating
|
||||||
* directly on {@link ReactiveElasticsearchClient}.
|
* directly on {@link ReactiveElasticsearchClient}.
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.elasticsearch.client.elc;
|
package org.springframework.data.elasticsearch.client.elc;
|
||||||
|
|
||||||
import static org.springframework.util.StringUtils.*;
|
import static org.springframework.util.StringUtils.hasText;
|
||||||
|
|
||||||
import co.elastic.clients.elasticsearch._types.AcknowledgedResponseBase;
|
import co.elastic.clients.elasticsearch._types.AcknowledgedResponseBase;
|
||||||
import co.elastic.clients.elasticsearch.indices.*;
|
import co.elastic.clients.elasticsearch.indices.*;
|
||||||
@ -24,12 +24,10 @@ import co.elastic.clients.transport.endpoints.BooleanResponse;
|
|||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||||
import org.springframework.data.elasticsearch.NoSuchIndexException;
|
import org.springframework.data.elasticsearch.NoSuchIndexException;
|
||||||
@ -48,10 +46,9 @@ import org.springframework.data.elasticsearch.core.index.GetIndexTemplateRequest
|
|||||||
import org.springframework.data.elasticsearch.core.index.GetTemplateRequest;
|
import org.springframework.data.elasticsearch.core.index.GetTemplateRequest;
|
||||||
import org.springframework.data.elasticsearch.core.index.PutIndexTemplateRequest;
|
import org.springframework.data.elasticsearch.core.index.PutIndexTemplateRequest;
|
||||||
import org.springframework.data.elasticsearch.core.index.PutTemplateRequest;
|
import org.springframework.data.elasticsearch.core.index.PutTemplateRequest;
|
||||||
import org.springframework.data.elasticsearch.core.mapping.Alias;
|
|
||||||
import org.springframework.data.elasticsearch.core.mapping.CreateIndexSettings;
|
|
||||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
|
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
|
||||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -133,14 +130,8 @@ public class ReactiveIndicesTemplate
|
|||||||
|
|
||||||
private Mono<Boolean> doCreate(IndexCoordinates indexCoordinates, Map<String, Object> settings,
|
private Mono<Boolean> doCreate(IndexCoordinates indexCoordinates, Map<String, Object> settings,
|
||||||
@Nullable Document mapping) {
|
@Nullable Document mapping) {
|
||||||
Set<Alias> aliases = (boundClass != null) ? getAliasesFor(boundClass) : new HashSet<>();
|
|
||||||
CreateIndexSettings indexSettings = CreateIndexSettings.builder(indexCoordinates)
|
|
||||||
.withAliases(aliases)
|
|
||||||
.withSettings(settings)
|
|
||||||
.withMapping(mapping)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
CreateIndexRequest createIndexRequest = requestConverter.indicesCreateRequest(indexSettings);
|
CreateIndexRequest createIndexRequest = requestConverter.indicesCreateRequest(indexCoordinates, settings, mapping);
|
||||||
Mono<CreateIndexResponse> createIndexResponse = Mono.from(execute(client -> client.create(createIndexRequest)));
|
Mono<CreateIndexResponse> createIndexResponse = Mono.from(execute(client -> client.create(createIndexRequest)));
|
||||||
return createIndexResponse.map(CreateIndexResponse::acknowledged);
|
return createIndexResponse.map(CreateIndexResponse::acknowledged);
|
||||||
}
|
}
|
||||||
@ -444,15 +435,6 @@ public class ReactiveIndicesTemplate
|
|||||||
return elasticsearchConverter.getMappingContext().getRequiredPersistentEntity(clazz).getIndexCoordinates();
|
return elasticsearchConverter.getMappingContext().getRequiredPersistentEntity(clazz).getIndexCoordinates();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the {@link Alias} of the provided class.
|
|
||||||
*
|
|
||||||
* @param clazz provided class that can be used to extract aliases.
|
|
||||||
*/
|
|
||||||
private Set<Alias> getAliasesFor(Class<?> clazz) {
|
|
||||||
return elasticsearchConverter.getMappingContext().getRequiredPersistentEntity(clazz).getAliases();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Class<?> checkForBoundClass() {
|
private Class<?> checkForBoundClass() {
|
||||||
if (boundClass == null) {
|
if (boundClass == null) {
|
||||||
throw new InvalidDataAccessApiUsageException("IndexOperations are not bound");
|
throw new InvalidDataAccessApiUsageException("IndexOperations are not bound");
|
||||||
|
@ -20,6 +20,7 @@ import static org.springframework.util.CollectionUtils.*;
|
|||||||
|
|
||||||
import co.elastic.clients.elasticsearch._types.Conflicts;
|
import co.elastic.clients.elasticsearch._types.Conflicts;
|
||||||
import co.elastic.clients.elasticsearch._types.ExpandWildcard;
|
import co.elastic.clients.elasticsearch._types.ExpandWildcard;
|
||||||
|
import co.elastic.clients.elasticsearch._types.InlineScript;
|
||||||
import co.elastic.clients.elasticsearch._types.NestedSortValue;
|
import co.elastic.clients.elasticsearch._types.NestedSortValue;
|
||||||
import co.elastic.clients.elasticsearch._types.OpType;
|
import co.elastic.clients.elasticsearch._types.OpType;
|
||||||
import co.elastic.clients.elasticsearch._types.SortOptions;
|
import co.elastic.clients.elasticsearch._types.SortOptions;
|
||||||
@ -42,20 +43,18 @@ import co.elastic.clients.elasticsearch.core.bulk.CreateOperation;
|
|||||||
import co.elastic.clients.elasticsearch.core.bulk.IndexOperation;
|
import co.elastic.clients.elasticsearch.core.bulk.IndexOperation;
|
||||||
import co.elastic.clients.elasticsearch.core.bulk.UpdateOperation;
|
import co.elastic.clients.elasticsearch.core.bulk.UpdateOperation;
|
||||||
import co.elastic.clients.elasticsearch.core.mget.MultiGetOperation;
|
import co.elastic.clients.elasticsearch.core.mget.MultiGetOperation;
|
||||||
|
import co.elastic.clients.elasticsearch.core.msearch.MultisearchBody;
|
||||||
import co.elastic.clients.elasticsearch.core.msearch.MultisearchHeader;
|
import co.elastic.clients.elasticsearch.core.msearch.MultisearchHeader;
|
||||||
import co.elastic.clients.elasticsearch.core.search.Highlight;
|
import co.elastic.clients.elasticsearch.core.search.Highlight;
|
||||||
import co.elastic.clients.elasticsearch.core.search.Rescore;
|
import co.elastic.clients.elasticsearch.core.search.Rescore;
|
||||||
import co.elastic.clients.elasticsearch.core.search.SearchRequestBody;
|
|
||||||
import co.elastic.clients.elasticsearch.core.search.SourceConfig;
|
import co.elastic.clients.elasticsearch.core.search.SourceConfig;
|
||||||
import co.elastic.clients.elasticsearch.indices.*;
|
import co.elastic.clients.elasticsearch.indices.*;
|
||||||
import co.elastic.clients.elasticsearch.indices.ExistsIndexTemplateRequest;
|
import co.elastic.clients.elasticsearch.indices.ExistsIndexTemplateRequest;
|
||||||
import co.elastic.clients.elasticsearch.indices.ExistsRequest;
|
import co.elastic.clients.elasticsearch.indices.ExistsRequest;
|
||||||
import co.elastic.clients.elasticsearch.indices.update_aliases.Action;
|
import co.elastic.clients.elasticsearch.indices.update_aliases.Action;
|
||||||
import co.elastic.clients.elasticsearch.sql.query.SqlFormat;
|
|
||||||
import co.elastic.clients.json.JsonData;
|
import co.elastic.clients.json.JsonData;
|
||||||
import co.elastic.clients.json.JsonpDeserializer;
|
import co.elastic.clients.json.JsonpDeserializer;
|
||||||
import co.elastic.clients.json.JsonpMapper;
|
import co.elastic.clients.json.JsonpMapper;
|
||||||
import co.elastic.clients.util.NamedValue;
|
|
||||||
import co.elastic.clients.util.ObjectBuilder;
|
import co.elastic.clients.util.ObjectBuilder;
|
||||||
import jakarta.json.stream.JsonParser;
|
import jakarta.json.stream.JsonParser;
|
||||||
|
|
||||||
@ -69,16 +68,13 @@ import java.util.Collections;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||||
import org.springframework.data.domain.Sort;
|
import org.springframework.data.domain.Sort;
|
||||||
import org.springframework.data.elasticsearch.core.RefreshPolicy;
|
import org.springframework.data.elasticsearch.core.RefreshPolicy;
|
||||||
@ -92,8 +88,6 @@ import org.springframework.data.elasticsearch.core.index.GetIndexTemplateRequest
|
|||||||
import org.springframework.data.elasticsearch.core.index.GetTemplateRequest;
|
import org.springframework.data.elasticsearch.core.index.GetTemplateRequest;
|
||||||
import org.springframework.data.elasticsearch.core.index.PutIndexTemplateRequest;
|
import org.springframework.data.elasticsearch.core.index.PutIndexTemplateRequest;
|
||||||
import org.springframework.data.elasticsearch.core.index.PutTemplateRequest;
|
import org.springframework.data.elasticsearch.core.index.PutTemplateRequest;
|
||||||
import org.springframework.data.elasticsearch.core.mapping.Alias;
|
|
||||||
import org.springframework.data.elasticsearch.core.mapping.CreateIndexSettings;
|
|
||||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
|
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
|
||||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
|
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
|
||||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||||
@ -102,6 +96,7 @@ import org.springframework.data.elasticsearch.core.reindex.ReindexRequest;
|
|||||||
import org.springframework.data.elasticsearch.core.reindex.Remote;
|
import org.springframework.data.elasticsearch.core.reindex.Remote;
|
||||||
import org.springframework.data.elasticsearch.core.script.Script;
|
import org.springframework.data.elasticsearch.core.script.Script;
|
||||||
import org.springframework.data.elasticsearch.support.DefaultStringObjectMap;
|
import org.springframework.data.elasticsearch.support.DefaultStringObjectMap;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
@ -116,6 +111,7 @@ import org.springframework.util.StringUtils;
|
|||||||
* @author Haibo Liu
|
* @author Haibo Liu
|
||||||
* @since 4.4
|
* @since 4.4
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("ClassCanBeRecord")
|
||||||
class RequestConverter extends AbstractQueryProcessor {
|
class RequestConverter extends AbstractQueryProcessor {
|
||||||
|
|
||||||
private static final Log LOGGER = LogFactory.getLog(RequestConverter.class);
|
private static final Log LOGGER = LogFactory.getLog(RequestConverter.class);
|
||||||
@ -174,8 +170,7 @@ class RequestConverter extends AbstractQueryProcessor {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
private co.elastic.clients.elasticsearch.indices.Alias.Builder buildAlias(AliasActionParameters parameters,
|
private Alias.Builder buildAlias(AliasActionParameters parameters, Alias.Builder aliasBuilder) {
|
||||||
co.elastic.clients.elasticsearch.indices.Alias.Builder aliasBuilder) {
|
|
||||||
|
|
||||||
if (parameters.getRouting() != null) {
|
if (parameters.getRouting() != null) {
|
||||||
aliasBuilder.routing(parameters.getRouting());
|
aliasBuilder.routing(parameters.getRouting());
|
||||||
@ -239,25 +234,17 @@ class RequestConverter extends AbstractQueryProcessor {
|
|||||||
return new ExistsRequest.Builder().index(Arrays.asList(indexCoordinates.getIndexNames())).build();
|
return new ExistsRequest.Builder().index(Arrays.asList(indexCoordinates.getIndexNames())).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public CreateIndexRequest indicesCreateRequest(CreateIndexSettings indexSettings) {
|
public CreateIndexRequest indicesCreateRequest(IndexCoordinates indexCoordinates, Map<String, Object> settings,
|
||||||
Map<String, co.elastic.clients.elasticsearch.indices.Alias> aliases = new HashMap<>();
|
@Nullable Document mapping) {
|
||||||
for (Alias alias : indexSettings.getAliases()) {
|
|
||||||
co.elastic.clients.elasticsearch.indices.Alias esAlias = co.elastic.clients.elasticsearch.indices.Alias
|
Assert.notNull(indexCoordinates, "indexCoordinates must not be null");
|
||||||
.of(ab -> ab.filter(getQuery(alias.getFilter(), null))
|
Assert.notNull(settings, "settings must not be null");
|
||||||
.routing(alias.getRouting())
|
|
||||||
.indexRouting(alias.getIndexRouting())
|
|
||||||
.searchRouting(alias.getSearchRouting())
|
|
||||||
.isHidden(alias.getHidden())
|
|
||||||
.isWriteIndex(alias.getWriteIndex()));
|
|
||||||
aliases.put(alias.getAlias(), esAlias);
|
|
||||||
}
|
|
||||||
|
|
||||||
// note: the new client does not support the index.storeType anymore
|
// note: the new client does not support the index.storeType anymore
|
||||||
return new CreateIndexRequest.Builder() //
|
return new CreateIndexRequest.Builder() //
|
||||||
.index(indexSettings.getIndexCoordinates().getIndexName()) //
|
.index(indexCoordinates.getIndexName()) //
|
||||||
.aliases(aliases)
|
.settings(indexSettings(settings)) //
|
||||||
.settings(indexSettings(indexSettings.getSettings())) //
|
.mappings(typeMapping(mapping)) //
|
||||||
.mappings(typeMapping(indexSettings.getMapping())) //
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -412,7 +399,7 @@ class RequestConverter extends AbstractQueryProcessor {
|
|||||||
|
|
||||||
if (putTemplateRequest.getSettings() != null) {
|
if (putTemplateRequest.getSettings() != null) {
|
||||||
Map<String, JsonData> settings = getTemplateParams(putTemplateRequest.getSettings().entrySet());
|
Map<String, JsonData> settings = getTemplateParams(putTemplateRequest.getSettings().entrySet());
|
||||||
builder.settings(sb -> sb.otherSettings(settings));
|
builder.settings(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (putTemplateRequest.getMappings() != null) {
|
if (putTemplateRequest.getMappings() != null) {
|
||||||
@ -533,27 +520,6 @@ class RequestConverter extends AbstractQueryProcessor {
|
|||||||
.of(gtr -> gtr.name(getTemplateRequest.getTemplateName()).flatSettings(true));
|
.of(gtr -> gtr.name(getTemplateRequest.getTemplateName()).flatSettings(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
public co.elastic.clients.elasticsearch.sql.QueryRequest sqlQueryRequest(SqlQuery query) {
|
|
||||||
Assert.notNull(query, "Query must not be null.");
|
|
||||||
|
|
||||||
return co.elastic.clients.elasticsearch.sql.QueryRequest.of(sqb -> sqb
|
|
||||||
.query(query.getQuery())
|
|
||||||
.catalog(query.getCatalog())
|
|
||||||
.columnar(query.getColumnar())
|
|
||||||
.cursor(query.getCursor())
|
|
||||||
.fetchSize(query.getFetchSize())
|
|
||||||
.fieldMultiValueLeniency(query.getFieldMultiValueLeniency())
|
|
||||||
.indexUsingFrozen(query.getIndexIncludeFrozen())
|
|
||||||
.keepAlive(time(query.getKeepAlive()))
|
|
||||||
.keepOnCompletion(query.getKeepOnCompletion())
|
|
||||||
.pageTimeout(time(query.getPageTimeout()))
|
|
||||||
.requestTimeout(time(query.getRequestTimeout()))
|
|
||||||
.waitForCompletionTimeout(time(query.getWaitForCompletionTimeout()))
|
|
||||||
.filter(getQuery(query.getFilter(), null))
|
|
||||||
.timeZone(Objects.toString(query.getTimeZone(), null))
|
|
||||||
.format(SqlFormat.Json));
|
|
||||||
}
|
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region documents
|
// region documents
|
||||||
@ -738,7 +704,8 @@ class RequestConverter extends AbstractQueryProcessor {
|
|||||||
return uob.build();
|
return uob.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private co.elastic.clients.elasticsearch._types.@Nullable Script getScript(@Nullable ScriptData scriptData) {
|
@Nullable
|
||||||
|
private co.elastic.clients.elasticsearch._types.Script getScript(@Nullable ScriptData scriptData) {
|
||||||
|
|
||||||
if (scriptData == null) {
|
if (scriptData == null) {
|
||||||
return null;
|
return null;
|
||||||
@ -750,11 +717,16 @@ class RequestConverter extends AbstractQueryProcessor {
|
|||||||
scriptData.params().forEach((key, value) -> params.put(key, JsonData.of(value, jsonpMapper)));
|
scriptData.params().forEach((key, value) -> params.put(key, JsonData.of(value, jsonpMapper)));
|
||||||
}
|
}
|
||||||
return co.elastic.clients.elasticsearch._types.Script.of(sb -> {
|
return co.elastic.clients.elasticsearch._types.Script.of(sb -> {
|
||||||
sb.lang(scriptData.language())
|
if (scriptData.type() == ScriptType.INLINE) {
|
||||||
.params(params)
|
sb.inline(is -> is //
|
||||||
.id(scriptData.scriptName());
|
.lang(scriptData.language()) //
|
||||||
if (scriptData.script() != null){
|
.source(scriptData.script()) //
|
||||||
sb.source(s -> s.scriptString(scriptData.script()));
|
.params(params)); //
|
||||||
|
} else if (scriptData.type() == ScriptType.STORED) {
|
||||||
|
sb.stored(ss -> ss //
|
||||||
|
.id(scriptData.script()) //
|
||||||
|
.params(params) //
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return sb;
|
return sb;
|
||||||
});
|
});
|
||||||
@ -926,13 +898,7 @@ class RequestConverter extends AbstractQueryProcessor {
|
|||||||
|
|
||||||
ReindexRequest.Script script = reindexRequest.getScript();
|
ReindexRequest.Script script = reindexRequest.getScript();
|
||||||
if (script != null) {
|
if (script != null) {
|
||||||
builder.script(sb -> {
|
builder.script(s -> s.inline(InlineScript.of(i -> i.lang(script.getLang()).source(script.getSource()))));
|
||||||
if (script.getSource() != null){
|
|
||||||
sb.source(s -> s.scriptString(script.getSource()));
|
|
||||||
}
|
|
||||||
sb.lang(script.getLang());
|
|
||||||
return sb;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.timeout(time(reindexRequest.getTimeout())) //
|
builder.timeout(time(reindexRequest.getTimeout())) //
|
||||||
@ -1050,7 +1016,7 @@ class RequestConverter extends AbstractQueryProcessor {
|
|||||||
order = sortField.order().jsonValue();
|
order = sortField.order().jsonValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
return sortField.field() + ':' + order;
|
return sortField.field() + ":" + order;
|
||||||
})
|
})
|
||||||
.collect(Collectors.toList()));
|
.collect(Collectors.toList()));
|
||||||
}
|
}
|
||||||
@ -1088,14 +1054,21 @@ class RequestConverter extends AbstractQueryProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uqb.script(sb -> {
|
uqb.script(sb -> {
|
||||||
sb.lang(query.getLang()).params(params);
|
if (query.getScriptType() == ScriptType.INLINE) {
|
||||||
if (query.getScript() != null){
|
sb.inline(is -> is //
|
||||||
sb.source(s -> s.scriptString(query.getScript()));
|
.lang(query.getLang()) //
|
||||||
|
.source(query.getScript()) //
|
||||||
|
.params(params)); //
|
||||||
|
} else if (query.getScriptType() == ScriptType.STORED) {
|
||||||
|
sb.stored(ss -> ss //
|
||||||
|
.id(query.getScript()) //
|
||||||
|
.params(params) //
|
||||||
|
);
|
||||||
}
|
}
|
||||||
sb.id(query.getId());
|
|
||||||
|
|
||||||
return sb;
|
return sb;
|
||||||
});
|
}
|
||||||
|
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
uqb //
|
uqb //
|
||||||
@ -1256,11 +1229,11 @@ class RequestConverter extends AbstractQueryProcessor {
|
|||||||
mtrb.searchTemplates(stb -> stb
|
mtrb.searchTemplates(stb -> stb
|
||||||
.header(msearchHeaderBuilder(query, param.index(), routing))
|
.header(msearchHeaderBuilder(query, param.index(), routing))
|
||||||
.body(bb -> {
|
.body(bb -> {
|
||||||
bb.explain(query.getExplain()) //
|
bb //
|
||||||
.id(query.getId()); //
|
.explain(query.getExplain()) //
|
||||||
if (query.getSource() != null){
|
.id(query.getId()) //
|
||||||
bb.source(s -> s.scriptString(query.getSource()));
|
.source(query.getSource()) //
|
||||||
}
|
;
|
||||||
|
|
||||||
if (!CollectionUtils.isEmpty(query.getParams())) {
|
if (!CollectionUtils.isEmpty(query.getParams())) {
|
||||||
Map<String, JsonData> params = getTemplateParams(query.getParams().entrySet());
|
Map<String, JsonData> params = getTemplateParams(query.getParams().entrySet());
|
||||||
@ -1296,15 +1269,11 @@ class RequestConverter extends AbstractQueryProcessor {
|
|||||||
.timeout(timeStringMs(query.getTimeout())) //
|
.timeout(timeStringMs(query.getTimeout())) //
|
||||||
;
|
;
|
||||||
|
|
||||||
var offset = query.getPageable().isPaged() ? query.getPageable().getOffset() : 0;
|
if (query.getPageable().isPaged()) {
|
||||||
var pageSize = query.getPageable().isPaged() ? query.getPageable().getPageSize()
|
bb //
|
||||||
: INDEX_MAX_RESULT_WINDOW;
|
.from((int) query.getPageable().getOffset()) //
|
||||||
// if we have both a page size and a max results, we take the min, this is necessary for
|
.size(query.getPageable().getPageSize());
|
||||||
// searchForStream to work correctly (#3098) as there the page size defines what is
|
}
|
||||||
// returned in a single request, and the max result determines the total number of
|
|
||||||
// documents returned
|
|
||||||
var size = query.isLimiting() ? Math.min(pageSize, query.getMaxResults()) : pageSize;
|
|
||||||
bb.from((int) offset).size(size);
|
|
||||||
|
|
||||||
if (!isEmpty(query.getFields())) {
|
if (!isEmpty(query.getFields())) {
|
||||||
bb.fields(fb -> {
|
bb.fields(fb -> {
|
||||||
@ -1317,6 +1286,10 @@ class RequestConverter extends AbstractQueryProcessor {
|
|||||||
bb.storedFields(query.getStoredFields());
|
bb.storedFields(query.getStoredFields());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (query.isLimiting()) {
|
||||||
|
bb.size(query.getMaxResults());
|
||||||
|
}
|
||||||
|
|
||||||
if (query.getMinScore() > 0) {
|
if (query.getMinScore() > 0) {
|
||||||
bb.minScore((double) query.getMinScore());
|
bb.minScore((double) query.getMinScore());
|
||||||
}
|
}
|
||||||
@ -1350,18 +1323,17 @@ class RequestConverter extends AbstractQueryProcessor {
|
|||||||
String script = runtimeField.getScript();
|
String script = runtimeField.getScript();
|
||||||
|
|
||||||
if (script != null) {
|
if (script != null) {
|
||||||
rfb.script(s -> {
|
rfb
|
||||||
if (script != null) {
|
.script(s -> s
|
||||||
s.source(so -> so.scriptString(script));
|
.inline(is -> {
|
||||||
}
|
is.source(script);
|
||||||
|
|
||||||
if (runtimeField.getParams() != null) {
|
if (runtimeField.getParams() != null) {
|
||||||
s.params(TypeUtils.paramsMap(runtimeField.getParams()));
|
is.params(TypeUtils.paramsMap(runtimeField.getParams()));
|
||||||
}
|
}
|
||||||
return s;
|
return is;
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
return rfb;
|
return rfb;
|
||||||
});
|
});
|
||||||
runtimeMappings.put(runtimeField.getName(), esRuntimeField);
|
runtimeMappings.put(runtimeField.getName(), esRuntimeField);
|
||||||
@ -1370,14 +1342,9 @@ class RequestConverter extends AbstractQueryProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!isEmpty(query.getIndicesBoost())) {
|
if (!isEmpty(query.getIndicesBoost())) {
|
||||||
Stream<NamedValue<Double>> namedValueStream = query.getIndicesBoost().stream()
|
bb.indicesBoost(query.getIndicesBoost().stream()
|
||||||
.map(indexBoost -> {
|
.map(indexBoost -> Map.of(indexBoost.getIndexName(), (double) indexBoost.getBoost()))
|
||||||
var namedValue = new NamedValue(indexBoost.getIndexName(),
|
.collect(Collectors.toList()));
|
||||||
Float.valueOf(indexBoost.getBoost()).doubleValue());
|
|
||||||
return namedValue;
|
|
||||||
});
|
|
||||||
List<NamedValue<Double>> namedValueList = namedValueStream.collect(Collectors.toList());
|
|
||||||
bb.indicesBoost(namedValueList);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
query.getScriptedFields().forEach(scriptedField -> bb.scriptFields(scriptedField.getFieldName(),
|
query.getScriptedFields().forEach(scriptedField -> bb.scriptFields(scriptedField.getFieldName(),
|
||||||
@ -1403,7 +1370,7 @@ class RequestConverter extends AbstractQueryProcessor {
|
|||||||
private Function<MultisearchHeader.Builder, ObjectBuilder<MultisearchHeader>> msearchHeaderBuilder(Query query,
|
private Function<MultisearchHeader.Builder, ObjectBuilder<MultisearchHeader>> msearchHeaderBuilder(Query query,
|
||||||
IndexCoordinates index, @Nullable String routing) {
|
IndexCoordinates index, @Nullable String routing) {
|
||||||
return h -> {
|
return h -> {
|
||||||
var searchType = (query instanceof NativeQuery nativeQuery && !isEmpty(nativeQuery.getKnnSearches())) ? null
|
var searchType = (query instanceof NativeQuery nativeQuery && nativeQuery.getKnnQuery() != null) ? null
|
||||||
: searchType(query.getSearchType());
|
: searchType(query.getSearchType());
|
||||||
|
|
||||||
h //
|
h //
|
||||||
@ -1435,7 +1402,7 @@ class RequestConverter extends AbstractQueryProcessor {
|
|||||||
|
|
||||||
ElasticsearchPersistentEntity<?> persistentEntity = getPersistentEntity(clazz);
|
ElasticsearchPersistentEntity<?> persistentEntity = getPersistentEntity(clazz);
|
||||||
|
|
||||||
var searchType = (query instanceof NativeQuery nativeQuery && !isEmpty(nativeQuery.getKnnSearches())) ? null
|
var searchType = (query instanceof NativeQuery nativeQuery && nativeQuery.getKnnQuery() != null) ? null
|
||||||
: searchType(query.getSearchType());
|
: searchType(query.getSearchType());
|
||||||
|
|
||||||
builder //
|
builder //
|
||||||
@ -1476,14 +1443,13 @@ class RequestConverter extends AbstractQueryProcessor {
|
|||||||
builder.seqNoPrimaryTerm(true);
|
builder.seqNoPrimaryTerm(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
var offset = query.getPageable().isPaged() ? query.getPageable().getOffset() : 0;
|
if (query.getPageable().isPaged()) {
|
||||||
var pageSize = query.getPageable().isPaged() ? query.getPageable().getPageSize() : INDEX_MAX_RESULT_WINDOW;
|
builder //
|
||||||
// if we have both a page size and a max results, we take the min, this is necessary for
|
.from((int) query.getPageable().getOffset()) //
|
||||||
// searchForStream to work correctly (#3098) as there the page size defines what is
|
.size(query.getPageable().getPageSize());
|
||||||
// returned in a single request, and the max result determines the total number of
|
} else {
|
||||||
// documents returned
|
builder.from(0).size(INDEX_MAX_RESULT_WINDOW);
|
||||||
var size = query.isLimiting() ? Math.min(pageSize, query.getMaxResults()) : pageSize;
|
}
|
||||||
builder.from((int) offset).size(size);
|
|
||||||
|
|
||||||
if (!isEmpty(query.getFields())) {
|
if (!isEmpty(query.getFields())) {
|
||||||
var fieldAndFormats = query.getFields().stream().map(field -> FieldAndFormat.of(b -> b.field(field))).toList();
|
var fieldAndFormats = query.getFields().stream().map(field -> FieldAndFormat.of(b -> b.field(field))).toList();
|
||||||
@ -1498,6 +1464,10 @@ class RequestConverter extends AbstractQueryProcessor {
|
|||||||
addIndicesOptions(builder, query.getIndicesOptions());
|
addIndicesOptions(builder, query.getIndicesOptions());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (query.isLimiting()) {
|
||||||
|
builder.size(query.getMaxResults());
|
||||||
|
}
|
||||||
|
|
||||||
if (query.getMinScore() > 0) {
|
if (query.getMinScore() > 0) {
|
||||||
builder.minScore((double) query.getMinScore());
|
builder.minScore((double) query.getMinScore());
|
||||||
}
|
}
|
||||||
@ -1554,16 +1524,16 @@ class RequestConverter extends AbstractQueryProcessor {
|
|||||||
rfb.type(RuntimeFieldType._DESERIALIZER.parse(runtimeField.getType()));
|
rfb.type(RuntimeFieldType._DESERIALIZER.parse(runtimeField.getType()));
|
||||||
String script = runtimeField.getScript();
|
String script = runtimeField.getScript();
|
||||||
if (script != null) {
|
if (script != null) {
|
||||||
rfb.script(s -> {
|
rfb
|
||||||
if (script != null) {
|
.script(s -> s
|
||||||
s.source(so -> so.scriptString(script));
|
.inline(is -> {
|
||||||
}
|
is.source(script);
|
||||||
|
|
||||||
if (runtimeField.getParams() != null) {
|
if (runtimeField.getParams() != null) {
|
||||||
s.params(TypeUtils.paramsMap(runtimeField.getParams()));
|
is.params(TypeUtils.paramsMap(runtimeField.getParams()));
|
||||||
}
|
}
|
||||||
return s;
|
return is;
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
return rfb;
|
return rfb;
|
||||||
@ -1585,14 +1555,9 @@ class RequestConverter extends AbstractQueryProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!isEmpty(query.getIndicesBoost())) {
|
if (!isEmpty(query.getIndicesBoost())) {
|
||||||
Stream<NamedValue<Double>> namedValueStream = query.getIndicesBoost().stream()
|
builder.indicesBoost(query.getIndicesBoost().stream()
|
||||||
.map(indexBoost -> {
|
.map(indexBoost -> Map.of(indexBoost.getIndexName(), (double) indexBoost.getBoost()))
|
||||||
var namedValue = new NamedValue(indexBoost.getIndexName(),
|
.collect(Collectors.toList()));
|
||||||
Float.valueOf(indexBoost.getBoost()).doubleValue());
|
|
||||||
return namedValue;
|
|
||||||
});
|
|
||||||
List<NamedValue<Double>> namedValueList = namedValueStream.collect(Collectors.toList());
|
|
||||||
builder.indicesBoost(namedValueList);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isEmpty(query.getDocValueFields())) {
|
if (!isEmpty(query.getDocValueFields())) {
|
||||||
@ -1654,7 +1619,7 @@ class RequestConverter extends AbstractQueryProcessor {
|
|||||||
builder.highlight(highlight);
|
builder.highlight(highlight);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addHighlight(Query query, SearchRequestBody.Builder builder) {
|
private void addHighlight(Query query, MultisearchBody.Builder builder) {
|
||||||
|
|
||||||
Highlight highlight = query.getHighlightQuery()
|
Highlight highlight = query.getHighlightQuery()
|
||||||
.map(highlightQuery -> new HighlightQueryBuilder(elasticsearchConverter.getMappingContext(), this)
|
.map(highlightQuery -> new HighlightQueryBuilder(elasticsearchConverter.getMappingContext(), this)
|
||||||
@ -1734,7 +1699,7 @@ class RequestConverter extends AbstractQueryProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private NestedSortValue getNestedSort(Order.@Nullable Nested nested,
|
private NestedSortValue getNestedSort(@Nullable Order.Nested nested,
|
||||||
@Nullable ElasticsearchPersistentEntity<?> persistentEntity) {
|
@Nullable ElasticsearchPersistentEntity<?> persistentEntity) {
|
||||||
return (nested == null || persistentEntity == null) ? null
|
return (nested == null || persistentEntity == null) ? null
|
||||||
: NestedSortValue.of(b -> b //
|
: NestedSortValue.of(b -> b //
|
||||||
@ -1764,6 +1729,17 @@ class RequestConverter extends AbstractQueryProcessor {
|
|||||||
.sort(query.getSortOptions()) //
|
.sort(query.getSortOptions()) //
|
||||||
;
|
;
|
||||||
|
|
||||||
|
if (query.getKnnQuery() != null) {
|
||||||
|
var kq = query.getKnnQuery();
|
||||||
|
builder.knn(ksb -> ksb
|
||||||
|
.field(kq.field())
|
||||||
|
.queryVector(kq.queryVector())
|
||||||
|
.numCandidates(kq.numCandidates())
|
||||||
|
.filter(kq.filter())
|
||||||
|
.similarity(kq.similarity()));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (!isEmpty(query.getKnnSearches())) {
|
if (!isEmpty(query.getKnnSearches())) {
|
||||||
builder.knn(query.getKnnSearches());
|
builder.knn(query.getKnnSearches());
|
||||||
}
|
}
|
||||||
@ -1778,13 +1754,24 @@ class RequestConverter extends AbstractQueryProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("DuplicatedCode")
|
@SuppressWarnings("DuplicatedCode")
|
||||||
private void prepareNativeSearch(NativeQuery query, SearchRequestBody.Builder builder) {
|
private void prepareNativeSearch(NativeQuery query, MultisearchBody.Builder builder) {
|
||||||
|
|
||||||
builder //
|
builder //
|
||||||
.suggest(query.getSuggester()) //
|
.suggest(query.getSuggester()) //
|
||||||
.collapse(query.getFieldCollapse()) //
|
.collapse(query.getFieldCollapse()) //
|
||||||
.sort(query.getSortOptions());
|
.sort(query.getSortOptions());
|
||||||
|
|
||||||
|
if (query.getKnnQuery() != null) {
|
||||||
|
var kq = query.getKnnQuery();
|
||||||
|
builder.knn(ksb -> ksb
|
||||||
|
.field(kq.field())
|
||||||
|
.queryVector(kq.queryVector())
|
||||||
|
.numCandidates(kq.numCandidates())
|
||||||
|
.filter(kq.filter())
|
||||||
|
.similarity(kq.similarity()));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (!isEmpty(query.getKnnSearches())) {
|
if (!isEmpty(query.getKnnSearches())) {
|
||||||
builder.knn(query.getKnnSearches());
|
builder.knn(query.getKnnSearches());
|
||||||
}
|
}
|
||||||
@ -1798,11 +1785,13 @@ class RequestConverter extends AbstractQueryProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
co.elastic.clients.elasticsearch._types.query_dsl.@Nullable Query getQuery(@Nullable Query query,
|
@Nullable
|
||||||
|
co.elastic.clients.elasticsearch._types.query_dsl.Query getQuery(@Nullable Query query,
|
||||||
@Nullable Class<?> clazz) {
|
@Nullable Class<?> clazz) {
|
||||||
return getEsQuery(query, (q) -> elasticsearchConverter.updateQuery(q, clazz));
|
return getEsQuery(query, (q) -> elasticsearchConverter.updateQuery(q, clazz));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("StatementWithEmptyBody")
|
||||||
private void addPostFilter(Query query, SearchRequest.Builder builder) {
|
private void addPostFilter(Query query, SearchRequest.Builder builder) {
|
||||||
|
|
||||||
// we only need to handle NativeQuery here. filter from a CriteriaQuery are added into the query and not as post
|
// we only need to handle NativeQuery here. filter from a CriteriaQuery are added into the query and not as post
|
||||||
@ -1897,11 +1886,10 @@ class RequestConverter extends AbstractQueryProcessor {
|
|||||||
.id(query.getId()) //
|
.id(query.getId()) //
|
||||||
.index(Arrays.asList(index.getIndexNames())) //
|
.index(Arrays.asList(index.getIndexNames())) //
|
||||||
.preference(query.getPreference()) //
|
.preference(query.getPreference()) //
|
||||||
.searchType(searchType(query.getSearchType())); //
|
.searchType(searchType(query.getSearchType())) //
|
||||||
|
.source(query.getSource()) //
|
||||||
|
;
|
||||||
|
|
||||||
if (query.getSource() != null) {
|
|
||||||
builder.source(so -> so.scriptString(query.getSource()));
|
|
||||||
}
|
|
||||||
if (query.getRoute() != null) {
|
if (query.getRoute() != null) {
|
||||||
builder.routing(query.getRoute());
|
builder.routing(query.getRoute());
|
||||||
} else if (StringUtils.hasText(routing)) {
|
} else if (StringUtils.hasText(routing)) {
|
||||||
@ -1944,7 +1932,7 @@ class RequestConverter extends AbstractQueryProcessor {
|
|||||||
.id(script.id()) //
|
.id(script.id()) //
|
||||||
.script(sb -> sb //
|
.script(sb -> sb //
|
||||||
.lang(script.language()) //
|
.lang(script.language()) //
|
||||||
.source(s -> s.scriptString(script.source()))));
|
.source(script.source())));
|
||||||
}
|
}
|
||||||
|
|
||||||
public GetScriptRequest scriptGet(String name) {
|
public GetScriptRequest scriptGet(String name) {
|
||||||
@ -2034,12 +2022,9 @@ class RequestConverter extends AbstractQueryProcessor {
|
|||||||
private SourceConfig getSourceConfig(Query query) {
|
private SourceConfig getSourceConfig(Query query) {
|
||||||
|
|
||||||
if (query.getSourceFilter() != null) {
|
if (query.getSourceFilter() != null) {
|
||||||
return SourceConfig.of(s -> {
|
return SourceConfig.of(s -> s //
|
||||||
|
.filter(sfb -> {
|
||||||
SourceFilter sourceFilter = query.getSourceFilter();
|
SourceFilter sourceFilter = query.getSourceFilter();
|
||||||
if (sourceFilter.fetchSource() != null) {
|
|
||||||
s.fetch(sourceFilter.fetchSource());
|
|
||||||
} else {
|
|
||||||
s.filter(sfb -> {
|
|
||||||
String[] includes = sourceFilter.getIncludes();
|
String[] includes = sourceFilter.getIncludes();
|
||||||
String[] excludes = sourceFilter.getExcludes();
|
String[] excludes = sourceFilter.getExcludes();
|
||||||
|
|
||||||
@ -2052,10 +2037,7 @@ class RequestConverter extends AbstractQueryProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return sfb;
|
return sfb;
|
||||||
});
|
}));
|
||||||
}
|
|
||||||
return s;
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -33,8 +33,6 @@ import co.elastic.clients.elasticsearch.core.mget.MultiGetResponseItem;
|
|||||||
import co.elastic.clients.elasticsearch.indices.*;
|
import co.elastic.clients.elasticsearch.indices.*;
|
||||||
import co.elastic.clients.elasticsearch.indices.get_index_template.IndexTemplateItem;
|
import co.elastic.clients.elasticsearch.indices.get_index_template.IndexTemplateItem;
|
||||||
import co.elastic.clients.elasticsearch.indices.get_mapping.IndexMappingRecord;
|
import co.elastic.clients.elasticsearch.indices.get_mapping.IndexMappingRecord;
|
||||||
import co.elastic.clients.elasticsearch.sql.QueryResponse;
|
|
||||||
import co.elastic.clients.json.JsonData;
|
|
||||||
import co.elastic.clients.json.JsonpMapper;
|
import co.elastic.clients.json.JsonpMapper;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -48,7 +46,6 @@ import java.util.stream.Collectors;
|
|||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.data.elasticsearch.ElasticsearchErrorCause;
|
import org.springframework.data.elasticsearch.ElasticsearchErrorCause;
|
||||||
import org.springframework.data.elasticsearch.core.IndexInformation;
|
import org.springframework.data.elasticsearch.core.IndexInformation;
|
||||||
import org.springframework.data.elasticsearch.core.MultiGetItem;
|
import org.springframework.data.elasticsearch.core.MultiGetItem;
|
||||||
@ -64,8 +61,8 @@ import org.springframework.data.elasticsearch.core.query.ByQueryResponse;
|
|||||||
import org.springframework.data.elasticsearch.core.query.StringQuery;
|
import org.springframework.data.elasticsearch.core.query.StringQuery;
|
||||||
import org.springframework.data.elasticsearch.core.reindex.ReindexResponse;
|
import org.springframework.data.elasticsearch.core.reindex.ReindexResponse;
|
||||||
import org.springframework.data.elasticsearch.core.script.Script;
|
import org.springframework.data.elasticsearch.core.script.Script;
|
||||||
import org.springframework.data.elasticsearch.core.sql.SqlResponse;
|
|
||||||
import org.springframework.data.elasticsearch.support.DefaultStringObjectMap;
|
import org.springframework.data.elasticsearch.support.DefaultStringObjectMap;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -92,7 +89,7 @@ class ResponseConverter {
|
|||||||
return ClusterHealth.builder() //
|
return ClusterHealth.builder() //
|
||||||
.withActivePrimaryShards(healthResponse.activePrimaryShards()) //
|
.withActivePrimaryShards(healthResponse.activePrimaryShards()) //
|
||||||
.withActiveShards(healthResponse.activeShards()) //
|
.withActiveShards(healthResponse.activeShards()) //
|
||||||
.withActiveShardsPercent(healthResponse.activeShardsPercentAsNumber())//
|
.withActiveShardsPercent(Double.parseDouble(healthResponse.activeShardsPercentAsNumber()))//
|
||||||
.withClusterName(healthResponse.clusterName()) //
|
.withClusterName(healthResponse.clusterName()) //
|
||||||
.withDelayedUnassignedShards(healthResponse.delayedUnassignedShards()) //
|
.withDelayedUnassignedShards(healthResponse.delayedUnassignedShards()) //
|
||||||
.withInitializingShards(healthResponse.initializingShards()) //
|
.withInitializingShards(healthResponse.initializingShards()) //
|
||||||
@ -191,7 +188,7 @@ class ResponseConverter {
|
|||||||
Assert.notNull(getMappingResponse, "getMappingResponse must not be null");
|
Assert.notNull(getMappingResponse, "getMappingResponse must not be null");
|
||||||
Assert.notNull(indexCoordinates, "indexCoordinates must not be null");
|
Assert.notNull(indexCoordinates, "indexCoordinates must not be null");
|
||||||
|
|
||||||
Map<String, IndexMappingRecord> mappings = getMappingResponse.mappings();
|
Map<String, IndexMappingRecord> mappings = getMappingResponse.result();
|
||||||
|
|
||||||
if (mappings == null || mappings.isEmpty()) {
|
if (mappings == null || mappings.isEmpty()) {
|
||||||
return Document.create();
|
return Document.create();
|
||||||
@ -219,7 +216,7 @@ class ResponseConverter {
|
|||||||
|
|
||||||
List<IndexInformation> indexInformationList = new ArrayList<>();
|
List<IndexInformation> indexInformationList = new ArrayList<>();
|
||||||
|
|
||||||
getIndexResponse.indices().forEach((indexName, indexState) -> {
|
getIndexResponse.result().forEach((indexName, indexState) -> {
|
||||||
Settings settings = indexState.settings() != null ? Settings.parse(toJson(indexState.settings(), jsonpMapper))
|
Settings settings = indexState.settings() != null ? Settings.parse(toJson(indexState.settings(), jsonpMapper))
|
||||||
: new Settings();
|
: new Settings();
|
||||||
Document mappings = indexState.mappings() != null ? Document.parse(toJson(indexState.mappings(), jsonpMapper))
|
Document mappings = indexState.mappings() != null ? Document.parse(toJson(indexState.mappings(), jsonpMapper))
|
||||||
@ -239,7 +236,7 @@ class ResponseConverter {
|
|||||||
Assert.notNull(getAliasResponse, "getAliasResponse must not be null");
|
Assert.notNull(getAliasResponse, "getAliasResponse must not be null");
|
||||||
|
|
||||||
Map<String, Set<AliasData>> aliasDataMap = new HashMap<>();
|
Map<String, Set<AliasData>> aliasDataMap = new HashMap<>();
|
||||||
getAliasResponse.aliases().forEach((indexName, alias) -> {
|
getAliasResponse.result().forEach((indexName, alias) -> {
|
||||||
Set<AliasData> aliasDataSet = new HashSet<>();
|
Set<AliasData> aliasDataSet = new HashSet<>();
|
||||||
alias.aliases()
|
alias.aliases()
|
||||||
.forEach((aliasName, aliasDefinition) -> aliasDataSet.add(indicesGetAliasData(aliasName, aliasDefinition)));
|
.forEach((aliasName, aliasDefinition) -> aliasDataSet.add(indicesGetAliasData(aliasName, aliasDefinition)));
|
||||||
@ -400,6 +397,7 @@ class ResponseConverter {
|
|||||||
private ReindexResponse.Failure reindexResponseFailureOf(BulkIndexByScrollFailure failure) {
|
private ReindexResponse.Failure reindexResponseFailureOf(BulkIndexByScrollFailure failure) {
|
||||||
return ReindexResponse.Failure.builder() //
|
return ReindexResponse.Failure.builder() //
|
||||||
.withIndex(failure.index()) //
|
.withIndex(failure.index()) //
|
||||||
|
.withType(failure.type()) //
|
||||||
.withId(failure.id()) //
|
.withId(failure.id()) //
|
||||||
.withStatus(failure.status())//
|
.withStatus(failure.status())//
|
||||||
.withErrorCause(toErrorCause(failure.cause())) //
|
.withErrorCause(toErrorCause(failure.cause())) //
|
||||||
@ -410,12 +408,14 @@ class ResponseConverter {
|
|||||||
private ByQueryResponse.Failure byQueryResponseFailureOf(BulkIndexByScrollFailure failure) {
|
private ByQueryResponse.Failure byQueryResponseFailureOf(BulkIndexByScrollFailure failure) {
|
||||||
return ByQueryResponse.Failure.builder() //
|
return ByQueryResponse.Failure.builder() //
|
||||||
.withIndex(failure.index()) //
|
.withIndex(failure.index()) //
|
||||||
|
.withType(failure.type()) //
|
||||||
.withId(failure.id()) //
|
.withId(failure.id()) //
|
||||||
.withStatus(failure.status())//
|
.withStatus(failure.status())//
|
||||||
.withErrorCause(toErrorCause(failure.cause())).build();
|
.withErrorCause(toErrorCause(failure.cause())).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MultiGetItem.@Nullable Failure getFailure(MultiGetResponseItem<EntityAsMap> itemResponse) {
|
@Nullable
|
||||||
|
public static MultiGetItem.Failure getFailure(MultiGetResponseItem<EntityAsMap> itemResponse) {
|
||||||
|
|
||||||
MultiGetError responseFailure = itemResponse.isFailure() ? itemResponse.failure() : null;
|
MultiGetError responseFailure = itemResponse.isFailure() ? itemResponse.failure() : null;
|
||||||
|
|
||||||
@ -497,10 +497,6 @@ class ResponseConverter {
|
|||||||
builder.withDeleted(response.deleted());
|
builder.withDeleted(response.deleted());
|
||||||
}
|
}
|
||||||
|
|
||||||
if(response.updated() != null) {
|
|
||||||
builder.withUpdated(response.updated());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response.batches() != null) {
|
if (response.batches() != null) {
|
||||||
builder.withBatches(Math.toIntExact(response.batches()));
|
builder.withBatches(Math.toIntExact(response.batches()));
|
||||||
}
|
}
|
||||||
@ -535,34 +531,11 @@ class ResponseConverter {
|
|||||||
? Script.builder() //
|
? Script.builder() //
|
||||||
.withId(response.id()) //
|
.withId(response.id()) //
|
||||||
.withLanguage(response.script().lang()) //
|
.withLanguage(response.script().lang()) //
|
||||||
.withSource(response.script().source().scriptString()).build() //
|
.withSource(response.script().source()).build() //
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region sql
|
|
||||||
public SqlResponse sqlResponse(QueryResponse response) {
|
|
||||||
SqlResponse.Builder builder = SqlResponse.builder();
|
|
||||||
builder.withRunning(Boolean.TRUE.equals(response.isRunning()))
|
|
||||||
.withPartial(Boolean.TRUE.equals(response.isPartial())).withCursor(response.cursor());
|
|
||||||
|
|
||||||
final List<SqlResponse.Column> columns = response.columns().stream()
|
|
||||||
.map(column -> new SqlResponse.Column(column.name(), column.type())).toList();
|
|
||||||
builder.withColumns(columns);
|
|
||||||
|
|
||||||
for (List<JsonData> rowValues : response.rows()) {
|
|
||||||
SqlResponse.Row.Builder rowBuilder = SqlResponse.Row.builder();
|
|
||||||
for (int idx = 0; idx < rowValues.size(); idx++) {
|
|
||||||
rowBuilder.withValue(columns.get(idx), rowValues.get(idx).toJson());
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.withRow(rowBuilder.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
// end region
|
|
||||||
|
|
||||||
// region helper functions
|
// region helper functions
|
||||||
|
|
||||||
private long timeToLong(Time time) {
|
private long timeToLong(Time time) {
|
||||||
|
@ -29,7 +29,6 @@ import co.elastic.clients.elasticsearch.core.search.Suggestion;
|
|||||||
import co.elastic.clients.elasticsearch.core.search.TotalHits;
|
import co.elastic.clients.elasticsearch.core.search.TotalHits;
|
||||||
import co.elastic.clients.json.JsonpMapper;
|
import co.elastic.clients.json.JsonpMapper;
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -39,7 +38,6 @@ import java.util.stream.Collectors;
|
|||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.data.elasticsearch.core.SearchShardStatistics;
|
import org.springframework.data.elasticsearch.core.SearchShardStatistics;
|
||||||
import org.springframework.data.elasticsearch.core.TotalHitsRelation;
|
import org.springframework.data.elasticsearch.core.TotalHitsRelation;
|
||||||
import org.springframework.data.elasticsearch.core.document.SearchDocument;
|
import org.springframework.data.elasticsearch.core.document.SearchDocument;
|
||||||
@ -49,6 +47,7 @@ import org.springframework.data.elasticsearch.core.suggest.response.PhraseSugges
|
|||||||
import org.springframework.data.elasticsearch.core.suggest.response.Suggest;
|
import org.springframework.data.elasticsearch.core.suggest.response.Suggest;
|
||||||
import org.springframework.data.elasticsearch.core.suggest.response.TermSuggestion;
|
import org.springframework.data.elasticsearch.core.suggest.response.TermSuggestion;
|
||||||
import org.springframework.data.elasticsearch.support.ScoreDoc;
|
import org.springframework.data.elasticsearch.support.ScoreDoc;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
@ -57,7 +56,6 @@ import org.springframework.util.CollectionUtils;
|
|||||||
*
|
*
|
||||||
* @author Peter-Josef Meisch
|
* @author Peter-Josef Meisch
|
||||||
* @author Haibo Liu
|
* @author Haibo Liu
|
||||||
* @author Mohamed El Harrougui
|
|
||||||
* @since 4.4
|
* @since 4.4
|
||||||
*/
|
*/
|
||||||
class SearchDocumentResponseBuilder {
|
class SearchDocumentResponseBuilder {
|
||||||
@ -85,10 +83,8 @@ class SearchDocumentResponseBuilder {
|
|||||||
Map<String, List<Suggestion<EntityAsMap>>> suggest = responseBody.suggest();
|
Map<String, List<Suggestion<EntityAsMap>>> suggest = responseBody.suggest();
|
||||||
var pointInTimeId = responseBody.pitId();
|
var pointInTimeId = responseBody.pitId();
|
||||||
var shards = responseBody.shards();
|
var shards = responseBody.shards();
|
||||||
var executionDurationInMillis = responseBody.took();
|
|
||||||
|
|
||||||
return from(hitsMetadata, shards, scrollId, pointInTimeId, executionDurationInMillis, aggregations, suggest,
|
return from(hitsMetadata, shards, scrollId, pointInTimeId, aggregations, suggest, entityCreator, jsonpMapper);
|
||||||
entityCreator, jsonpMapper);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -113,10 +109,8 @@ class SearchDocumentResponseBuilder {
|
|||||||
var aggregations = response.aggregations();
|
var aggregations = response.aggregations();
|
||||||
var suggest = response.suggest();
|
var suggest = response.suggest();
|
||||||
var pointInTimeId = response.pitId();
|
var pointInTimeId = response.pitId();
|
||||||
var executionDurationInMillis = response.took();
|
|
||||||
|
|
||||||
return from(hitsMetadata, shards, scrollId, pointInTimeId, executionDurationInMillis, aggregations, suggest,
|
return from(hitsMetadata, shards, scrollId, pointInTimeId, aggregations, suggest, entityCreator, jsonpMapper);
|
||||||
entityCreator, jsonpMapper);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -133,8 +127,7 @@ class SearchDocumentResponseBuilder {
|
|||||||
* @return the {@link SearchDocumentResponse}
|
* @return the {@link SearchDocumentResponse}
|
||||||
*/
|
*/
|
||||||
public static <T> SearchDocumentResponse from(HitsMetadata<?> hitsMetadata, @Nullable ShardStatistics shards,
|
public static <T> SearchDocumentResponse from(HitsMetadata<?> hitsMetadata, @Nullable ShardStatistics shards,
|
||||||
@Nullable String scrollId, @Nullable String pointInTimeId, long executionDurationInMillis,
|
@Nullable String scrollId, @Nullable String pointInTimeId, @Nullable Map<String, Aggregate> aggregations,
|
||||||
@Nullable Map<String, Aggregate> aggregations,
|
|
||||||
Map<String, List<Suggestion<EntityAsMap>>> suggestES, SearchDocumentResponse.EntityCreator<T> entityCreator,
|
Map<String, List<Suggestion<EntityAsMap>>> suggestES, SearchDocumentResponse.EntityCreator<T> entityCreator,
|
||||||
JsonpMapper jsonpMapper) {
|
JsonpMapper jsonpMapper) {
|
||||||
|
|
||||||
@ -158,8 +151,6 @@ class SearchDocumentResponseBuilder {
|
|||||||
|
|
||||||
float maxScore = hitsMetadata.maxScore() != null ? hitsMetadata.maxScore().floatValue() : Float.NaN;
|
float maxScore = hitsMetadata.maxScore() != null ? hitsMetadata.maxScore().floatValue() : Float.NaN;
|
||||||
|
|
||||||
Duration executionDuration = Duration.ofMillis(executionDurationInMillis);
|
|
||||||
|
|
||||||
List<SearchDocument> searchDocuments = new ArrayList<>();
|
List<SearchDocument> searchDocuments = new ArrayList<>();
|
||||||
for (Hit<?> hit : hitsMetadata.hits()) {
|
for (Hit<?> hit : hitsMetadata.hits()) {
|
||||||
searchDocuments.add(DocumentAdapters.from(hit, jsonpMapper));
|
searchDocuments.add(DocumentAdapters.from(hit, jsonpMapper));
|
||||||
@ -172,8 +163,7 @@ class SearchDocumentResponseBuilder {
|
|||||||
|
|
||||||
SearchShardStatistics shardStatistics = shards != null ? shardsFrom(shards) : null;
|
SearchShardStatistics shardStatistics = shards != null ? shardsFrom(shards) : null;
|
||||||
|
|
||||||
return new SearchDocumentResponse(totalHits, totalHitsRelation, maxScore, executionDuration, scrollId,
|
return new SearchDocumentResponse(totalHits, totalHitsRelation, maxScore, scrollId, pointInTimeId, searchDocuments,
|
||||||
pointInTimeId, searchDocuments,
|
|
||||||
aggregationsContainer, suggest, shardStatistics);
|
aggregationsContainer, suggest, shardStatistics);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +38,6 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.data.domain.Sort;
|
import org.springframework.data.domain.Sort;
|
||||||
import org.springframework.data.elasticsearch.core.RefreshPolicy;
|
import org.springframework.data.elasticsearch.core.RefreshPolicy;
|
||||||
import org.springframework.data.elasticsearch.core.document.Document;
|
import org.springframework.data.elasticsearch.core.document.Document;
|
||||||
@ -53,6 +52,7 @@ import org.springframework.data.elasticsearch.core.query.UpdateResponse;
|
|||||||
import org.springframework.data.elasticsearch.core.query.types.ConflictsType;
|
import org.springframework.data.elasticsearch.core.query.types.ConflictsType;
|
||||||
import org.springframework.data.elasticsearch.core.query.types.OperatorType;
|
import org.springframework.data.elasticsearch.core.query.types.OperatorType;
|
||||||
import org.springframework.data.elasticsearch.core.reindex.ReindexRequest;
|
import org.springframework.data.elasticsearch.core.reindex.ReindexRequest;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -220,7 +220,7 @@ final class TypeUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
static SortOrder sortOrder(Sort.@Nullable Direction direction) {
|
static SortOrder sortOrder(@Nullable Sort.Direction direction) {
|
||||||
|
|
||||||
if (direction == null) {
|
if (direction == null) {
|
||||||
return null;
|
return null;
|
||||||
@ -301,7 +301,7 @@ final class TypeUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
static OpType opType(IndexQuery.@Nullable OpType opType) {
|
static OpType opType(@Nullable IndexQuery.OpType opType) {
|
||||||
|
|
||||||
if (opType != null) {
|
if (opType != null) {
|
||||||
return switch (opType) {
|
return switch (opType) {
|
||||||
@ -325,7 +325,8 @@ final class TypeUtils {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static UpdateResponse.@Nullable Result result(@Nullable Result result) {
|
@Nullable
|
||||||
|
static UpdateResponse.Result result(@Nullable Result result) {
|
||||||
|
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
return null;
|
return null;
|
||||||
@ -342,7 +343,7 @@ final class TypeUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
static ScoreMode scoreMode(RescorerQuery.@Nullable ScoreMode scoreMode) {
|
static ScoreMode scoreMode(@Nullable RescorerQuery.ScoreMode scoreMode) {
|
||||||
|
|
||||||
if (scoreMode == null) {
|
if (scoreMode == null) {
|
||||||
return null;
|
return null;
|
||||||
@ -360,7 +361,7 @@ final class TypeUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
static SearchType searchType(Query.@Nullable SearchType searchType) {
|
static SearchType searchType(@Nullable Query.SearchType searchType) {
|
||||||
|
|
||||||
if (searchType == null) {
|
if (searchType == null) {
|
||||||
return null;
|
return null;
|
||||||
@ -417,7 +418,7 @@ final class TypeUtils {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
static VersionType versionType(
|
static VersionType versionType(
|
||||||
org.springframework.data.elasticsearch.annotations.Document.@Nullable VersionType versionType) {
|
@Nullable org.springframework.data.elasticsearch.annotations.Document.VersionType versionType) {
|
||||||
|
|
||||||
if (versionType != null) {
|
if (versionType != null) {
|
||||||
return switch (versionType) {
|
return switch (versionType) {
|
||||||
@ -535,7 +536,7 @@ final class TypeUtils {
|
|||||||
* @param scoreMode spring-data-elasticsearch {@literal scoreMode}.
|
* @param scoreMode spring-data-elasticsearch {@literal scoreMode}.
|
||||||
* @return an Elasticsearch {@literal scoreMode}.
|
* @return an Elasticsearch {@literal scoreMode}.
|
||||||
*/
|
*/
|
||||||
static ChildScoreMode scoreMode(HasChildQuery.@Nullable ScoreMode scoreMode) {
|
static ChildScoreMode scoreMode(@Nullable HasChildQuery.ScoreMode scoreMode) {
|
||||||
if (scoreMode == null) {
|
if (scoreMode == null) {
|
||||||
return ChildScoreMode.None;
|
return ChildScoreMode.None;
|
||||||
}
|
}
|
||||||
|
@ -19,11 +19,11 @@ import co.elastic.clients.elasticsearch._types.mapping.RuntimeFieldType;
|
|||||||
import co.elastic.clients.elasticsearch._types.mapping.TypeMapping;
|
import co.elastic.clients.elasticsearch._types.mapping.TypeMapping;
|
||||||
import co.elastic.clients.elasticsearch.indices.IndexSettings;
|
import co.elastic.clients.elasticsearch.indices.IndexSettings;
|
||||||
import co.elastic.clients.elasticsearch.indices.PutMappingRequest;
|
import co.elastic.clients.elasticsearch.indices.PutMappingRequest;
|
||||||
|
import org.springframework.aot.hint.MemberCategory;
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.aot.hint.RuntimeHints;
|
import org.springframework.aot.hint.RuntimeHints;
|
||||||
import org.springframework.aot.hint.RuntimeHintsRegistrar;
|
import org.springframework.aot.hint.RuntimeHintsRegistrar;
|
||||||
import org.springframework.aot.hint.TypeReference;
|
import org.springframework.aot.hint.TypeReference;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* runtime hints for the Elasticsearch client libraries, as these do not provide any of their own.
|
* runtime hints for the Elasticsearch client libraries, as these do not provide any of their own.
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
@org.jspecify.annotations.NullMarked
|
@org.springframework.lang.NonNullApi
|
||||||
|
@org.springframework.lang.NonNullFields
|
||||||
package org.springframework.data.elasticsearch.client.elc.aot;
|
package org.springframework.data.elasticsearch.client.elc.aot;
|
||||||
|
@ -18,5 +18,6 @@
|
|||||||
* This package contains classes that use the new Elasticsearch client library (co.elastic.clients:elasticsearch-java)
|
* This package contains classes that use the new Elasticsearch client library (co.elastic.clients:elasticsearch-java)
|
||||||
* to access Elasticsearch.
|
* to access Elasticsearch.
|
||||||
*/
|
*/
|
||||||
@org.jspecify.annotations.NullMarked
|
@org.springframework.lang.NonNullApi
|
||||||
|
@org.springframework.lang.NonNullFields
|
||||||
package org.springframework.data.elasticsearch.client.elc;
|
package org.springframework.data.elasticsearch.client.elc;
|
||||||
|
@ -1,274 +0,0 @@
|
|||||||
package org.springframework.data.elasticsearch.client.elc.rest5_client;
|
|
||||||
|
|
||||||
import co.elastic.clients.transport.TransportOptions;
|
|
||||||
import co.elastic.clients.transport.TransportUtils;
|
|
||||||
import co.elastic.clients.transport.rest5_client.Rest5ClientOptions;
|
|
||||||
import co.elastic.clients.transport.rest5_client.low_level.RequestOptions;
|
|
||||||
import co.elastic.clients.transport.rest5_client.low_level.Rest5Client;
|
|
||||||
import co.elastic.clients.transport.rest5_client.low_level.Rest5ClientBuilder;
|
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.net.URI;
|
|
||||||
import java.net.URISyntaxException;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.concurrent.ThreadFactory;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
import javax.net.ssl.SSLContext;
|
|
||||||
|
|
||||||
import org.apache.hc.client5.http.config.ConnectionConfig;
|
|
||||||
import org.apache.hc.client5.http.config.RequestConfig;
|
|
||||||
import org.apache.hc.client5.http.impl.DefaultAuthenticationStrategy;
|
|
||||||
import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
|
|
||||||
import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder;
|
|
||||||
import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager;
|
|
||||||
import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder;
|
|
||||||
import org.apache.hc.client5.http.impl.routing.DefaultProxyRoutePlanner;
|
|
||||||
import org.apache.hc.core5.http.Header;
|
|
||||||
import org.apache.hc.core5.http.HttpHost;
|
|
||||||
import org.apache.hc.core5.http.message.BasicHeader;
|
|
||||||
import org.apache.hc.core5.http.nio.ssl.BasicClientTlsStrategy;
|
|
||||||
import org.apache.hc.core5.util.Timeout;
|
|
||||||
import org.jspecify.annotations.NonNull;
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.data.elasticsearch.client.ClientConfiguration;
|
|
||||||
import org.springframework.data.elasticsearch.support.HttpHeaders;
|
|
||||||
import org.springframework.data.elasticsearch.support.VersionInfo;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility class containing the functions to create the Elasticsearch Rest5Client used from Elasticsearch 9 on.
|
|
||||||
*
|
|
||||||
* @since 6.0
|
|
||||||
*/
|
|
||||||
public final class Rest5Clients {
|
|
||||||
|
|
||||||
// values copied from Rest5ClientBuilder
|
|
||||||
public static final int DEFAULT_CONNECT_TIMEOUT_MILLIS = 1000;
|
|
||||||
public static final int DEFAULT_SOCKET_TIMEOUT_MILLIS = 30000;
|
|
||||||
public static final int DEFAULT_RESPONSE_TIMEOUT_MILLIS = 0; // meaning infinite
|
|
||||||
public static final int DEFAULT_MAX_CONN_PER_ROUTE = 10;
|
|
||||||
public static final int DEFAULT_MAX_CONN_TOTAL = 30;
|
|
||||||
|
|
||||||
private Rest5Clients() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a low level {@link Rest5Client} for the given configuration.
|
|
||||||
*
|
|
||||||
* @param clientConfiguration must not be {@literal null}
|
|
||||||
* @return the {@link Rest5Client}
|
|
||||||
*/
|
|
||||||
public static Rest5Client getRest5Client(ClientConfiguration clientConfiguration) {
|
|
||||||
return getRest5ClientBuilder(clientConfiguration).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Rest5ClientBuilder getRest5ClientBuilder(ClientConfiguration clientConfiguration) {
|
|
||||||
|
|
||||||
HttpHost[] httpHosts = getHttpHosts(clientConfiguration);
|
|
||||||
Rest5ClientBuilder builder = Rest5Client.builder(httpHosts);
|
|
||||||
|
|
||||||
if (clientConfiguration.getPathPrefix() != null) {
|
|
||||||
builder.setPathPrefix(clientConfiguration.getPathPrefix());
|
|
||||||
}
|
|
||||||
|
|
||||||
HttpHeaders headers = clientConfiguration.getDefaultHeaders();
|
|
||||||
|
|
||||||
if (!headers.isEmpty()) {
|
|
||||||
builder.setDefaultHeaders(toHeaderArray(headers));
|
|
||||||
}
|
|
||||||
|
|
||||||
// we need to provide our own HttpClient, as the Rest5ClientBuilder
|
|
||||||
// does not provide a callback for configuration the http client as the old RestClientBuilder.
|
|
||||||
var httpClient = createHttpClient(clientConfiguration);
|
|
||||||
builder.setHttpClient(httpClient);
|
|
||||||
|
|
||||||
for (ClientConfiguration.ClientConfigurationCallback<?> clientConfigurationCallback : clientConfiguration
|
|
||||||
.getClientConfigurers()) {
|
|
||||||
if (clientConfigurationCallback instanceof ElasticsearchRest5ClientConfigurationCallback configurationCallback) {
|
|
||||||
builder = configurationCallback.configure(builder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static HttpHost @NonNull [] getHttpHosts(ClientConfiguration clientConfiguration) {
|
|
||||||
List<InetSocketAddress> hosts = clientConfiguration.getEndpoints();
|
|
||||||
boolean useSsl = clientConfiguration.useSsl();
|
|
||||||
return hosts.stream()
|
|
||||||
.map(it -> (useSsl ? "https" : "http") + "://" + it.getHostString() + ':' + it.getPort())
|
|
||||||
.map(URI::create)
|
|
||||||
.map(HttpHost::create)
|
|
||||||
.toArray(HttpHost[]::new);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Header[] toHeaderArray(HttpHeaders headers) {
|
|
||||||
return headers.entrySet().stream() //
|
|
||||||
.flatMap(entry -> entry.getValue().stream() //
|
|
||||||
.map(value -> new BasicHeader(entry.getKey(), value))) //
|
|
||||||
.toList().toArray(new Header[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// the basic logic to create the http client is copied from the Rest5ClientBuilder class, this is taken from the
|
|
||||||
// Elasticsearch code, as there is no public usable instance in that
|
|
||||||
private static CloseableHttpAsyncClient createHttpClient(ClientConfiguration clientConfiguration) {
|
|
||||||
|
|
||||||
var requestConfigBuilder = RequestConfig.custom();
|
|
||||||
var connectionConfigBuilder = ConnectionConfig.custom();
|
|
||||||
|
|
||||||
Duration connectTimeout = clientConfiguration.getConnectTimeout();
|
|
||||||
|
|
||||||
if (!connectTimeout.isNegative()) {
|
|
||||||
connectionConfigBuilder.setConnectTimeout(
|
|
||||||
Timeout.of(Math.toIntExact(connectTimeout.toMillis()), TimeUnit.MILLISECONDS));
|
|
||||||
}
|
|
||||||
|
|
||||||
Duration socketTimeout = clientConfiguration.getSocketTimeout();
|
|
||||||
|
|
||||||
if (!socketTimeout.isNegative()) {
|
|
||||||
var soTimeout = Timeout.of(Math.toIntExact(socketTimeout.toMillis()), TimeUnit.MILLISECONDS);
|
|
||||||
connectionConfigBuilder.setSocketTimeout(soTimeout);
|
|
||||||
requestConfigBuilder.setConnectionRequestTimeout(soTimeout);
|
|
||||||
} else {
|
|
||||||
connectionConfigBuilder.setSocketTimeout(Timeout.of(DEFAULT_SOCKET_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS));
|
|
||||||
requestConfigBuilder
|
|
||||||
.setConnectionRequestTimeout(Timeout.of(DEFAULT_RESPONSE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS));
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
SSLContext sslContext = clientConfiguration.getCaFingerprint().isPresent()
|
|
||||||
? TransportUtils.sslContextFromCaFingerprint(clientConfiguration.getCaFingerprint().get())
|
|
||||||
: (clientConfiguration.getSslContext().isPresent()
|
|
||||||
? clientConfiguration.getSslContext().get()
|
|
||||||
: SSLContext.getDefault());
|
|
||||||
|
|
||||||
ConnectionConfig connectionConfig = connectionConfigBuilder.build();
|
|
||||||
|
|
||||||
PoolingAsyncClientConnectionManager defaultConnectionManager = PoolingAsyncClientConnectionManagerBuilder.create()
|
|
||||||
.setDefaultConnectionConfig(connectionConfig)
|
|
||||||
.setMaxConnPerRoute(DEFAULT_MAX_CONN_PER_ROUTE)
|
|
||||||
.setMaxConnTotal(DEFAULT_MAX_CONN_TOTAL)
|
|
||||||
.setTlsStrategy(new BasicClientTlsStrategy(sslContext))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
var requestConfig = requestConfigBuilder.build();
|
|
||||||
|
|
||||||
var immutableRefToHttpClientBuilder = new Object() {
|
|
||||||
HttpAsyncClientBuilder httpClientBuilder = HttpAsyncClientBuilder.create()
|
|
||||||
.setDefaultRequestConfig(requestConfig)
|
|
||||||
.setConnectionManager(defaultConnectionManager)
|
|
||||||
.setUserAgent(VersionInfo.clientVersions())
|
|
||||||
.setTargetAuthenticationStrategy(new DefaultAuthenticationStrategy())
|
|
||||||
.setThreadFactory(new RestClientThreadFactory());
|
|
||||||
};
|
|
||||||
|
|
||||||
clientConfiguration.getProxy().ifPresent(proxy -> {
|
|
||||||
try {
|
|
||||||
var proxyRoutePlanner = new DefaultProxyRoutePlanner(HttpHost.create(proxy));
|
|
||||||
immutableRefToHttpClientBuilder.httpClientBuilder.setRoutePlanner(proxyRoutePlanner);
|
|
||||||
} catch (URISyntaxException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
immutableRefToHttpClientBuilder.httpClientBuilder.addRequestInterceptorFirst((request, entity, context) -> {
|
|
||||||
clientConfiguration.getHeadersSupplier().get().forEach((header, values) -> {
|
|
||||||
// The accept and content-type headers are already put on the request, despite this being the first
|
|
||||||
// interceptor.
|
|
||||||
if ("Accept".equalsIgnoreCase(header) || " Content-Type".equalsIgnoreCase(header)) {
|
|
||||||
request.removeHeaders(header);
|
|
||||||
}
|
|
||||||
values.forEach(value -> request.addHeader(header, value));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
for (ClientConfiguration.ClientConfigurationCallback<?> clientConfigurer : clientConfiguration
|
|
||||||
.getClientConfigurers()) {
|
|
||||||
if (clientConfigurer instanceof ElasticsearchHttpClientConfigurationCallback httpClientConfigurer) {
|
|
||||||
immutableRefToHttpClientBuilder.httpClientBuilder = httpClientConfigurer.configure(immutableRefToHttpClientBuilder.httpClientBuilder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return immutableRefToHttpClientBuilder.httpClientBuilder.build();
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
throw new IllegalStateException("could not create the default ssl context", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copied from the Elasticsearch code as this class is not public there.
|
|
||||||
*/
|
|
||||||
private static class RestClientThreadFactory implements ThreadFactory {
|
|
||||||
private static final AtomicLong CLIENT_THREAD_POOL_ID_GENERATOR = new AtomicLong();
|
|
||||||
private final long clientThreadPoolId;
|
|
||||||
private final AtomicLong clientThreadId;
|
|
||||||
|
|
||||||
private RestClientThreadFactory() {
|
|
||||||
this.clientThreadPoolId = CLIENT_THREAD_POOL_ID_GENERATOR.getAndIncrement();
|
|
||||||
this.clientThreadId = new AtomicLong();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Thread newThread(Runnable runnable) {
|
|
||||||
return new Thread(runnable, String.format(Locale.ROOT, "elasticsearch-rest-client-%d-thread-%d",
|
|
||||||
this.clientThreadPoolId, this.clientThreadId.incrementAndGet()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link org.springframework.data.elasticsearch.client.ClientConfiguration.ClientConfigurationCallback} to configure
|
|
||||||
* the Elasticsearch Rest5Client's Http client with a {@link HttpAsyncClientBuilder}
|
|
||||||
*
|
|
||||||
* @since 6.0
|
|
||||||
*/
|
|
||||||
public interface ElasticsearchHttpClientConfigurationCallback
|
|
||||||
extends ClientConfiguration.ClientConfigurationCallback<HttpAsyncClientBuilder> {
|
|
||||||
|
|
||||||
static Rest5Clients.ElasticsearchHttpClientConfigurationCallback from(
|
|
||||||
Function<HttpAsyncClientBuilder, HttpAsyncClientBuilder> httpClientBuilderCallback) {
|
|
||||||
|
|
||||||
Assert.notNull(httpClientBuilderCallback, "httpClientBuilderCallback must not be null");
|
|
||||||
|
|
||||||
return httpClientBuilderCallback::apply;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link ClientConfiguration.ClientConfigurationCallback} to configure the Rest5Client client with a
|
|
||||||
* {@link Rest5ClientBuilder}
|
|
||||||
*
|
|
||||||
* @since 6.0
|
|
||||||
*/
|
|
||||||
public interface ElasticsearchRest5ClientConfigurationCallback
|
|
||||||
extends ClientConfiguration.ClientConfigurationCallback<Rest5ClientBuilder> {
|
|
||||||
|
|
||||||
static ElasticsearchRest5ClientConfigurationCallback from(
|
|
||||||
Function<Rest5ClientBuilder, Rest5ClientBuilder> rest5ClientBuilderCallback) {
|
|
||||||
|
|
||||||
Assert.notNull(rest5ClientBuilderCallback, "rest5ClientBuilderCallback must not be null");
|
|
||||||
|
|
||||||
return rest5ClientBuilderCallback::apply;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Rest5ClientOptions.Builder getRest5ClientOptionsBuilder(@Nullable TransportOptions transportOptions) {
|
|
||||||
|
|
||||||
if (transportOptions instanceof Rest5ClientOptions rest5ClientOptions) {
|
|
||||||
return rest5ClientOptions.toBuilder();
|
|
||||||
}
|
|
||||||
|
|
||||||
var builder = new Rest5ClientOptions.Builder(RequestOptions.DEFAULT.toBuilder());
|
|
||||||
|
|
||||||
if (transportOptions != null) {
|
|
||||||
transportOptions.headers().forEach(header -> builder.addHeader(header.getKey(), header.getValue()));
|
|
||||||
transportOptions.queryParameters().forEach(builder::setParameter);
|
|
||||||
builder.onWarnings(transportOptions.onWarnings());
|
|
||||||
}
|
|
||||||
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2025 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This package contains related to the new (from Elasticsearch 9 on) Rest5Client. There are also classes copied over from Elasticsearch in order to have a Rest5ClientBuilder that allows to configure the http client.
|
|
||||||
*/
|
|
||||||
@org.jspecify.annotations.NullMarked
|
|
||||||
package org.springframework.data.elasticsearch.client.elc.rest5_client;
|
|
@ -1,195 +0,0 @@
|
|||||||
package org.springframework.data.elasticsearch.client.elc.rest_client;
|
|
||||||
|
|
||||||
import co.elastic.clients.transport.TransportOptions;
|
|
||||||
import co.elastic.clients.transport.TransportUtils;
|
|
||||||
import co.elastic.clients.transport.rest_client.RestClientOptions;
|
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
import org.apache.http.HttpHost;
|
|
||||||
import org.apache.http.HttpRequest;
|
|
||||||
import org.apache.http.HttpRequestInterceptor;
|
|
||||||
import org.apache.http.client.config.RequestConfig;
|
|
||||||
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
|
|
||||||
import org.apache.http.message.BasicHeader;
|
|
||||||
import org.apache.http.protocol.HttpContext;
|
|
||||||
import org.elasticsearch.client.RequestOptions;
|
|
||||||
import org.elasticsearch.client.RestClient;
|
|
||||||
import org.elasticsearch.client.RestClientBuilder;
|
|
||||||
import org.jspecify.annotations.NonNull;
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.data.elasticsearch.client.ClientConfiguration;
|
|
||||||
import org.springframework.data.elasticsearch.client.elc.ElasticsearchClients;
|
|
||||||
import org.springframework.data.elasticsearch.support.HttpHeaders;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility class containing the functions to create the Elasticsearch RestClient used up to Elasticsearch 9.
|
|
||||||
*
|
|
||||||
* @since 6.0
|
|
||||||
* @deprecated since 6.0, use the new Rest5Client the code for that is in the package ../rest_client.
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.0", forRemoval = true)
|
|
||||||
public final class RestClients {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a low level {@link RestClient} for the given configuration.
|
|
||||||
*
|
|
||||||
* @param clientConfiguration must not be {@literal null}
|
|
||||||
* @return the {@link RestClient}
|
|
||||||
*/
|
|
||||||
public static RestClient getRestClient(ClientConfiguration clientConfiguration) {
|
|
||||||
return getRestClientBuilder(clientConfiguration).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static RestClientBuilder getRestClientBuilder(ClientConfiguration clientConfiguration) {
|
|
||||||
HttpHost[] httpHosts = getHttpHosts(clientConfiguration);
|
|
||||||
RestClientBuilder builder = RestClient.builder(httpHosts);
|
|
||||||
|
|
||||||
if (clientConfiguration.getPathPrefix() != null) {
|
|
||||||
builder.setPathPrefix(clientConfiguration.getPathPrefix());
|
|
||||||
}
|
|
||||||
|
|
||||||
HttpHeaders headers = clientConfiguration.getDefaultHeaders();
|
|
||||||
|
|
||||||
if (!headers.isEmpty()) {
|
|
||||||
builder.setDefaultHeaders(toHeaderArray(headers));
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.setHttpClientConfigCallback(clientBuilder -> {
|
|
||||||
if (clientConfiguration.getCaFingerprint().isPresent()) {
|
|
||||||
clientBuilder
|
|
||||||
.setSSLContext(TransportUtils.sslContextFromCaFingerprint(clientConfiguration.getCaFingerprint().get()));
|
|
||||||
}
|
|
||||||
clientConfiguration.getSslContext().ifPresent(clientBuilder::setSSLContext);
|
|
||||||
clientConfiguration.getHostNameVerifier().ifPresent(clientBuilder::setSSLHostnameVerifier);
|
|
||||||
clientBuilder.addInterceptorLast(new CustomHeaderInjector(clientConfiguration.getHeadersSupplier()));
|
|
||||||
|
|
||||||
RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();
|
|
||||||
Duration connectTimeout = clientConfiguration.getConnectTimeout();
|
|
||||||
|
|
||||||
if (!connectTimeout.isNegative()) {
|
|
||||||
requestConfigBuilder.setConnectTimeout(Math.toIntExact(connectTimeout.toMillis()));
|
|
||||||
}
|
|
||||||
|
|
||||||
Duration socketTimeout = clientConfiguration.getSocketTimeout();
|
|
||||||
|
|
||||||
if (!socketTimeout.isNegative()) {
|
|
||||||
requestConfigBuilder.setSocketTimeout(Math.toIntExact(socketTimeout.toMillis()));
|
|
||||||
requestConfigBuilder.setConnectionRequestTimeout(Math.toIntExact(socketTimeout.toMillis()));
|
|
||||||
}
|
|
||||||
|
|
||||||
clientBuilder.setDefaultRequestConfig(requestConfigBuilder.build());
|
|
||||||
|
|
||||||
clientConfiguration.getProxy().map(HttpHost::create).ifPresent(clientBuilder::setProxy);
|
|
||||||
|
|
||||||
for (ClientConfiguration.ClientConfigurationCallback<?> clientConfigurer : clientConfiguration
|
|
||||||
.getClientConfigurers()) {
|
|
||||||
if (clientConfigurer instanceof RestClients.ElasticsearchHttpClientConfigurationCallback restClientConfigurationCallback) {
|
|
||||||
clientBuilder = restClientConfigurationCallback.configure(clientBuilder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return clientBuilder;
|
|
||||||
});
|
|
||||||
|
|
||||||
for (ClientConfiguration.ClientConfigurationCallback<?> clientConfigurationCallback : clientConfiguration
|
|
||||||
.getClientConfigurers()) {
|
|
||||||
if (clientConfigurationCallback instanceof ElasticsearchRestClientConfigurationCallback configurationCallback) {
|
|
||||||
builder = configurationCallback.configure(builder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static HttpHost @NonNull [] getHttpHosts(ClientConfiguration clientConfiguration) {
|
|
||||||
List<InetSocketAddress> hosts = clientConfiguration.getEndpoints();
|
|
||||||
boolean useSsl = clientConfiguration.useSsl();
|
|
||||||
return hosts.stream()
|
|
||||||
.map(it -> (useSsl ? "https" : "http") + "://" + it.getHostString() + ':' + it.getPort())
|
|
||||||
.map(HttpHost::create).toArray(HttpHost[]::new);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static org.apache.http.Header[] toHeaderArray(HttpHeaders headers) {
|
|
||||||
return headers.entrySet().stream() //
|
|
||||||
.flatMap(entry -> entry.getValue().stream() //
|
|
||||||
.map(value -> new BasicHeader(entry.getKey(), value))) //
|
|
||||||
.toArray(org.apache.http.Header[]::new);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interceptor to inject custom supplied headers.
|
|
||||||
*
|
|
||||||
* @since 4.4
|
|
||||||
*/
|
|
||||||
record CustomHeaderInjector(Supplier<HttpHeaders> headersSupplier) implements HttpRequestInterceptor {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void process(HttpRequest request, HttpContext context) {
|
|
||||||
HttpHeaders httpHeaders = headersSupplier.get();
|
|
||||||
|
|
||||||
if (httpHeaders != null && !httpHeaders.isEmpty()) {
|
|
||||||
Arrays.stream(toHeaderArray(httpHeaders)).forEach(request::addHeader);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link org.springframework.data.elasticsearch.client.ClientConfiguration.ClientConfigurationCallback} to configure
|
|
||||||
* the Elasticsearch RestClient's Http client with a {@link HttpAsyncClientBuilder}
|
|
||||||
*
|
|
||||||
* @since 4.4
|
|
||||||
*/
|
|
||||||
public interface ElasticsearchHttpClientConfigurationCallback
|
|
||||||
extends ClientConfiguration.ClientConfigurationCallback<HttpAsyncClientBuilder> {
|
|
||||||
|
|
||||||
static RestClients.ElasticsearchHttpClientConfigurationCallback from(
|
|
||||||
Function<HttpAsyncClientBuilder, HttpAsyncClientBuilder> httpClientBuilderCallback) {
|
|
||||||
|
|
||||||
Assert.notNull(httpClientBuilderCallback, "httpClientBuilderCallback must not be null");
|
|
||||||
|
|
||||||
return httpClientBuilderCallback::apply;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link org.springframework.data.elasticsearch.client.ClientConfiguration.ClientConfigurationCallback} to configure
|
|
||||||
* the RestClient client with a {@link RestClientBuilder}
|
|
||||||
*
|
|
||||||
* @since 5.0
|
|
||||||
*/
|
|
||||||
public interface ElasticsearchRestClientConfigurationCallback
|
|
||||||
extends ClientConfiguration.ClientConfigurationCallback<RestClientBuilder> {
|
|
||||||
|
|
||||||
static ElasticsearchRestClientConfigurationCallback from(
|
|
||||||
Function<RestClientBuilder, RestClientBuilder> restClientBuilderCallback) {
|
|
||||||
|
|
||||||
Assert.notNull(restClientBuilderCallback, "restClientBuilderCallback must not be null");
|
|
||||||
|
|
||||||
return restClientBuilderCallback::apply;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static RestClientOptions.Builder getRestClientOptionsBuilder(@Nullable TransportOptions transportOptions) {
|
|
||||||
|
|
||||||
if (transportOptions instanceof RestClientOptions restClientOptions) {
|
|
||||||
return restClientOptions.toBuilder();
|
|
||||||
}
|
|
||||||
|
|
||||||
var builder = new RestClientOptions.Builder(RequestOptions.DEFAULT.toBuilder());
|
|
||||||
|
|
||||||
if (transportOptions != null) {
|
|
||||||
transportOptions.headers().forEach(header -> builder.addHeader(header.getKey(), header.getValue()));
|
|
||||||
transportOptions.queryParameters().forEach(builder::setParameter);
|
|
||||||
builder.onWarnings(transportOptions.onWarnings());
|
|
||||||
}
|
|
||||||
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2022-2025 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This package contains related to the old (up to Elasticsearch 9) RestClient.
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.0", forRemoval=true)
|
|
||||||
@org.jspecify.annotations.NullMarked
|
|
||||||
package org.springframework.data.elasticsearch.client.elc.rest_client;
|
|
@ -1,2 +1,3 @@
|
|||||||
@org.jspecify.annotations.NullMarked
|
@org.springframework.lang.NonNullApi
|
||||||
|
@org.springframework.lang.NonNullFields
|
||||||
package org.springframework.data.elasticsearch.client;
|
package org.springframework.data.elasticsearch.client;
|
||||||
|
@ -19,7 +19,7 @@ import java.util.LinkedHashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
@org.jspecify.annotations.NullMarked
|
@org.springframework.lang.NonNullApi
|
||||||
|
@org.springframework.lang.NonNullFields
|
||||||
package org.springframework.data.elasticsearch.client.util;
|
package org.springframework.data.elasticsearch.client.util;
|
||||||
|
@ -17,7 +17,6 @@ package org.springframework.data.elasticsearch.config;
|
|||||||
|
|
||||||
import static org.springframework.data.config.ParsingUtils.*;
|
import static org.springframework.data.config.ParsingUtils.*;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||||
@ -29,6 +28,7 @@ import org.springframework.data.auditing.config.IsNewAwareAuditingHandlerBeanDef
|
|||||||
import org.springframework.data.elasticsearch.core.event.AuditingEntityCallback;
|
import org.springframework.data.elasticsearch.core.event.AuditingEntityCallback;
|
||||||
import org.springframework.data.elasticsearch.core.event.ReactiveAuditingEntityCallback;
|
import org.springframework.data.elasticsearch.core.event.ReactiveAuditingEntityCallback;
|
||||||
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
|
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.util.ClassUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
|
@ -20,7 +20,6 @@ import java.util.Collections;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
|
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
|
||||||
@ -35,6 +34,7 @@ import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchC
|
|||||||
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
|
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
|
||||||
import org.springframework.data.mapping.model.FieldNamingStrategy;
|
import org.springframework.data.mapping.model.FieldNamingStrategy;
|
||||||
import org.springframework.data.mapping.model.PropertyNameFieldNamingStrategy;
|
import org.springframework.data.mapping.model.PropertyNameFieldNamingStrategy;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.util.ClassUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
@org.jspecify.annotations.NullMarked
|
@org.springframework.lang.NonNullApi
|
||||||
|
@org.springframework.lang.NonNullFields
|
||||||
package org.springframework.data.elasticsearch.config;
|
package org.springframework.data.elasticsearch.config;
|
||||||
|
@ -24,7 +24,6 @@ import java.util.Objects;
|
|||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.beans.BeansException;
|
import org.springframework.beans.BeansException;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.ApplicationContextAware;
|
import org.springframework.context.ApplicationContextAware;
|
||||||
@ -58,6 +57,7 @@ import org.springframework.data.elasticsearch.support.VersionInfo;
|
|||||||
import org.springframework.data.mapping.callback.EntityCallbacks;
|
import org.springframework.data.mapping.callback.EntityCallbacks;
|
||||||
import org.springframework.data.mapping.context.MappingContext;
|
import org.springframework.data.mapping.context.MappingContext;
|
||||||
import org.springframework.data.util.Streamable;
|
import org.springframework.data.util.Streamable;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
@ -298,6 +298,12 @@ public abstract class AbstractElasticsearchTemplate implements ElasticsearchOper
|
|||||||
return this.delete(id, getIndexCoordinatesFor(entityType));
|
return this.delete(id, getIndexCoordinatesFor(entityType));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Deprecated
|
||||||
|
public ByQueryResponse delete(Query query, Class<?> clazz) {
|
||||||
|
return delete(query, clazz, getIndexCoordinatesFor(clazz));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String delete(Object entity) {
|
public String delete(Object entity) {
|
||||||
return delete(entity, getIndexCoordinatesFor(entity.getClass()));
|
return delete(entity, getIndexCoordinatesFor(entity.getClass()));
|
||||||
|
@ -26,7 +26,6 @@ import java.util.List;
|
|||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.reactivestreams.Subscriber;
|
import org.reactivestreams.Subscriber;
|
||||||
import org.reactivestreams.Subscription;
|
import org.reactivestreams.Subscription;
|
||||||
import org.springframework.beans.BeansException;
|
import org.springframework.beans.BeansException;
|
||||||
@ -57,6 +56,7 @@ import org.springframework.data.elasticsearch.core.script.Script;
|
|||||||
import org.springframework.data.elasticsearch.core.suggest.response.Suggest;
|
import org.springframework.data.elasticsearch.core.suggest.response.Suggest;
|
||||||
import org.springframework.data.elasticsearch.support.VersionInfo;
|
import org.springframework.data.elasticsearch.support.VersionInfo;
|
||||||
import org.springframework.data.mapping.callback.ReactiveEntityCallbacks;
|
import org.springframework.data.mapping.callback.ReactiveEntityCallbacks;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -233,7 +233,6 @@ abstract public class AbstractReactiveElasticsearchTemplate
|
|||||||
.subscribe(new Subscriber<>() {
|
.subscribe(new Subscriber<>() {
|
||||||
@Nullable private Subscription subscription = null;
|
@Nullable private Subscription subscription = null;
|
||||||
private final AtomicBoolean upstreamComplete = new AtomicBoolean(false);
|
private final AtomicBoolean upstreamComplete = new AtomicBoolean(false);
|
||||||
private final AtomicBoolean onNextHasBeenCalled = new AtomicBoolean(false);
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSubscribe(Subscription subscription) {
|
public void onSubscribe(Subscription subscription) {
|
||||||
@ -243,7 +242,6 @@ abstract public class AbstractReactiveElasticsearchTemplate
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onNext(List<T> entityList) {
|
public void onNext(List<T> entityList) {
|
||||||
onNextHasBeenCalled.set(true);
|
|
||||||
saveAll(entityList, index)
|
saveAll(entityList, index)
|
||||||
.map(sink::tryEmitNext)
|
.map(sink::tryEmitNext)
|
||||||
.doOnComplete(() -> {
|
.doOnComplete(() -> {
|
||||||
@ -269,10 +267,6 @@ abstract public class AbstractReactiveElasticsearchTemplate
|
|||||||
@Override
|
@Override
|
||||||
public void onComplete() {
|
public void onComplete() {
|
||||||
upstreamComplete.set(true);
|
upstreamComplete.set(true);
|
||||||
if (!onNextHasBeenCalled.get()) {
|
|
||||||
// this happens when an empty flux is saved
|
|
||||||
sink.tryEmitComplete();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return sink.asFlux();
|
return sink.asFlux();
|
||||||
@ -414,6 +408,12 @@ abstract public class AbstractReactiveElasticsearchTemplate
|
|||||||
|
|
||||||
abstract protected Mono<String> doDeleteById(String id, @Nullable String routing, IndexCoordinates index);
|
abstract protected Mono<String> doDeleteById(String id, @Nullable String routing, IndexCoordinates index);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Deprecated
|
||||||
|
public Mono<ByQueryResponse> delete(Query query, Class<?> entityType) {
|
||||||
|
return delete(query, entityType, getIndexCoordinatesFor(entityType));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<ByQueryResponse> delete(DeleteQuery query, Class<?> entityType) {
|
public Mono<ByQueryResponse> delete(DeleteQuery query, Class<?> entityType) {
|
||||||
return delete(query, entityType, getIndexCoordinatesFor(entityType));
|
return delete(query, entityType, getIndexCoordinatesFor(entityType));
|
||||||
|
@ -18,7 +18,6 @@ package org.springframework.data.elasticsearch.core;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||||
import org.springframework.data.elasticsearch.core.query.BulkOptions;
|
import org.springframework.data.elasticsearch.core.query.BulkOptions;
|
||||||
import org.springframework.data.elasticsearch.core.query.ByQueryResponse;
|
import org.springframework.data.elasticsearch.core.query.ByQueryResponse;
|
||||||
@ -29,6 +28,7 @@ import org.springframework.data.elasticsearch.core.query.UpdateQuery;
|
|||||||
import org.springframework.data.elasticsearch.core.query.UpdateResponse;
|
import org.springframework.data.elasticsearch.core.query.UpdateResponse;
|
||||||
import org.springframework.data.elasticsearch.core.reindex.ReindexRequest;
|
import org.springframework.data.elasticsearch.core.reindex.ReindexRequest;
|
||||||
import org.springframework.data.elasticsearch.core.reindex.ReindexResponse;
|
import org.springframework.data.elasticsearch.core.reindex.ReindexResponse;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The operations for the
|
* The operations for the
|
||||||
@ -272,6 +272,19 @@ public interface DocumentOperations {
|
|||||||
*/
|
*/
|
||||||
String delete(Object entity, IndexCoordinates index);
|
String delete(Object entity, IndexCoordinates index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete all records matching the query.
|
||||||
|
*
|
||||||
|
* @param query query defining the objects
|
||||||
|
* @param clazz The entity class, must be annotated with
|
||||||
|
* {@link org.springframework.data.elasticsearch.annotations.Document}
|
||||||
|
* @return response with detailed information
|
||||||
|
* @since 4.1
|
||||||
|
* @deprecated since 5.3.0, use {@link #delete(DeleteQuery, Class)}
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
ByQueryResponse delete(Query query, Class<?> clazz);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete all records matching the query.
|
* Delete all records matching the query.
|
||||||
*
|
*
|
||||||
@ -283,6 +296,19 @@ public interface DocumentOperations {
|
|||||||
*/
|
*/
|
||||||
ByQueryResponse delete(DeleteQuery query, Class<?> clazz);
|
ByQueryResponse delete(DeleteQuery query, Class<?> clazz);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete all records matching the query.
|
||||||
|
*
|
||||||
|
* @param query query defining the objects
|
||||||
|
* @param clazz The entity class, must be annotated with
|
||||||
|
* {@link org.springframework.data.elasticsearch.annotations.Document}
|
||||||
|
* @param index the index from which to delete
|
||||||
|
* @return response with detailed information
|
||||||
|
* @deprecated since 5.3.0, use {@link #delete(DeleteQuery, Class, IndexCoordinates)}
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
ByQueryResponse delete(Query query, Class<?> clazz, IndexCoordinates index);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete all records matching the query.
|
* Delete all records matching the query.
|
||||||
*
|
*
|
||||||
|
@ -15,13 +15,12 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.elasticsearch.core;
|
package org.springframework.data.elasticsearch.core;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.data.elasticsearch.core.cluster.ClusterOperations;
|
import org.springframework.data.elasticsearch.core.cluster.ClusterOperations;
|
||||||
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
||||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||||
import org.springframework.data.elasticsearch.core.routing.RoutingResolver;
|
import org.springframework.data.elasticsearch.core.routing.RoutingResolver;
|
||||||
import org.springframework.data.elasticsearch.core.script.ScriptOperations;
|
import org.springframework.data.elasticsearch.core.script.ScriptOperations;
|
||||||
import org.springframework.data.elasticsearch.core.sql.SqlOperations;
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ElasticsearchOperations. Since 4.0 this interface only contains common helper functions, the other methods have been
|
* ElasticsearchOperations. Since 4.0 this interface only contains common helper functions, the other methods have been
|
||||||
@ -36,7 +35,7 @@ import org.springframework.data.elasticsearch.core.sql.SqlOperations;
|
|||||||
* @author Dmitriy Yakovlev
|
* @author Dmitriy Yakovlev
|
||||||
* @author Peter-Josef Meisch
|
* @author Peter-Josef Meisch
|
||||||
*/
|
*/
|
||||||
public interface ElasticsearchOperations extends DocumentOperations, SearchOperations, ScriptOperations, SqlOperations {
|
public interface ElasticsearchOperations extends DocumentOperations, SearchOperations, ScriptOperations {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get an {@link IndexOperations} that is bound to the given class
|
* get an {@link IndexOperations} that is bound to the given class
|
||||||
|
@ -17,7 +17,6 @@ package org.springframework.data.elasticsearch.core;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.core.convert.ConversionService;
|
import org.springframework.core.convert.ConversionService;
|
||||||
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
||||||
import org.springframework.data.elasticsearch.core.join.JoinField;
|
import org.springframework.data.elasticsearch.core.join.JoinField;
|
||||||
@ -30,6 +29,7 @@ import org.springframework.data.mapping.IdentifierAccessor;
|
|||||||
import org.springframework.data.mapping.PersistentPropertyAccessor;
|
import org.springframework.data.mapping.PersistentPropertyAccessor;
|
||||||
import org.springframework.data.mapping.context.MappingContext;
|
import org.springframework.data.mapping.context.MappingContext;
|
||||||
import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
|
import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -18,10 +18,10 @@ package org.springframework.data.elasticsearch.core;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.data.elasticsearch.core.document.Document;
|
import org.springframework.data.elasticsearch.core.document.Document;
|
||||||
import org.springframework.data.elasticsearch.core.index.AliasData;
|
import org.springframework.data.elasticsearch.core.index.AliasData;
|
||||||
import org.springframework.data.elasticsearch.core.index.Settings;
|
import org.springframework.data.elasticsearch.core.index.Settings;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Immutable object that holds information(name, settings, mappings, aliases) about an Index
|
* Immutable object that holds information(name, settings, mappings, aliases) about an Index
|
||||||
|
@ -19,10 +19,10 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.data.elasticsearch.core.document.Document;
|
import org.springframework.data.elasticsearch.core.document.Document;
|
||||||
import org.springframework.data.elasticsearch.core.index.*;
|
import org.springframework.data.elasticsearch.core.index.*;
|
||||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The operations for the
|
* The operations for the
|
||||||
|
@ -22,10 +22,10 @@ import java.util.Map;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.data.elasticsearch.core.document.Document;
|
import org.springframework.data.elasticsearch.core.document.Document;
|
||||||
import org.springframework.data.elasticsearch.core.index.*;
|
import org.springframework.data.elasticsearch.core.index.*;
|
||||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.elasticsearch.core;
|
package org.springframework.data.elasticsearch.core;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Value class capturing information about a newly indexed document in Elasticsearch.
|
* Value class capturing information about a newly indexed document in Elasticsearch.
|
||||||
|
@ -15,8 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.elasticsearch.core;
|
package org.springframework.data.elasticsearch.core;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.data.elasticsearch.ElasticsearchErrorCause;
|
import org.springframework.data.elasticsearch.ElasticsearchErrorCause;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Response object for items returned from multiget requests, encapsulating the returned data and potential error
|
* Response object for items returned from multiget requests, encapsulating the returned data and potential error
|
||||||
|
@ -326,6 +326,17 @@ public interface ReactiveDocumentOperations {
|
|||||||
*/
|
*/
|
||||||
Mono<String> delete(String id, Class<?> entityType);
|
Mono<String> delete(String id, Class<?> entityType);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete the documents matching the given {@link Query} extracting index from entity metadata.
|
||||||
|
*
|
||||||
|
* @param query must not be {@literal null}.
|
||||||
|
* @param entityType must not be {@literal null}.
|
||||||
|
* @return a {@link Mono} emitting the number of the removed documents.
|
||||||
|
* @deprecated since 5.3.0, use {@link #delete(DeleteQuery, Class)}
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
Mono<ByQueryResponse> delete(Query query, Class<?> entityType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete the documents matching the given {@link Query} extracting index from entity metadata.
|
* Delete the documents matching the given {@link Query} extracting index from entity metadata.
|
||||||
*
|
*
|
||||||
@ -336,6 +347,18 @@ public interface ReactiveDocumentOperations {
|
|||||||
*/
|
*/
|
||||||
Mono<ByQueryResponse> delete(DeleteQuery query, Class<?> entityType);
|
Mono<ByQueryResponse> delete(DeleteQuery query, Class<?> entityType);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete the documents matching the given {@link Query} extracting index from entity metadata.
|
||||||
|
*
|
||||||
|
* @param query must not be {@literal null}.
|
||||||
|
* @param entityType must not be {@literal null}.
|
||||||
|
* @param index the target index, must not be {@literal null}
|
||||||
|
* @return a {@link Mono} emitting the number of the removed documents.
|
||||||
|
* @deprecated since 5.3.0, use {@link #delete(DeleteQuery, Class, IndexCoordinates)}
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
Mono<ByQueryResponse> delete(Query query, Class<?> entityType, IndexCoordinates index);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete the documents matching the given {@link Query} extracting index from entity metadata.
|
* Delete the documents matching the given {@link Query} extracting index from entity metadata.
|
||||||
*
|
*
|
||||||
|
@ -15,14 +15,13 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.elasticsearch.core;
|
package org.springframework.data.elasticsearch.core;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.data.elasticsearch.core.cluster.ReactiveClusterOperations;
|
import org.springframework.data.elasticsearch.core.cluster.ReactiveClusterOperations;
|
||||||
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
||||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
|
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
|
||||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||||
import org.springframework.data.elasticsearch.core.routing.RoutingResolver;
|
import org.springframework.data.elasticsearch.core.routing.RoutingResolver;
|
||||||
import org.springframework.data.elasticsearch.core.script.ReactiveScriptOperations;
|
import org.springframework.data.elasticsearch.core.script.ReactiveScriptOperations;
|
||||||
import org.springframework.data.elasticsearch.core.sql.ReactiveSqlOperations;
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface that specifies a basic set of Elasticsearch operations executed in a reactive way.
|
* Interface that specifies a basic set of Elasticsearch operations executed in a reactive way.
|
||||||
@ -32,7 +31,7 @@ import org.springframework.data.elasticsearch.core.sql.ReactiveSqlOperations;
|
|||||||
* @since 3.2
|
* @since 3.2
|
||||||
*/
|
*/
|
||||||
public interface ReactiveElasticsearchOperations
|
public interface ReactiveElasticsearchOperations
|
||||||
extends ReactiveDocumentOperations, ReactiveSearchOperations, ReactiveScriptOperations, ReactiveSqlOperations {
|
extends ReactiveDocumentOperations, ReactiveSearchOperations, ReactiveScriptOperations {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the {@link ElasticsearchConverter} used.
|
* Get the {@link ElasticsearchConverter} used.
|
||||||
|
@ -17,17 +17,14 @@ package org.springframework.data.elasticsearch.core;
|
|||||||
|
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.data.elasticsearch.core.suggest.response.Suggest;
|
import org.springframework.data.elasticsearch.core.suggest.response.Suggest;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encapsulates a Flux of {@link SearchHit}s with additional information from the search.
|
* Encapsulates a Flux of {@link SearchHit}s with additional information from the search.
|
||||||
*
|
*
|
||||||
* @param <T> the result data class.
|
* @param <T> the result data class.
|
||||||
* @author Peter-Josef Meisch
|
* @author Peter-Josef Meisch
|
||||||
* @author Mohamed El Harrougui
|
|
||||||
* @since 4.4
|
* @since 4.4
|
||||||
*/
|
*/
|
||||||
public interface ReactiveSearchHits<T> {
|
public interface ReactiveSearchHits<T> {
|
||||||
@ -40,11 +37,6 @@ public interface ReactiveSearchHits<T> {
|
|||||||
|
|
||||||
float getMaxScore();
|
float getMaxScore();
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the execution duration it took to complete the request
|
|
||||||
*/
|
|
||||||
Duration getExecutionDuration();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the {@link SearchHit}s from the search result.
|
* @return the {@link SearchHit}s from the search result.
|
||||||
*/
|
*/
|
||||||
|
@ -17,14 +17,11 @@ package org.springframework.data.elasticsearch.core;
|
|||||||
|
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.data.elasticsearch.core.suggest.response.Suggest;
|
import org.springframework.data.elasticsearch.core.suggest.response.Suggest;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Peter-Josef Meisch
|
* @author Peter-Josef Meisch
|
||||||
* @author Mohamed El Harrougui
|
|
||||||
* @since 4.4
|
* @since 4.4
|
||||||
*/
|
*/
|
||||||
public class ReactiveSearchHitsImpl<T> implements ReactiveSearchHits<T> {
|
public class ReactiveSearchHitsImpl<T> implements ReactiveSearchHits<T> {
|
||||||
@ -61,11 +58,6 @@ public class ReactiveSearchHitsImpl<T> implements ReactiveSearchHits<T> {
|
|||||||
return delegate.getMaxScore();
|
return delegate.getMaxScore();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Duration getExecutionDuration() {
|
|
||||||
return delegate.getExecutionDuration();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasSearchHits() {
|
public boolean hasSearchHits() {
|
||||||
return delegate.hasSearchHits();
|
return delegate.hasSearchHits();
|
||||||
|
@ -23,9 +23,9 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.data.elasticsearch.core.document.Explanation;
|
import org.springframework.data.elasticsearch.core.document.Explanation;
|
||||||
import org.springframework.data.elasticsearch.core.document.NestedMetaData;
|
import org.springframework.data.elasticsearch.core.document.NestedMetaData;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -48,12 +48,12 @@ public class SearchHit<T> {
|
|||||||
@Nullable private final NestedMetaData nestedMetaData;
|
@Nullable private final NestedMetaData nestedMetaData;
|
||||||
@Nullable private final String routing;
|
@Nullable private final String routing;
|
||||||
@Nullable private final Explanation explanation;
|
@Nullable private final Explanation explanation;
|
||||||
private final Map<String, Double> matchedQueries = new LinkedHashMap<>();
|
private final List<String> matchedQueries = new ArrayList<>();
|
||||||
|
|
||||||
public SearchHit(@Nullable String index, @Nullable String id, @Nullable String routing, float score,
|
public SearchHit(@Nullable String index, @Nullable String id, @Nullable String routing, float score,
|
||||||
@Nullable Object[] sortValues, @Nullable Map<String, List<String>> highlightFields,
|
@Nullable Object[] sortValues, @Nullable Map<String, List<String>> highlightFields,
|
||||||
@Nullable Map<String, SearchHits<?>> innerHits, @Nullable NestedMetaData nestedMetaData,
|
@Nullable Map<String, SearchHits<?>> innerHits, @Nullable NestedMetaData nestedMetaData,
|
||||||
@Nullable Explanation explanation, @Nullable Map<String, Double> matchedQueries, T content) {
|
@Nullable Explanation explanation, @Nullable List<String> matchedQueries, T content) {
|
||||||
this.index = index;
|
this.index = index;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.routing = routing;
|
this.routing = routing;
|
||||||
@ -73,7 +73,7 @@ public class SearchHit<T> {
|
|||||||
this.content = content;
|
this.content = content;
|
||||||
|
|
||||||
if (matchedQueries != null) {
|
if (matchedQueries != null) {
|
||||||
this.matchedQueries.putAll(matchedQueries);
|
this.matchedQueries.addAll(matchedQueries);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,7 +194,7 @@ public class SearchHit<T> {
|
|||||||
* @return the matched queries for this SearchHit.
|
* @return the matched queries for this SearchHit.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public Map<String, Double> getMatchedQueries() {
|
public List<String> getMatchedQueries() {
|
||||||
return matchedQueries;
|
return matchedQueries;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.elasticsearch.core;
|
package org.springframework.data.elasticsearch.core;
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@ -23,7 +22,6 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.data.elasticsearch.UncategorizedElasticsearchException;
|
import org.springframework.data.elasticsearch.UncategorizedElasticsearchException;
|
||||||
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
||||||
import org.springframework.data.elasticsearch.core.document.Document;
|
import org.springframework.data.elasticsearch.core.document.Document;
|
||||||
@ -35,6 +33,7 @@ import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersiste
|
|||||||
import org.springframework.data.elasticsearch.core.suggest.response.CompletionSuggestion;
|
import org.springframework.data.elasticsearch.core.suggest.response.CompletionSuggestion;
|
||||||
import org.springframework.data.elasticsearch.core.suggest.response.Suggest;
|
import org.springframework.data.elasticsearch.core.suggest.response.Suggest;
|
||||||
import org.springframework.data.mapping.context.MappingContext;
|
import org.springframework.data.mapping.context.MappingContext;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -48,7 +47,6 @@ import org.springframework.util.Assert;
|
|||||||
* @author Sascha Woo
|
* @author Sascha Woo
|
||||||
* @author Jakob Hoeper
|
* @author Jakob Hoeper
|
||||||
* @author Haibo Liu
|
* @author Haibo Liu
|
||||||
* @author Mohamed El Harrougui
|
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
public class SearchHitMapping<T> {
|
public class SearchHitMapping<T> {
|
||||||
@ -89,7 +87,6 @@ public class SearchHitMapping<T> {
|
|||||||
long totalHits = searchDocumentResponse.getTotalHits();
|
long totalHits = searchDocumentResponse.getTotalHits();
|
||||||
SearchShardStatistics shardStatistics = searchDocumentResponse.getSearchShardStatistics();
|
SearchShardStatistics shardStatistics = searchDocumentResponse.getSearchShardStatistics();
|
||||||
float maxScore = searchDocumentResponse.getMaxScore();
|
float maxScore = searchDocumentResponse.getMaxScore();
|
||||||
Duration executionDuration = searchDocumentResponse.getExecutionDuration();
|
|
||||||
String scrollId = searchDocumentResponse.getScrollId();
|
String scrollId = searchDocumentResponse.getScrollId();
|
||||||
String pointInTimeId = searchDocumentResponse.getPointInTimeId();
|
String pointInTimeId = searchDocumentResponse.getPointInTimeId();
|
||||||
|
|
||||||
@ -107,8 +104,8 @@ public class SearchHitMapping<T> {
|
|||||||
Suggest suggest = searchDocumentResponse.getSuggest();
|
Suggest suggest = searchDocumentResponse.getSuggest();
|
||||||
mapHitsInCompletionSuggestion(suggest);
|
mapHitsInCompletionSuggestion(suggest);
|
||||||
|
|
||||||
return new SearchHitsImpl<>(totalHits, totalHitsRelation, maxScore, executionDuration, scrollId, pointInTimeId,
|
return new SearchHitsImpl<>(totalHits, totalHitsRelation, maxScore, scrollId, pointInTimeId, searchHits,
|
||||||
searchHits, aggregations, suggest, shardStatistics);
|
aggregations, suggest, shardStatistics);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@ -241,7 +238,6 @@ public class SearchHitMapping<T> {
|
|||||||
return new SearchHitsImpl<>(searchHits.getTotalHits(),
|
return new SearchHitsImpl<>(searchHits.getTotalHits(),
|
||||||
searchHits.getTotalHitsRelation(),
|
searchHits.getTotalHitsRelation(),
|
||||||
searchHits.getMaxScore(),
|
searchHits.getMaxScore(),
|
||||||
searchHits.getExecutionDuration(),
|
|
||||||
scrollId,
|
scrollId,
|
||||||
searchHits.getPointInTimeId(),
|
searchHits.getPointInTimeId(),
|
||||||
convertedSearchHits,
|
convertedSearchHits,
|
||||||
|
@ -21,11 +21,11 @@ import java.util.List;
|
|||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.data.domain.PageImpl;
|
import org.springframework.data.domain.PageImpl;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.data.util.CloseableIterator;
|
import org.springframework.data.util.CloseableIterator;
|
||||||
import org.springframework.data.util.ReactiveWrappers;
|
import org.springframework.data.util.ReactiveWrappers;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility class with helper methods for working with {@link SearchHit}.
|
* Utility class with helper methods for working with {@link SearchHit}.
|
||||||
|
@ -15,13 +15,12 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.elasticsearch.core;
|
package org.springframework.data.elasticsearch.core;
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.data.elasticsearch.core.suggest.response.Suggest;
|
import org.springframework.data.elasticsearch.core.suggest.response.Suggest;
|
||||||
import org.springframework.data.util.Streamable;
|
import org.springframework.data.util.Streamable;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encapsulates a list of {@link SearchHit}s with additional information from the search.
|
* Encapsulates a list of {@link SearchHit}s with additional information from the search.
|
||||||
@ -29,7 +28,6 @@ import org.springframework.data.util.Streamable;
|
|||||||
* @param <T> the result data class.
|
* @param <T> the result data class.
|
||||||
* @author Sascha Woo
|
* @author Sascha Woo
|
||||||
* @author Haibo Liu
|
* @author Haibo Liu
|
||||||
* @author Mohamed El Harrougui
|
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
public interface SearchHits<T> extends Streamable<SearchHit<T>> {
|
public interface SearchHits<T> extends Streamable<SearchHit<T>> {
|
||||||
@ -45,11 +43,6 @@ public interface SearchHits<T> extends Streamable<SearchHit<T>> {
|
|||||||
*/
|
*/
|
||||||
float getMaxScore();
|
float getMaxScore();
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the execution duration it took to complete the request
|
|
||||||
*/
|
|
||||||
Duration getExecutionDuration();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param index position in List.
|
* @param index position in List.
|
||||||
* @return the {@link SearchHit} at position {index}
|
* @return the {@link SearchHit} at position {index}
|
||||||
|
@ -15,13 +15,12 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.elasticsearch.core;
|
package org.springframework.data.elasticsearch.core;
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.springframework.data.elasticsearch.core.suggest.response.Suggest;
|
import org.springframework.data.elasticsearch.core.suggest.response.Suggest;
|
||||||
import org.springframework.data.util.Lazy;
|
import org.springframework.data.util.Lazy;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -31,7 +30,6 @@ import org.springframework.util.Assert;
|
|||||||
* @author Peter-Josef Meisch
|
* @author Peter-Josef Meisch
|
||||||
* @author Sascha Woo
|
* @author Sascha Woo
|
||||||
* @author Haibo Liu
|
* @author Haibo Liu
|
||||||
* @author Mohamed El Harrougui
|
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
public class SearchHitsImpl<T> implements SearchScrollHits<T> {
|
public class SearchHitsImpl<T> implements SearchScrollHits<T> {
|
||||||
@ -39,7 +37,6 @@ public class SearchHitsImpl<T> implements SearchScrollHits<T> {
|
|||||||
private final long totalHits;
|
private final long totalHits;
|
||||||
private final TotalHitsRelation totalHitsRelation;
|
private final TotalHitsRelation totalHitsRelation;
|
||||||
private final float maxScore;
|
private final float maxScore;
|
||||||
private final Duration executionDuration;
|
|
||||||
@Nullable private final String scrollId;
|
@Nullable private final String scrollId;
|
||||||
private final List<? extends SearchHit<T>> searchHits;
|
private final List<? extends SearchHit<T>> searchHits;
|
||||||
private final Lazy<List<SearchHit<T>>> unmodifiableSearchHits;
|
private final Lazy<List<SearchHit<T>>> unmodifiableSearchHits;
|
||||||
@ -52,13 +49,12 @@ public class SearchHitsImpl<T> implements SearchScrollHits<T> {
|
|||||||
* @param totalHits the number of total hits for the search
|
* @param totalHits the number of total hits for the search
|
||||||
* @param totalHitsRelation the relation {@see TotalHitsRelation}, must not be {@literal null}
|
* @param totalHitsRelation the relation {@see TotalHitsRelation}, must not be {@literal null}
|
||||||
* @param maxScore the maximum score
|
* @param maxScore the maximum score
|
||||||
* @param executionDuration the execution duration it took to complete the request
|
|
||||||
* @param scrollId the scroll id if available
|
* @param scrollId the scroll id if available
|
||||||
* @param searchHits must not be {@literal null}
|
* @param searchHits must not be {@literal null}
|
||||||
* @param aggregations the aggregations if available
|
* @param aggregations the aggregations if available
|
||||||
*/
|
*/
|
||||||
public SearchHitsImpl(long totalHits, TotalHitsRelation totalHitsRelation, float maxScore, Duration executionDuration,
|
public SearchHitsImpl(long totalHits, TotalHitsRelation totalHitsRelation, float maxScore, @Nullable String scrollId,
|
||||||
@Nullable String scrollId, @Nullable String pointInTimeId, List<? extends SearchHit<T>> searchHits,
|
@Nullable String pointInTimeId, List<? extends SearchHit<T>> searchHits,
|
||||||
@Nullable AggregationsContainer<?> aggregations, @Nullable Suggest suggest,
|
@Nullable AggregationsContainer<?> aggregations, @Nullable Suggest suggest,
|
||||||
@Nullable SearchShardStatistics searchShardStatistics) {
|
@Nullable SearchShardStatistics searchShardStatistics) {
|
||||||
|
|
||||||
@ -67,7 +63,6 @@ public class SearchHitsImpl<T> implements SearchScrollHits<T> {
|
|||||||
this.totalHits = totalHits;
|
this.totalHits = totalHits;
|
||||||
this.totalHitsRelation = totalHitsRelation;
|
this.totalHitsRelation = totalHitsRelation;
|
||||||
this.maxScore = maxScore;
|
this.maxScore = maxScore;
|
||||||
this.executionDuration = executionDuration;
|
|
||||||
this.scrollId = scrollId;
|
this.scrollId = scrollId;
|
||||||
this.pointInTimeId = pointInTimeId;
|
this.pointInTimeId = pointInTimeId;
|
||||||
this.searchHits = searchHits;
|
this.searchHits = searchHits;
|
||||||
@ -93,11 +88,6 @@ public class SearchHitsImpl<T> implements SearchScrollHits<T> {
|
|||||||
return maxScore;
|
return maxScore;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Duration getExecutionDuration() {
|
|
||||||
return executionDuration;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public String getScrollId() {
|
public String getScrollId() {
|
||||||
@ -143,7 +133,6 @@ public class SearchHitsImpl<T> implements SearchScrollHits<T> {
|
|||||||
"totalHits=" + totalHits + //
|
"totalHits=" + totalHits + //
|
||||||
", totalHitsRelation=" + totalHitsRelation + //
|
", totalHitsRelation=" + totalHitsRelation + //
|
||||||
", maxScore=" + maxScore + //
|
", maxScore=" + maxScore + //
|
||||||
", executionDuration=" + executionDuration + //
|
|
||||||
", scrollId='" + scrollId + '\'' + //
|
", scrollId='" + scrollId + '\'' + //
|
||||||
", pointInTimeId='" + pointInTimeId + '\'' + //
|
", pointInTimeId='" + pointInTimeId + '\'' + //
|
||||||
", searchHits={" + searchHits.size() + " elements}" + //
|
", searchHits={" + searchHits.size() + " elements}" + //
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user