diff --git a/.gitignore b/.gitignore
index ea0475e148..449f58ea44 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,7 +30,7 @@ target
build/
node_modules
node
-package.json
package-lock.json
-.mvn/.gradle-enterprise
+.mvn/.develocity
+/src/test/resources/testcontainers-local.properties
diff --git a/.mvn/extensions.xml b/.mvn/extensions.xml
index ebd7610255..e0857eaa25 100644
--- a/.mvn/extensions.xml
+++ b/.mvn/extensions.xml
@@ -1,13 +1,8 @@
- com.gradle
- gradle-enterprise-maven-extension
- 1.19.2
-
-
- com.gradle
- common-custom-user-data-maven-extension
- 1.12.4
+ io.spring.develocity.conventions
+ develocity-conventions-maven-extension
+ 0.0.22
diff --git a/.mvn/gradle-enterprise.xml b/.mvn/gradle-enterprise.xml
deleted file mode 100644
index f88a885d06..0000000000
--- a/.mvn/gradle-enterprise.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
- https://ge.spring.io
-
-
- false
- true
- true
-
- #{{'0.0.0.0'}}
-
-
-
-
- true
-
-
-
-
- ${env.GRADLE_ENTERPRISE_CACHE_USERNAME}
- ${env.GRADLE_ENTERPRISE_CACHE_PASSWORD}
-
-
- true
- #{env['GRADLE_ENTERPRISE_CACHE_USERNAME'] != null and env['GRADLE_ENTERPRISE_CACHE_PASSWORD'] != null}
-
-
-
diff --git a/.mvn/jvm.config b/.mvn/jvm.config
new file mode 100644
index 0000000000..e27f6e8f5e
--- /dev/null
+++ b/.mvn/jvm.config
@@ -0,0 +1,14 @@
+--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
+--add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED
+--add-exports jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED
+--add-exports jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED
+--add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED
+--add-exports jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED
+--add-exports jdk.compiler/com.sun.tools.javac.tree=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.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
diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties
index 021cf949cc..e075a74d86 100644
--- a/.mvn/wrapper/maven-wrapper.properties
+++ b/.mvn/wrapper/maven-wrapper.properties
@@ -1,3 +1,3 @@
-#Wed Oct 04 16:58:13 PDT 2023
+#Thu Nov 07 09:47:28 CET 2024
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.5/apache-maven-3.9.5-bin.zip
+distributionUrl=https\://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip
diff --git a/Jenkinsfile b/Jenkinsfile
index 685270466c..1d2500ed1e 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -33,15 +33,16 @@ pipeline {
environment {
ARTIFACTORY = credentials("${p['artifactory.credentials']}")
- DEVELOCITY_CACHE = credentials("${p['develocity.cache.credentials']}")
DEVELOCITY_ACCESS_KEY = credentials("${p['develocity.access-key']}")
}
steps {
script {
- docker.image(p['docker.java.main.image']).inside(p['docker.java.inside.docker']) {
- sh 'PROFILE=none ci/verify.sh'
- sh "ci/clean.sh"
+ docker.withRegistry(p['docker.proxy.registry'], p['docker.proxy.credentials']) {
+ docker.image(p['docker.java.main.image']).inside(p['docker.java.inside.docker']) {
+ sh "PROFILE=none JENKINS_USER_NAME=${p['jenkins.user.name']} ci/verify.sh"
+ sh "JENKINS_USER_NAME=${p['jenkins.user.name']} ci/clean.sh"
+ }
}
}
}
@@ -63,14 +64,15 @@ pipeline {
options { timeout(time: 30, unit: 'MINUTES') }
environment {
ARTIFACTORY = credentials("${p['artifactory.credentials']}")
- DEVELOCITY_CACHE = credentials("${p['develocity.cache.credentials']}")
DEVELOCITY_ACCESS_KEY = credentials("${p['develocity.access-key']}")
}
steps {
script {
- docker.image(p['docker.java.next.image']).inside(p['docker.java.inside.docker']) {
- sh 'PROFILE=none ci/verify.sh'
- sh "ci/clean.sh"
+ docker.withRegistry(p['docker.proxy.registry'], p['docker.proxy.credentials']) {
+ docker.image(p['docker.java.next.image']).inside(p['docker.java.inside.docker']) {
+ sh "PROFILE=none JENKINS_USER_NAME=${p['jenkins.user.name']} ci/verify.sh"
+ sh "JENKINS_USER_NAME=${p['jenkins.user.name']} ci/clean.sh"
+ }
}
}
}
@@ -90,28 +92,26 @@ pipeline {
label 'data'
}
options { timeout(time: 20, unit: 'MINUTES') }
-
environment {
ARTIFACTORY = credentials("${p['artifactory.credentials']}")
- DEVELOCITY_CACHE = credentials("${p['develocity.cache.credentials']}")
DEVELOCITY_ACCESS_KEY = credentials("${p['develocity.access-key']}")
}
-
steps {
script {
- docker.image(p['docker.java.main.image']).inside(p['docker.java.inside.basic']) {
- sh 'MAVEN_OPTS="-Duser.name=spring-builds+jenkins -Duser.home=/tmp/jenkins-home" ' +
- 'DEVELOCITY_CACHE_USERNAME=${DEVELOCITY_CACHE_USR} ' +
- 'DEVELOCITY_CACHE_PASSWORD=${DEVELOCITY_CACHE_PSW} ' +
- 'GRADLE_ENTERPRISE_ACCESS_KEY=${DEVELOCITY_ACCESS_KEY} ' +
- './mvnw -s settings.xml -Pci,artifactory -Dmaven.repo.local=/tmp/jenkins-home/.m2/spring-data-elasticsearch-non-root ' +
- '-Dartifactory.server=https://repo.spring.io ' +
- "-Dartifactory.username=${ARTIFACTORY_USR} " +
- "-Dartifactory.password=${ARTIFACTORY_PSW} " +
- "-Dartifactory.staging-repository=libs-snapshot-local " +
- "-Dartifactory.build-name=spring-data-elasticsearch " +
- "-Dartifactory.build-number=${BUILD_NUMBER} " +
- '-Dmaven.test.skip=true clean deploy -U -B'
+ docker.withRegistry(p['docker.proxy.registry'], p['docker.proxy.credentials']) {
+ docker.image(p['docker.java.main.image']).inside(p['docker.java.inside.docker']) {
+ sh 'MAVEN_OPTS="-Duser.name=' + "${p['jenkins.user.name']}" + ' -Duser.home=/tmp/jenkins-home" ' +
+ "./mvnw -s settings.xml -Pci,artifactory " +
+ "-Ddevelocity.storage.directory=/tmp/jenkins-home/.develocity-root " +
+ "-Dartifactory.server=${p['artifactory.url']} " +
+ "-Dartifactory.username=${ARTIFACTORY_USR} " +
+ "-Dartifactory.password=${ARTIFACTORY_PSW} " +
+ "-Dartifactory.staging-repository=${p['artifactory.repository.snapshot']} " +
+ "-Dartifactory.build-name=spring-data-elasticsearch " +
+ "-Dartifactory.build-number=spring-data-elasticsearch-${BRANCH_NAME}-build-${BUILD_NUMBER} " +
+ "-Dmaven.repo.local=/tmp/jenkins-home/.m2/spring-data-elasticsearch " +
+ "-Dmaven.test.skip=true clean deploy -U -B"
+ }
}
}
}
diff --git a/README.adoc b/README.adoc
index d106098ef8..0242089d82 100644
--- a/README.adoc
+++ b/README.adoc
@@ -1,6 +1,4 @@
-image:https://spring.io/badges/spring-data-elasticsearch/ga.svg[Spring Data Elasticsearch,link=https://projects.spring.io/spring-data-elasticsearch#quick-start] image:https://spring.io/badges/spring-data-elasticsearch/snapshot.svg[Spring Data Elasticsearch,link=https://projects.spring.io/spring-data-elasticsearch#quick-start]
-
-= Spring Data for Elasticsearch image:https://jenkins.spring.io/buildStatus/icon?job=spring-data-elasticsearch%2Fmain&subject=Build[link=https://jenkins.spring.io/view/SpringData/job/spring-data-elasticsearch/] https://gitter.im/spring-projects/spring-data[image:https://badges.gitter.im/spring-projects/spring-data.svg[Gitter]] image:https://img.shields.io/badge/Revved%20up%20by-Gradle%20Enterprise-06A0CE?logo=Gradle&labelColor=02303A["Revved up by Gradle Enterprise", link="https://ge.spring.io/scans?search.rootProjectNames=Spring%20Data%20Elasticsearch"]
+= Spring Data for Elasticsearch image:https://jenkins.spring.io/buildStatus/icon?job=spring-data-elasticsearch%2Fmain&subject=Build[link=https://jenkins.spring.io/view/SpringData/job/spring-data-elasticsearch/] https://gitter.im/spring-projects/spring-data[image:https://badges.gitter.im/spring-projects/spring-data.svg[Gitter]] image:https://img.shields.io/badge/Revved%20up%20by-Develocity-06A0CE?logo=Gradle&labelColor=02303A["Revved up by Develocity", link="https://ge.spring.io/scans?search.rootProjectNames=Spring%20Data%20Elasticsearch"]
The primary goal of the https://projects.spring.io/spring-data[Spring Data] project is to make it easier to build Spring-powered applications that use new data access technologies such as non-relational databases, map-reduce frameworks, and cloud based data services.
@@ -64,7 +62,7 @@ public class MyService {
=== Using the RestClient
-Please check the [official documentation](https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/#elasticsearch.clients.configuration).
+Please check the https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/#elasticsearch.clients.configuration[official documentation].
=== Maven configuration
@@ -126,8 +124,7 @@ We’d love to help!
https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/[reference documentation], and https://docs.spring.io/spring-data/elasticsearch/docs/current/api/[Javadocs].
* Learn the Spring basics – Spring Data builds on Spring Framework, check the https://spring.io[spring.io] web-site for a wealth of reference documentation.
If you are just starting out with Spring, try one of the https://spring.io/guides[guides].
-* Ask a question - we monitor https://stackoverflow.com[stackoverflow.com] for questions tagged with https://stackoverflow.com/tags/spring-data[`spring-data-elasticsearch`].
-You can also chat with the community on https://gitter.im/spring-projects/spring-data[Gitter].
+* Ask a question or chat with the community on https://app.gitter.im/#/room/#spring-projects_spring-data:gitter.im[Gitter].
* Report bugs with Spring Data for Elasticsearch at https://github.com/spring-projects/spring-data-elasticsearch/issues[https://github.com/spring-projects/spring-data-elasticsearch/issues].
== Reporting Issues
@@ -171,7 +168,7 @@ Building the documentation builds also the project without running tests.
$ ./mvnw clean install -Pantora
----
-The generated documentation is available from `target/antora/site/index.html`.
+The generated documentation is available from `target/site/index.html`.
== Examples
diff --git a/ci/clean.sh b/ci/clean.sh
index 9f86e51ebf..ca174330ee 100755
--- a/ci/clean.sh
+++ b/ci/clean.sh
@@ -2,11 +2,7 @@
set -euo pipefail
-export DEVELOCITY_CACHE_USERNAME=${DEVELOCITY_CACHE_USR}
-export DEVELOCITY_CACHE_PASSWORD=${DEVELOCITY_CACHE_PSW}
+export JENKINS_USER=${JENKINS_USER_NAME}
-# The environment variable to configure access key is still GRADLE_ENTERPRISE_ACCESS_KEY
-export GRADLE_ENTERPRISE_ACCESS_KEY=${DEVELOCITY_ACCESS_KEY}
-
-MAVEN_OPTS="-Duser.name=spring-builds+jenkins -Duser.home=/tmp/jenkins-home" \
- ./mvnw -s settings.xml clean -Dmaven.repo.local=/tmp/jenkins-home/.m2/spring-data-elasticsearch
+MAVEN_OPTS="-Duser.name=${JENKINS_USER} -Duser.home=/tmp/jenkins-home" \
+ ./mvnw -s settings.xml clean -Dscan=false -Dmaven.repo.local=/tmp/jenkins-home/.m2/spring-data-elasticsearch -Ddevelocity.storage.directory=/tmp/jenkins-home/.develocity-root
diff --git a/ci/pipeline.properties b/ci/pipeline.properties
index d65c9db587..cde4a8e881 100644
--- a/ci/pipeline.properties
+++ b/ci/pipeline.properties
@@ -1,22 +1,19 @@
# Java versions
-java.main.tag=17.0.8_7-jdk-focal
-java.next.tag=21_35-jdk-jammy
+java.main.tag=24.0.1_9-jdk-noble
+java.next.tag=24.0.1_9-jdk-noble
# Docker container images - standard
-docker.java.main.image=harbor-repo.vmware.com/dockerhub-proxy-cache/library/eclipse-temurin:${java.main.tag}
-docker.java.next.image=harbor-repo.vmware.com/dockerhub-proxy-cache/library/eclipse-temurin:${java.next.tag}
+docker.java.main.image=library/eclipse-temurin:${java.main.tag}
+docker.java.next.image=library/eclipse-temurin:${java.next.tag}
# Supported versions of MongoDB
-docker.mongodb.4.4.version=4.4.25
-docker.mongodb.5.0.version=5.0.21
-docker.mongodb.6.0.version=6.0.10
-docker.mongodb.7.0.version=7.0.2
+docker.mongodb.6.0.version=6.0.23
+docker.mongodb.7.0.version=7.0.20
+docker.mongodb.8.0.version=8.0.9
# Supported versions of Redis
docker.redis.6.version=6.2.13
-
-# Supported versions of Cassandra
-docker.cassandra.3.version=3.11.16
+docker.redis.7.version=7.2.4
# Docker environment settings
docker.java.inside.basic=-v $HOME:/tmp/jenkins-home
@@ -25,6 +22,10 @@ docker.java.inside.docker=-u root -v /var/run/docker.sock:/var/run/docker.sock -
# Credentials
docker.registry=
docker.credentials=hub.docker.com-springbuildmaster
+docker.proxy.registry=https://docker-hub.usw1.packages.broadcom.com
+docker.proxy.credentials=usw1_packages_broadcom_com-jenkins-token
artifactory.credentials=02bd1690-b54f-4c9f-819d-a77cb7a9822c
-develocity.cache.credentials=gradle_enterprise_cache_user
+artifactory.url=https://repo.spring.io
+artifactory.repository.snapshot=libs-snapshot-local
develocity.access-key=gradle_enterprise_secret_access_key
+jenkins.user.name=spring-builds+jenkins
diff --git a/ci/verify.sh b/ci/verify.sh
index 82734212ba..46afc80280 100755
--- a/ci/verify.sh
+++ b/ci/verify.sh
@@ -3,14 +3,8 @@
set -euo pipefail
mkdir -p /tmp/jenkins-home/.m2/spring-data-elasticsearch
-chown -R 1001:1001 .
+export JENKINS_USER=${JENKINS_USER_NAME}
-export DEVELOCITY_CACHE_USERNAME=${DEVELOCITY_CACHE_USR}
-export DEVELOCITY_CACHE_PASSWORD=${DEVELOCITY_CACHE_PSW}
-
-# The environment variable to configure access key is still GRADLE_ENTERPRISE_ACCESS_KEY
-export GRADLE_ENTERPRISE_ACCESS_KEY=${DEVELOCITY_ACCESS_KEY}
-
-MAVEN_OPTS="-Duser.name=spring-builds+jenkins -Duser.home=/tmp/jenkins-home" \
+MAVEN_OPTS="-Duser.name=${JENKINS_USER} -Duser.home=/tmp/jenkins-home" \
./mvnw -s settings.xml \
- -P${PROFILE} clean dependency:list verify -Dsort -U -B -Dmaven.repo.local=/tmp/jenkins-home/.m2/spring-data-elasticsearch
\ No newline at end of file
+ -P${PROFILE} clean dependency:list verify -Dsort -U -B -Dmaven.repo.local=/tmp/jenkins-home/.m2/spring-data-elasticsearch -Ddevelocity.storage.directory=/tmp/jenkins-home/.develocity-root
diff --git a/package.json b/package.json
new file mode 100644
index 0000000000..4689506b3f
--- /dev/null
+++ b/package.json
@@ -0,0 +1,10 @@
+{
+ "dependencies": {
+ "antora": "3.2.0-alpha.6",
+ "@antora/atlas-extension": "1.0.0-alpha.2",
+ "@antora/collector-extension": "1.0.0-alpha.7",
+ "@asciidoctor/tabs": "1.0.0-beta.6",
+ "@springio/antora-extensions": "1.13.0",
+ "@springio/asciidoctor-extensions": "1.0.0-alpha.11"
+ }
+}
diff --git a/pom.xml b/pom.xml
index c13bab9a2d..4fcfd20c49 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,12 +5,12 @@
org.springframework.dataspring-data-elasticsearch
- 5.3.0-SNAPSHOT
+ 6.0.0-SNAPSHOTorg.springframework.data.buildspring-data-parent
- 3.3.0-SNAPSHOT
+ 4.0.0-SNAPSHOTSpring Data Elasticsearch
@@ -18,17 +18,16 @@
https://github.com/spring-projects/spring-data-elasticsearch
- 3.3.0-SNAPSHOT
+ 4.0.0-SNAPSHOT
- 8.11.1
+ 9.0.2
- 1.0.8.RELEASE
- 0.14.4
- 2.18.0
- 1.5.1
- 1.18.0
- 2.35.1
+ 0.19.0
+ 2.23.1
+ 1.5.3
+ 1.20.0
+ 3.9.1spring.data.elasticsearch
@@ -132,9 +131,10 @@
+
org.elasticsearch.client
- elasticsearch-rest-client
+ elasticsearch-rest-client${elasticsearch-java}
@@ -144,6 +144,13 @@
+
+ com.querydsl
+ querydsl-core
+ ${querydsl}
+ true
+
+
com.fasterxml.jackson.core
@@ -248,13 +255,6 @@
test
-
- io.projectreactor.tools
- blockhound-junit-platform
- ${blockhound-junit}
- test
-
-
org.skyscreamerjsonassert
@@ -263,8 +263,8 @@
- com.github.tomakehurst
- wiremock-jre8
+ org.wiremock
+ wiremock${wiremock}test
@@ -324,6 +324,13 @@
test
+
+ com.tngtech.archunit
+ archunit-junit5
+ ${archunit}
+ test
+
+
@@ -436,25 +443,6 @@
-
- jdk13+
-
-
- [13,)
-
-
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
-
- -XX:+AllowRedefinitionToAddDeleteMethods
-
-
-
-
-
-
antora-process-resources
@@ -472,7 +460,7 @@
- io.spring.maven.antora
+ org.antoraantora-maven-plugin
diff --git a/src/main/antora/antora-playbook.yml b/src/main/antora/antora-playbook.yml
index 27404c0c14..1a4f73c1e6 100644
--- a/src/main/antora/antora-playbook.yml
+++ b/src/main/antora/antora-playbook.yml
@@ -3,8 +3,7 @@
# The purpose of this Antora playbook is to build the docs in the current branch.
antora:
extensions:
- - '@antora/collector-extension'
- - require: '@springio/antora-extensions/root-component-extension'
+ - require: '@springio/antora-extensions'
root_component_name: 'data-elasticsearch'
site:
title: Spring Data Elasticsearch
@@ -18,17 +17,16 @@ content:
- url: https://github.com/spring-projects/spring-data-commons
# Refname matching:
# https://docs.antora.org/antora/latest/playbook/content-refname-matching/
- branches: [ main, 3.2.x ]
+ branches: [ main, 3.4.x, 3.3.x ]
start_path: src/main/antora
asciidoc:
attributes:
- page-pagination: ''
hide-uri-scheme: '@'
tabs-sync-option: '@'
- chomp: 'all'
extensions:
- '@asciidoctor/tabs'
- '@springio/asciidoctor-extensions'
+ - '@springio/asciidoctor-extensions/javadoc-extension'
sourcemap: true
urls:
latest_version_segment: ''
@@ -38,5 +36,5 @@ runtime:
format: pretty
ui:
bundle:
- url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.3.5/ui-bundle.zip
+ url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.4.16/ui-bundle.zip
snapshot: true
diff --git a/src/main/antora/antora.yml b/src/main/antora/antora.yml
index 70364a772e..2348fca613 100644
--- a/src/main/antora/antora.yml
+++ b/src/main/antora/antora.yml
@@ -10,3 +10,8 @@ ext:
local: true
scan:
dir: target/classes/
+ - run:
+ command: ./mvnw package -Pdistribute
+ local: true
+ scan:
+ dir: target/antora
diff --git a/src/main/antora/modules/ROOT/nav.adoc b/src/main/antora/modules/ROOT/nav.adoc
index db6e1ca61b..fa1ee8110d 100644
--- a/src/main/antora/modules/ROOT/nav.adoc
+++ b/src/main/antora/modules/ROOT/nav.adoc
@@ -9,6 +9,10 @@
*** xref:migration-guides/migration-guide-4.4-5.0.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.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[]
@@ -39,4 +43,5 @@
** xref:repositories/query-keywords-reference.adoc[]
** xref:repositories/query-return-types-reference.adoc[]
-* https://github.com/spring-projects/spring-data-commons/wiki[Wiki]
+* xref:attachment$api/java/index.html[Javadoc,role=link-external,window=_blank]
+* https://github.com/spring-projects/spring-data-commons/wiki[Wiki,role=link-external,window=_blank]
diff --git a/src/main/antora/modules/ROOT/pages/elasticsearch/auditing.adoc b/src/main/antora/modules/ROOT/pages/elasticsearch/auditing.adoc
index d02373f82b..f9633dec4f 100644
--- a/src/main/antora/modules/ROOT/pages/elasticsearch/auditing.adoc
+++ b/src/main/antora/modules/ROOT/pages/elasticsearch/auditing.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;
-import org.springframework.lang.Nullable;
+import org.jspecify.annotations.Nullable;
public interface Persistable {
@Nullable
@@ -81,5 +81,5 @@ class MyConfiguration {
}
----
-If your code contains more than one `AuditorAware` bean for different types, you must provide the name of the bean to use as an argument to the `auditorAwareRef` parameter of the
- `@EnableElasticsearchAuditing` annotation.
+If your code contains more than one `AuditorAware` bean for different types, you must provide the name of the bean to use as an argument to the `auditorAwareRef` parameter of the
+ `@EnableElasticsearchAuditing` annotation.
diff --git a/src/main/antora/modules/ROOT/pages/elasticsearch/clients.adoc b/src/main/antora/modules/ROOT/pages/elasticsearch/clients.adoc
index d7cfa9826c..0cf7d5ea3c 100644
--- a/src/main/antora/modules/ROOT/pages/elasticsearch/clients.adoc
+++ b/src/main/antora/modules/ROOT/pages/elasticsearch/clients.adoc
@@ -31,7 +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]
====
-The `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:
@@ -52,13 +52,13 @@ RestClient restClient; <.>
JsonpMapper jsonpMapper; <.>
----
-<.> an implementation of `ElasticsearchOperations`
+<.> an implementation of javadoc:org.springframework.data.elasticsearch.core.ElasticsearchOperations[]
<.> the `co.elastic.clients.elasticsearch.ElasticsearchClient` that is used.
<.> the low level `RestClient` from the Elasticsearch libraries
<.> the `JsonpMapper` user by the Elasticsearch `Transport`
====
-Basically one should just use the `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.
[[elasticsearch.clients.reactiverestclient]]
@@ -86,7 +86,7 @@ public class MyClientConfig extends ReactiveElasticsearchConfiguration {
<.> for a detailed description of the builder methods see xref:elasticsearch/clients.adoc#elasticsearch.clients.configuration[Client Configuration]
====
-The `ReactiveElasticsearchConfiguration` class allows further configuration by overriding for example the `jsonpMapper()` or `transportOptions()` methods.
+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:
@@ -108,20 +108,20 @@ JsonpMapper jsonpMapper; <.>
the following can be injected:
-<.> an implementation of `ReactiveElasticsearchOperations`
+<.> 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 `ReactiveElasticsearchOperations` to interact with the Elasticsearch cluster.
+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.configuration]]
== Client Configuration
-Client behaviour can be changed via the `ClientConfiguration` that allows to set options for SSL, connect and socket timeouts, headers and other parameters.
+Client behaviour can be changed via the javadoc:org.springframework.data.elasticsearch.client.ClientConfiguration[] that allows to set options for SSL, connect and socket timeouts, headers and other parameters.
.Client Configuration
====
@@ -150,7 +150,7 @@ ClientConfiguration clientConfiguration = ClientConfiguration.builder()
return headers;
})
.withClientConfigurer( <.>
- ElasticsearchClientConfigurationCallback.from(clientBuilder -> {
+ ElasticsearchHttpClientConfigurationCallback.from(clientBuilder -> {
// ...
return clientBuilder;
}))
@@ -178,7 +178,7 @@ If this is used in the reactive setup, the supplier function *must not* block!
[[elasticsearch.clients.configuration.callbacks]]
=== Client configuration callbacks
-The `ClientConfiguration` class offers the most common parameters to configure the client.
+The javadoc:org.springframework.data.elasticsearch.client.ClientConfiguration[] class offers the most common parameters to configure the client.
In the case this is not enough, the user can add callback functions by using the `withClientConfigurer(ClientConfigurationCallback>)` method.
The following callbacks are provided:
@@ -192,6 +192,7 @@ This callback provides a `org.elasticsearch.client.RestClientBuilder` that can b
[source,java]
----
ClientConfiguration.builder()
+ .connectedTo("localhost:9200", "localhost:9291")
.withClientConfigurer(ElasticsearchClients.ElasticsearchRestClientConfigurationCallback.from(restClientBuilder -> {
// configure the Elasticsearch RestClient
return restClientBuilder;
@@ -210,6 +211,7 @@ used by the `RestClient`.
[source,java]
----
ClientConfiguration.builder()
+ .connectedTo("localhost:9200", "localhost:9291")
.withClientConfigurer(ElasticsearchClients.ElasticsearchHttpClientConfigurationCallback.from(httpAsyncClientBuilder -> {
// configure the HttpAsyncClient
return httpAsyncClientBuilder;
diff --git a/src/main/antora/modules/ROOT/pages/elasticsearch/elasticsearch-new.adoc b/src/main/antora/modules/ROOT/pages/elasticsearch/elasticsearch-new.adoc
index 021161650c..d4a9c565d0 100644
--- a/src/main/antora/modules/ROOT/pages/elasticsearch/elasticsearch-new.adoc
+++ b/src/main/antora/modules/ROOT/pages/elasticsearch/elasticsearch-new.adoc
@@ -1,6 +1,40 @@
[[new-features]]
= What's new
+[[new-features.6-0-0]]
+== New in Spring Data Elasticsearch 6.0
+
+* Upgarde to Spring 7
+* Switch to jspecify nullability annotations
+* Upgrade to Elasticsearch 9.0.2
+
+
+[[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 in Spring Data Elasticsearch 5.3
+
+* Upgrade to Elasticsearch 8.13.2.
+* Add support for highlight queries in highlighting.
+* Add shard statistics to the `SearchHit` class.
+* Add support for multi search template API.
+* Add support for SpEL in @Query.
+* Add support for field aliases in the index mapping.
+* Add support for has_child and has_parent queries.
+
[[new-features.5-2-0]]
== New in Spring Data Elasticsearch 5.2
diff --git a/src/main/antora/modules/ROOT/pages/elasticsearch/join-types.adoc b/src/main/antora/modules/ROOT/pages/elasticsearch/join-types.adoc
index c97dd46c62..a1bc3df192 100644
--- a/src/main/antora/modules/ROOT/pages/elasticsearch/join-types.adoc
+++ b/src/main/antora/modules/ROOT/pages/elasticsearch/join-types.adoc
@@ -52,7 +52,7 @@ public class Statement {
return routing;
}
- public void setRouting(Routing routing) {
+ public void setRouting(String routing) {
this.routing = routing;
}
@@ -199,7 +199,7 @@ void init() {
repository.save(
Statement.builder()
.withText("+1 for the sun")
- ,withRouting(savedWeather.getId())
+ .withRouting(savedWeather.getId())
.withRelation(new JoinField<>("vote", sunnyAnswer.getId())) <5>
.build());
}
@@ -226,6 +226,7 @@ SearchHits hasVotes() {
Query query = NativeQuery.builder()
.withQuery(co.elastic.clients.elasticsearch._types.query_dsl.Query.of(qb -> qb
.hasChild(hc -> hc
+ .type("answer")
.queryName("vote")
.query(matchAllQueryAsQuery())
.scoreMode(ChildScoreMode.None)
diff --git a/src/main/antora/modules/ROOT/pages/elasticsearch/misc.adoc b/src/main/antora/modules/ROOT/pages/elasticsearch/misc.adoc
index 36567cda4a..7f3ac8f0ff 100644
--- a/src/main/antora/modules/ROOT/pages/elasticsearch/misc.adoc
+++ b/src/main/antora/modules/ROOT/pages/elasticsearch/misc.adoc
@@ -365,6 +365,8 @@ 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.
+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
xref:repositories/custom-implementations.adoc[]) as an example how this can be integrated into a repository call.
@@ -449,4 +451,3 @@ 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.
For the definition of the order path and the nested paths, the Java entity property names should be used.
-
diff --git a/src/main/antora/modules/ROOT/pages/elasticsearch/object-mapping.adoc b/src/main/antora/modules/ROOT/pages/elasticsearch/object-mapping.adoc
index ab6e98d5c4..6ca12728c0 100644
--- a/src/main/antora/modules/ROOT/pages/elasticsearch/object-mapping.adoc
+++ b/src/main/antora/modules/ROOT/pages/elasticsearch/object-mapping.adoc
@@ -192,8 +192,7 @@ public String getProperty() {
This annotation can be set on a String property of an entity.
This property will not be written to the mapping, it will not be stored in Elasticsearch and its value will not be read from an Elasticsearch document.
-After an entity is persisted, for example with a call to `ElasticsearchOperations.save(T entity)`, the entity
-returned from that call will contain the name of the index that an entity was saved to in that property.
+After an entity is persisted, for example with a call to `ElasticsearchOperations.save(T entity)`, the entity returned from that call will contain the name of the index that an entity was saved to in that property.
This is useful when the index name is dynamically set by a bean, or when writing to a write alias.
Putting some value into such a property does not set the index into which an entity is stored!
@@ -423,7 +422,6 @@ Looking at the `Configuration` from the xref:elasticsearch/object-mapping.adoc#e
@Configuration
public class Config extends ElasticsearchConfiguration {
- @NonNull
@Override
public ClientConfiguration clientConfiguration() {
return ClientConfiguration.builder() //
diff --git a/src/main/antora/modules/ROOT/pages/elasticsearch/repositories/elasticsearch-repositories.adoc b/src/main/antora/modules/ROOT/pages/elasticsearch/repositories/elasticsearch-repositories.adoc
index 8a1f7fe664..1d08868c10 100644
--- a/src/main/antora/modules/ROOT/pages/elasticsearch/repositories/elasticsearch-repositories.adoc
+++ b/src/main/antora/modules/ROOT/pages/elasticsearch/repositories/elasticsearch-repositories.adoc
@@ -12,10 +12,10 @@ class Book {
@Id
private String id;
- @Field(type = FieldType.text)
+ @Field(type = FieldType.Text)
private String name;
- @Field(type = FieldType.text)
+ @Field(type = FieldType.Text)
private String summary;
@Field(type = FieldType.Integer)
diff --git a/src/main/antora/modules/ROOT/pages/elasticsearch/repositories/elasticsearch-repository-queries.adoc b/src/main/antora/modules/ROOT/pages/elasticsearch/repositories/elasticsearch-repository-queries.adoc
index 2b725a820f..b22e17522d 100644
--- a/src/main/antora/modules/ROOT/pages/elasticsearch/repositories/elasticsearch-repository-queries.adoc
+++ b/src/main/antora/modules/ROOT/pages/elasticsearch/repositories/elasticsearch-repository-queries.adoc
@@ -10,7 +10,9 @@ The Elasticsearch module supports all basic query building feature as string que
=== Declared queries
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 @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 the @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]]
== Query creation
@@ -312,11 +314,13 @@ Repository methods can be defined to have the following return types for returni
* `SearchPage`
[[elasticsearch.query-methods.at-query]]
-== Using @Query Annotation
+== 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 placeholders are of the form `?0`, `?1`, `?2` etc. for the first, second, third parameter and so on.
+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.
+
[source,java]
----
interface BookRepository extends ElasticsearchRepository {
@@ -341,15 +345,20 @@ 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
====
A repository method such as
+
[source,java]
----
@Query("{\"ids\": {\"values\": ?0 }}")
List getByIds(Collection 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]
----
{
@@ -361,3 +370,223 @@ would make an https://www.elastic.co/guide/en/elasticsearch/reference/current/qu
}
----
====
+
+[[elasticsearch.query-methods.at-query.spel]]
+=== Using SpEL Expressions
+
+.Declare query on the method using the `@Query` annotation with SpEL expression.
+====
+https://docs.spring.io/spring-framework/reference/core/expressions.html[SpEL expression] is also supported when defining query in `@Query`.
+
+[source,java]
+----
+interface BookRepository extends ElasticsearchRepository {
+ @Query("""
+ {
+ "bool":{
+ "must":[
+ {
+ "term":{
+ "name": "#{#name}"
+ }
+ }
+ ]
+ }
+ }
+ """)
+ Page findByName(String name, Pageable pageable);
+}
+----
+
+If for example the function is called with the parameter _John_, it would produce the following query body:
+
+[source,json]
+----
+{
+ "bool":{
+ "must":[
+ {
+ "term":{
+ "name": "John"
+ }
+ }
+ ]
+ }
+}
+----
+====
+
+.accessing parameter property.
+====
+Supposing that we have the following class as query parameter type:
+
+[source,java]
+----
+public record QueryParameter(String value) {
+}
+----
+
+It's easy to access the parameter by `#` symbol, then reference the property `value` with a simple `.`:
+
+[source,java]
+----
+interface BookRepository extends ElasticsearchRepository {
+ @Query("""
+ {
+ "bool":{
+ "must":[
+ {
+ "term":{
+ "name": "#{#parameter.value}"
+ }
+ }
+ ]
+ }
+ }
+ """)
+ Page findByName(QueryParameter parameter, Pageable pageable);
+}
+----
+
+We can pass `new QueryParameter("John")` as the parameter now, and it will produce the same query string as above.
+====
+
+.accessing bean property.
+====
+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:
+
+[source,java]
+----
+interface BookRepository extends ElasticsearchRepository {
+ @Query("""
+ {
+ "bool":{
+ "must":[
+ {
+ "term":{
+ "name": "#{@queryParameter.value}"
+ }
+ }
+ ]
+ }
+ }
+ """)
+ Page findByName(Pageable pageable);
+}
+----
+====
+
+.SpEL and `Collection` param.
+====
+`Collection` parameter is also supported and is as easy to use as normal `String`, such as the following `terms` query:
+
+[source,java]
+----
+interface BookRepository extends ElasticsearchRepository {
+ @Query("""
+ {
+ "bool":{
+ "must":[
+ {
+ "terms":{
+ "name": #{#names}
+ }
+ }
+ ]
+ }
+ }
+ """)
+ Page findByName(Collection names, Pageable pageable);
+}
+----
+
+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:
+
+[source,json]
+----
+{
+ "bool":{
+ "must":[
+ {
+ "terms":{
+ "name": ["name1", "name2"]
+ }
+ }
+ ]
+ }
+}
+----
+====
+
+.access property in the `Collection` param.
+====
+https://docs.spring.io/spring-framework/reference/core/expressions/language-ref/collection-projection.html[SpEL Collection Projection] is convenient to use when values in the `Collection` parameter is not plain `String`:
+
+[source,java]
+----
+interface BookRepository extends ElasticsearchRepository {
+ @Query("""
+ {
+ "bool":{
+ "must":[
+ {
+ "terms":{
+ "name": #{#parameters.![value]}
+ }
+ }
+ ]
+ }
+ }
+ """)
+ Page findByName(Collection 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.
+====
+
+.alter parameter name by using `@Param`
+====
+When accessing the parameter by SpEL, it's also useful to alter the parameter name to another one by `@Param` annotation in Sping Data:
+
+[source,java]
+----
+interface BookRepository extends ElasticsearchRepository {
+ @Query("""
+ {
+ "bool":{
+ "must":[
+ {
+ "terms":{
+ "name": #{#another.![value]}
+ }
+ }
+ ]
+ }
+ }
+ """)
+ Page findByName(@Param("another") Collection parameters, Pageable pageable);
+}
+----
+
+====
+
+[[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 {
+ @SearchTemplateQuery(id = "book-by-title")
+ SearchHits 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.
diff --git a/src/main/antora/modules/ROOT/pages/elasticsearch/scripted-and-runtime-fields.adoc b/src/main/antora/modules/ROOT/pages/elasticsearch/scripted-and-runtime-fields.adoc
index 7c5d730e25..64d4a0c003 100644
--- a/src/main/antora/modules/ROOT/pages/elasticsearch/scripted-and-runtime-fields.adoc
+++ b/src/main/antora/modules/ROOT/pages/elasticsearch/scripted-and-runtime-fields.adoc
@@ -20,12 +20,12 @@ Whereas the birthdate is fix, the age depends on the time when a query is issued
====
[source,java]
----
+import org.jspecify.annotations.Nullable;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.DateFormat;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.ScriptedField;
-import org.springframework.lang.Nullable;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
@@ -194,7 +194,7 @@ In the following code this is used to run a query for a given gender and maximum
var runtimeField = new RuntimeField("age", "long", """ <.>
Instant currentDate = Instant.ofEpochMilli(new Date().getTime());
- Instant startDate = doc['birth-date'].value.toInstant();
+ Instant startDate = doc['birthDate'].value.toInstant();
emit (ChronoUnit.DAYS.between(startDate, currentDate) / 365);
""");
diff --git a/src/main/antora/modules/ROOT/pages/elasticsearch/template.adoc b/src/main/antora/modules/ROOT/pages/elasticsearch/template.adoc
index b893bb1a19..d5cbec5d09 100644
--- a/src/main/antora/modules/ROOT/pages/elasticsearch/template.adoc
+++ b/src/main/antora/modules/ROOT/pages/elasticsearch/template.adoc
@@ -3,10 +3,10 @@
Spring Data Elasticsearch uses several interfaces to define the operations that can be called against an Elasticsearch index (for a description of the reactive interfaces see xref:elasticsearch/reactive-template.adoc[]).
-* `IndexOperations` defines actions on index level like creating or deleting an index.
-* `DocumentOperations` defines actions to store, update and retrieve entities based on their id.
-* `SearchOperations` define the actions to search for multiple entities using queries
-* `ElasticsearchOperations` combines the `DocumentOperations` and `SearchOperations` interfaces.
+* javadoc:org.springframework.data.elasticsearch.core.IndexOperations[] defines actions on index level like creating or deleting an index.
+* javadoc:org.springframework.data.elasticsearch.core.DocumentOperations[] defines actions to store, update and retrieve entities based on their id.
+* javadoc:org.springframework.data.elasticsearch.core.SearchOperations[] define the actions to search for multiple entities using queries
+* javadoc:org.springframework.data.elasticsearch.core.ElasticsearchOperations[] combines the `DocumentOperations` and `SearchOperations` interfaces.
These interfaces correspond to the structuring of the https://www.elastic.co/guide/en/elasticsearch/reference/current/rest-apis.html[Elasticsearch API].
@@ -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.
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.
+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.
The following classes and interfaces are now available:
.SearchHit
diff --git a/src/main/antora/modules/ROOT/pages/elasticsearch/versions.adoc b/src/main/antora/modules/ROOT/pages/elasticsearch/versions.adoc
index 19d824b00e..861e2ff3bb 100644
--- a/src/main/antora/modules/ROOT/pages/elasticsearch/versions.adoc
+++ b/src/main/antora/modules/ROOT/pages/elasticsearch/versions.adoc
@@ -1,24 +1,27 @@
[[preface.versions]]
= Versions
-The following table shows the Elasticsearch versions that are used by Spring Data release trains and version of Spring Data Elasticsearch included in that, as well as the Spring Boot versions referring to that particular Spring Data release train.
-The Elasticsearch version given shows with which client libraries Spring Data Elasticsearch was built and tested.
+The following table shows the Elasticsearch and Spring versions that are used by Spring Data release trains and the version of Spring Data Elasticsearch included in that.
-[cols="^,^,^,^,^",options="header"]
+[cols="^,^,^,^",options="header"]
|===
-| Spring Data Release Train | Spring Data Elasticsearch | Elasticsearch | Spring Framework | Spring Boot
-| 2023.1 (Vaughan) | 5.2.x | 8.11.1 | 6.1.x | 3.2.x
-| 2023.0 (Ullmann) | 5.1.x | 8.7.1 | 6.0.x | 3.1.x
-| 2022.0 (Turing) | 5.0.xfootnote:oom[Out of maintenance] | 8.5.3 | 6.0.x | 3.0.x
-| 2021.2 (Raj) | 4.4.xfootnote:oom[] | 7.17.3 | 5.3.x | 2.7.x
-| 2021.1 (Q) | 4.3.xfootnote:oom[] | 7.15.2 | 5.3.x | 2.6.x
-| 2021.0 (Pascal) | 4.2.xfootnote:oom[] | 7.12.0 | 5.3.x | 2.5.x
-| 2020.0 (Ockham) | 4.1.xfootnote:oom[] | 7.9.3 | 5.3.2 | 2.4.x
-| Neumann | 4.0.xfootnote:oom[] | 7.6.2 | 5.2.12 |2.3.x
-| Moore | 3.2.xfootnote:oom[] |6.8.12 | 5.2.12| 2.2.x
-| Lovelace | 3.1.xfootnote:oom[] | 6.2.2 | 5.1.19 |2.1.x
-| Kay | 3.0.xfootnote:oom[] | 5.5.0 | 5.0.13 | 2.0.x
-| Ingalls | 2.1.xfootnote:oom[] | 2.4.0 | 4.3.25 | 1.5.x
+| Spring Data Release Train | Spring Data Elasticsearch | Elasticsearch | Spring Framework
+| 2025.1 (in development) | 6.0.x | 9.0.2 | 7.0.x
+| 2025.0 | 5.5.x | 8.18.1 | 6.2.x
+| 2024.1 | 5.4.x | 8.15.5 | 6.1.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
+| 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.0 (Pascal) | 4.2.xfootnote:oom[] | 7.12.0 | 5.3.x
+| 2020.0 (Ockham) | 4.1.xfootnote:oom[] | 7.9.3 | 5.3.2
+| Neumann | 4.0.xfootnote:oom[] | 7.6.2 | 5.2.12
+| Moore | 3.2.xfootnote:oom[] |6.8.12 | 5.2.12
+| Lovelace | 3.1.xfootnote:oom[] | 6.2.2 | 5.1.19
+| Kay | 3.0.xfootnote:oom[] | 5.5.0 | 5.0.13
+| Ingalls | 2.1.xfootnote:oom[] | 2.4.0 | 4.3.25
|===
Support for upcoming versions of Elasticsearch is being tracked and general compatibility should be given assuming the usage of the xref:elasticsearch/template.adoc[ElasticsearchOperations interface].
diff --git a/src/main/antora/modules/ROOT/pages/migration-guides/migration-guide-4.4-5.0.adoc b/src/main/antora/modules/ROOT/pages/migration-guides/migration-guide-4.4-5.0.adoc
index eb627f141a..e11955fefa 100644
--- a/src/main/antora/modules/ROOT/pages/migration-guides/migration-guide-4.4-5.0.adoc
+++ b/src/main/antora/modules/ROOT/pages/migration-guides/migration-guide-4.4-5.0.adoc
@@ -49,7 +49,7 @@ Also the reactive implementation that was provided up to now has been moved here
If you are using `ElasticsearchRestTemplate` directly and not the `ElasticsearchOperations` interface you'll need to adjust your imports as well.
When working with the `NativeSearchQuery` class, you'll need to switch to the `NativeQuery` class, which can take a
-`Query` instance comign from the new Elasticsearch client libraries.
+`Query` instance coming from the new Elasticsearch client libraries.
You'll find plenty of examples in the test code.
[[elasticsearch-migration-guide-4.4-5.0.breaking-changes-records]]
diff --git a/src/main/antora/modules/ROOT/pages/migration-guides/migration-guide-5.2-5.3.adoc b/src/main/antora/modules/ROOT/pages/migration-guides/migration-guide-5.2-5.3.adoc
new file mode 100644
index 0000000000..808578cb59
--- /dev/null
+++ b/src/main/antora/modules/ROOT/pages/migration-guides/migration-guide-5.2-5.3.adoc
@@ -0,0 +1,21 @@
+[[elasticsearch-migration-guide-5.2-5.3]]
+= Upgrading from 5.2.x to 5.3.x
+
+This section describes breaking changes from version 5.2.x to 5.3.x and how removed features can be replaced by new introduced features.
+
+[[elasticsearch-migration-guide-5.2-5.3.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 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 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
+`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]]
+== Deprecations
+
+=== Removals
+
+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.
diff --git a/src/main/antora/modules/ROOT/pages/migration-guides/migration-guide-5.3-5.4.adoc b/src/main/antora/modules/ROOT/pages/migration-guides/migration-guide-5.3-5.4.adoc
new file mode 100644
index 0000000000..c5178ff75d
--- /dev/null
+++ b/src/main/antora/modules/ROOT/pages/migration-guides/migration-guide-5.3-5.4.adoc
@@ -0,0 +1,23 @@
+[[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
diff --git a/src/main/antora/modules/ROOT/pages/migration-guides/migration-guide-5.4-5.5.adoc b/src/main/antora/modules/ROOT/pages/migration-guides/migration-guide-5.4-5.5.adoc
new file mode 100644
index 0000000000..38b2b4af2b
--- /dev/null
+++ b/src/main/antora/modules/ROOT/pages/migration-guides/migration-guide-5.4-5.5.adoc
@@ -0,0 +1,30 @@
+[[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)
+```
diff --git a/src/main/antora/modules/ROOT/pages/migration-guides/migration-guide-5.5-6.0.adoc b/src/main/antora/modules/ROOT/pages/migration-guides/migration-guide-5.5-6.0.adoc
new file mode 100644
index 0000000000..7667701a17
--- /dev/null
+++ b/src/main/antora/modules/ROOT/pages/migration-guides/migration-guide-5.5-6.0.adoc
@@ -0,0 +1,21 @@
+[[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
+
+[[elasticsearch-migration-guide-5.5-6.0.deprecations]]
+== Deprecations
+
+
+=== 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>)
+```
diff --git a/src/main/java/org/springframework/data/elasticsearch/BulkFailureException.java b/src/main/java/org/springframework/data/elasticsearch/BulkFailureException.java
index 8d5a10a2ac..6d40bca631 100644
--- a/src/main/java/org/springframework/data/elasticsearch/BulkFailureException.java
+++ b/src/main/java/org/springframework/data/elasticsearch/BulkFailureException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020-2023 the original author or authors.
+ * Copyright 2020-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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/ElasticsearchErrorCause.java b/src/main/java/org/springframework/data/elasticsearch/ElasticsearchErrorCause.java
index 38f52df0c8..22dbbfd7c0 100644
--- a/src/main/java/org/springframework/data/elasticsearch/ElasticsearchErrorCause.java
+++ b/src/main/java/org/springframework/data/elasticsearch/ElasticsearchErrorCause.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2022-2023 the original author or authors.
+ * 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.
@@ -15,10 +15,10 @@
*/
package org.springframework.data.elasticsearch;
-import org.springframework.lang.Nullable;
-
import java.util.List;
+import org.jspecify.annotations.Nullable;
+
/**
* Object describing an Elasticsearch error
*
@@ -26,8 +26,7 @@
* @since 4.4
*/
public class ElasticsearchErrorCause {
- @Nullable
- private final String type;
+ @Nullable private final String type;
private final String reason;
diff --git a/src/main/java/org/springframework/data/elasticsearch/NoSuchIndexException.java b/src/main/java/org/springframework/data/elasticsearch/NoSuchIndexException.java
index b7a1bbd6e0..c1eab9bcf7 100644
--- a/src/main/java/org/springframework/data/elasticsearch/NoSuchIndexException.java
+++ b/src/main/java/org/springframework/data/elasticsearch/NoSuchIndexException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2023 the original author or authors.
+ * Copyright 2019-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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/ResourceFailureException.java b/src/main/java/org/springframework/data/elasticsearch/ResourceFailureException.java
index 0b9c0bf3a5..493d3b4b7b 100644
--- a/src/main/java/org/springframework/data/elasticsearch/ResourceFailureException.java
+++ b/src/main/java/org/springframework/data/elasticsearch/ResourceFailureException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2021-2023 the original author or authors.
+ * 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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/ResourceNotFoundException.java b/src/main/java/org/springframework/data/elasticsearch/ResourceNotFoundException.java
index 03170a0708..5e97b4e00b 100644
--- a/src/main/java/org/springframework/data/elasticsearch/ResourceNotFoundException.java
+++ b/src/main/java/org/springframework/data/elasticsearch/ResourceNotFoundException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2022-2023 the original author or authors.
+ * 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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/RestStatusException.java b/src/main/java/org/springframework/data/elasticsearch/RestStatusException.java
index 8849e21d83..c707686098 100644
--- a/src/main/java/org/springframework/data/elasticsearch/RestStatusException.java
+++ b/src/main/java/org/springframework/data/elasticsearch/RestStatusException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2021-2023 the original author or authors.
+ * 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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/UncategorizedElasticsearchException.java b/src/main/java/org/springframework/data/elasticsearch/UncategorizedElasticsearchException.java
index c86be98f0a..ffc71ef7ba 100644
--- a/src/main/java/org/springframework/data/elasticsearch/UncategorizedElasticsearchException.java
+++ b/src/main/java/org/springframework/data/elasticsearch/UncategorizedElasticsearchException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020-2023 the original author or authors.
+ * Copyright 2020-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.
@@ -15,8 +15,8 @@
*/
package org.springframework.data.elasticsearch;
+import org.jspecify.annotations.Nullable;
import org.springframework.dao.UncategorizedDataAccessException;
-import org.springframework.lang.Nullable;
/**
* @author Peter-Josef Meisch
diff --git a/src/main/java/org/springframework/data/elasticsearch/VersionConflictException.java b/src/main/java/org/springframework/data/elasticsearch/VersionConflictException.java
index d9c2e83dff..b3f31d3550 100644
--- a/src/main/java/org/springframework/data/elasticsearch/VersionConflictException.java
+++ b/src/main/java/org/springframework/data/elasticsearch/VersionConflictException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 the original author or authors.
+ * Copyright 2023-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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/Alias.java b/src/main/java/org/springframework/data/elasticsearch/annotations/Alias.java
new file mode 100644
index 0000000000..0f707e942e
--- /dev/null
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/Alias.java
@@ -0,0 +1,79 @@
+/*
+ * 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;
+}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/Aliases.java b/src/main/java/org/springframework/data/elasticsearch/annotations/Aliases.java
new file mode 100644
index 0000000000..ea5d895294
--- /dev/null
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/Aliases.java
@@ -0,0 +1,36 @@
+/*
+ * 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();
+}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/CompletionContext.java b/src/main/java/org/springframework/data/elasticsearch/annotations/CompletionContext.java
index 4fd6faa383..da27c1245b 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/CompletionContext.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/CompletionContext.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2023 the original author or authors.
+ * Copyright 2019-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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/CompletionField.java b/src/main/java/org/springframework/data/elasticsearch/annotations/CompletionField.java
index 95e5060f93..94ca1ea724 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/CompletionField.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/CompletionField.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013-2023 the original author or authors.
+ * Copyright 2013-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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/CountQuery.java b/src/main/java/org/springframework/data/elasticsearch/annotations/CountQuery.java
index 463452ca1d..80bb7c15f9 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/CountQuery.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/CountQuery.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2021-2023 the original author or authors.
+ * 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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/DateFormat.java b/src/main/java/org/springframework/data/elasticsearch/annotations/DateFormat.java
index 1119374dcd..9f3b7f9d78 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/DateFormat.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/DateFormat.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014-2023 the original author or authors.
+ * Copyright 2014-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.
@@ -39,41 +39,173 @@ public enum DateFormat {
basic_t_time("'T'HHmmss.SSSXXX"), //
basic_t_time_no_millis("'T'HHmmssXXX"), //
basic_week_date("YYYY'W'wwe"), // week-based-year!
+ /**
+ * @since 5.3
+ */
+ strict_basic_week_date("YYYY'W'wwe"), // week-based-year!
basic_week_date_time("YYYY'W'wwe'T'HHmmss.SSSX"), // here Elasticsearch uses a different zone format
+ /**
+ * @since 5.3
+ */
+ strict_basic_week_date_time("YYYY'W'wwe'T'HHmmss.SSSX"), // here Elasticsearch uses a different zone format
basic_week_date_time_no_millis("YYYY'W'wwe'T'HHmmssX"), //
+ /**
+ * @since 5.3
+ */
+ strict_basic_week_date_time_no_millis("YYYY'W'wwe'T'HHmmssX"), //
date("uuuu-MM-dd"), //
+ /**
+ * @since 5.3
+ */
+ strict_date("uuuu-MM-dd"), //
date_hour("uuuu-MM-dd'T'HH"), //
+ /**
+ * @since 5.3
+ */
+ strict_date_hour("uuuu-MM-dd'T'HH"), //
date_hour_minute("uuuu-MM-dd'T'HH:mm"), //
+ /**
+ * @since 5.3
+ */
+ strict_date_hour_minute("uuuu-MM-dd'T'HH:mm"), //
date_hour_minute_second("uuuu-MM-dd'T'HH:mm:ss"), //
+ /**
+ * @since 5.3
+ */
+ strict_date_hour_minute_second("uuuu-MM-dd'T'HH:mm:ss"), //
date_hour_minute_second_fraction("uuuu-MM-dd'T'HH:mm:ss.SSS"), //
+ /**
+ * @since 5.3
+ */
+ strict_date_hour_minute_second_fraction("uuuu-MM-dd'T'HH:mm:ss.SSS"), //
date_hour_minute_second_millis("uuuu-MM-dd'T'HH:mm:ss.SSS"), //
+ /**
+ * @since 5.3
+ */
+ strict_date_hour_minute_second_millis("uuuu-MM-dd'T'HH:mm:ss.SSS"), //
date_optional_time("uuuu-MM-dd['T'HH:mm:ss.SSSXXX]"), //
+ /**
+ * @since 5.3
+ */
+ strict_date_optional_time("uuuu-MM-dd['T'HH:mm:ss.SSSXXX]"), //
strict_date_optional_time_nanos("uuuu-MM-dd['T'HH:mm:ss.SSSSSSXXX]"), //
date_time("uuuu-MM-dd'T'HH:mm:ss.SSSXXX"), //
+ /**
+ * @since 5.3
+ */
+ strict_date_time("uuuu-MM-dd'T'HH:mm:ss.SSSXXX"), //
date_time_no_millis("uuuu-MM-dd'T'HH:mm:ssVV"), // here Elasticsearch uses the zone-id in its implementation
+ /**
+ * @since 5.3
+ */
+ strict_date_time_no_millis("uuuu-MM-dd'T'HH:mm:ssVV"), // here Elasticsearch uses the zone-id in its implementation
epoch_millis("epoch_millis"), //
epoch_second("epoch_second"), //
hour("HH"), //
+ /**
+ * @since 5.3
+ */
+ strict_hour("HH"), //
hour_minute("HH:mm"), //
+ /**
+ * @since 5.3
+ */
+ strict_hour_minute("HH:mm"), //
hour_minute_second("HH:mm:ss"), //
+ /**
+ * @since 5.3
+ */
+ strict_hour_minute_second("HH:mm:ss"), //
hour_minute_second_fraction("HH:mm:ss.SSS"), //
+ /**
+ * @since 5.3
+ */
+ strict_hour_minute_second_fraction("HH:mm:ss.SSS"), //
hour_minute_second_millis("HH:mm:ss.SSS"), //
+ /**
+ * @since 5.3
+ */
+ strict_hour_minute_second_millis("HH:mm:ss.SSS"), //
ordinal_date("uuuu-DDD"), //
+ /**
+ * @since 5.3
+ */
+ strict_ordinal_date("uuuu-DDD"), //
ordinal_date_time("uuuu-DDD'T'HH:mm:ss.SSSXXX"), //
+ /**
+ * @since 5.3
+ */
+ strict_ordinal_date_time("uuuu-DDD'T'HH:mm:ss.SSSXXX"), //
ordinal_date_time_no_millis("uuuu-DDD'T'HH:mm:ssXXX"), //
+ /**
+ * @since 5.3
+ */
+ strict_ordinal_date_time_no_millis("uuuu-DDD'T'HH:mm:ssXXX"), //
time("HH:mm:ss.SSSXXX"), //
+ /**
+ * @since 5.3
+ */
+ strict_time("HH:mm:ss.SSSXXX"), //
time_no_millis("HH:mm:ssXXX"), //
+ /**
+ * @since 5.3
+ */
+ strict_time_no_millis("HH:mm:ssXXX"), //
t_time("'T'HH:mm:ss.SSSXXX"), //
+ /**
+ * @since 5.3
+ */
+ strict_t_time("'T'HH:mm:ss.SSSXXX"), //
t_time_no_millis("'T'HH:mm:ssXXX"), //
+ /**
+ * @since 5.3
+ */
+ strict_t_time_no_millis("'T'HH:mm:ssXXX"), //
week_date("YYYY-'W'ww-e"), //
+ /**
+ * @since 5.3
+ */
+ strict_week_date("YYYY-'W'ww-e"), //
week_date_time("YYYY-'W'ww-e'T'HH:mm:ss.SSSXXX"), //
+ /**
+ * @since 5.3
+ */
+ strict_week_date_time("YYYY-'W'ww-e'T'HH:mm:ss.SSSXXX"), //
week_date_time_no_millis("YYYY-'W'ww-e'T'HH:mm:ssXXX"), //
+ /**
+ * @since 5.3
+ */
+ strict_week_date_time_no_millis("YYYY-'W'ww-e'T'HH:mm:ssXXX"), //
weekyear(""), // no TemporalAccessor available for these 3
+ /**
+ * @since 5.3
+ */
+ strict_weekyear(""), // no TemporalAccessor available for these 3
weekyear_week(""), //
+ /**
+ * @since 5.3
+ */
+ strict_weekyear_week(""), //
weekyear_week_day(""), //
+ /**
+ * @since 5.3
+ */
+ strict_strict_weekyear_week_day(""), //
year("uuuu"), //
+ /**
+ * @since 5.3
+ */
+ strict_year("uuuu"), //
year_month("uuuu-MM"), //
- year_month_day("uuuu-MM-dd"); //
+ /**
+ * @since 5.3
+ */
+ strict_year_month("uuuu-MM"), //
+ year_month_day("uuuu-MM-dd"), //
+ /**
+ * @since 5.3
+ */
+ strict_year_month_day("uuuu-MM-dd"); //
private final String pattern;
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/Document.java b/src/main/java/org/springframework/data/elasticsearch/annotations/Document.java
index fb24e05483..1131b2cd59 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/Document.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/Document.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013-2023 the original author or authors.
+ * Copyright 2013-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.
@@ -100,6 +100,13 @@
*/
boolean storeVersionInSource() default true;
+ /**
+ * Aliases for the index.
+ *
+ * @since 5.4
+ */
+ Alias[] aliases() default {};
+
/**
* @since 4.3
*/
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/Dynamic.java b/src/main/java/org/springframework/data/elasticsearch/annotations/Dynamic.java
index fae31617a9..9868c6e3c6 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/Dynamic.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/Dynamic.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2021-2023 the original author or authors.
+ * 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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/Field.java b/src/main/java/org/springframework/data/elasticsearch/annotations/Field.java
index 0459857d31..97815477ae 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/Field.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/Field.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013-2023 the original author or authors.
+ * Copyright 2013-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.
@@ -37,6 +37,8 @@
* @author Brian Kimmig
* @author Morgan Lutz
* @author Sascha Woo
+ * @author Haibo Liu
+ * @author Andriy Redko
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.METHOD })
@@ -128,6 +130,10 @@
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
*/
String nullValue() default "";
@@ -195,6 +201,27 @@
*/
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.
* To be used in combination with {@link FieldType#Object} or {@link FieldType#Nested}
@@ -218,4 +245,11 @@
* @since 5.1
*/
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 "";
}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/FieldElementType.java b/src/main/java/org/springframework/data/elasticsearch/annotations/FieldElementType.java
new file mode 100644
index 0000000000..49271764ba
--- /dev/null
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/FieldElementType.java
@@ -0,0 +1,26 @@
+/*
+ * 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";
+}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/FieldType.java b/src/main/java/org/springframework/data/elasticsearch/annotations/FieldType.java
index d6cb398ba5..f701948d6d 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/FieldType.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/FieldType.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013-2023 the original author or authors.
+ * Copyright 2013-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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/Filter.java b/src/main/java/org/springframework/data/elasticsearch/annotations/Filter.java
new file mode 100644
index 0000000000..7f07df55d1
--- /dev/null
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/Filter.java
@@ -0,0 +1,38 @@
+/*
+ * 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 "";
+}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/GeoPointField.java b/src/main/java/org/springframework/data/elasticsearch/annotations/GeoPointField.java
index e17b85ff01..05695abc98 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/GeoPointField.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/GeoPointField.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013-2023 the original author or authors.
+ * Copyright 2013-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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/GeoShapeField.java b/src/main/java/org/springframework/data/elasticsearch/annotations/GeoShapeField.java
index 865bf694da..0121b07ee1 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/GeoShapeField.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/GeoShapeField.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017-2023 the original author or authors.
+ * Copyright 2017-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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/Highlight.java b/src/main/java/org/springframework/data/elasticsearch/annotations/Highlight.java
index 0c59f2d149..30312ab434 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/Highlight.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/Highlight.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020-2023 the original author or authors.
+ * Copyright 2020-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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/HighlightField.java b/src/main/java/org/springframework/data/elasticsearch/annotations/HighlightField.java
index 4dbf7e92ba..f6318be98a 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/HighlightField.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/HighlightField.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020-2023 the original author or authors.
+ * Copyright 2020-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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/HighlightParameters.java b/src/main/java/org/springframework/data/elasticsearch/annotations/HighlightParameters.java
index 55cb5ab579..d4e8bbfd2b 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/HighlightParameters.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/HighlightParameters.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020-2023 the original author or authors.
+ * Copyright 2020-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.
@@ -21,6 +21,7 @@
/**
* @author Peter-Josef Meisch
+ * @author Haibo Liu
* @since 4.0
*/
@Documented
@@ -59,6 +60,8 @@
int numberOfFragments() default -1;
+ Query highlightQuery() default @Query;
+
String order() default "";
int phraseLimit() default -1;
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/IndexOptions.java b/src/main/java/org/springframework/data/elasticsearch/annotations/IndexOptions.java
index b396786abb..2de226c7b1 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/IndexOptions.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/IndexOptions.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2023 the original author or authors.
+ * Copyright 2019-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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/IndexPrefixes.java b/src/main/java/org/springframework/data/elasticsearch/annotations/IndexPrefixes.java
index 9d8333b0f8..01adc8fbb4 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/IndexPrefixes.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/IndexPrefixes.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2023 the original author or authors.
+ * Copyright 2019-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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/IndexedIndexName.java b/src/main/java/org/springframework/data/elasticsearch/annotations/IndexedIndexName.java
index 1a15f506c9..4d76b97492 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/IndexedIndexName.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/IndexedIndexName.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 the original author or authors.
+ * Copyright 2023-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.
@@ -15,9 +15,6 @@
*/
package org.springframework.data.elasticsearch.annotations;
-import org.springframework.data.annotation.ReadOnlyProperty;
-import org.springframework.data.annotation.Transient;
-
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@@ -25,10 +22,10 @@
import java.lang.annotation.Target;
/**
- * Annotation to mark a String property of an entity to be filled with the name of the index where the entity was
- * stored after it is indexed into Elasticsearch. This can be used when the name of the index is dynamically created
- * or when a document was indexed into a write alias.
- *
+ * Annotation to mark a String property of an entity to be filled with the name of the index where the entity was stored
+ * after it is indexed into Elasticsearch. This can be used when the name of the index is dynamically created or when a
+ * document was indexed into a write alias.
+ *
* This can not be used to specify the index where an entity should be written to.
*
* @author Peter-Josef Meisch
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/InnerField.java b/src/main/java/org/springframework/data/elasticsearch/annotations/InnerField.java
index 3d1bd46e62..651bf5a825 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/InnerField.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/InnerField.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014-2023 the original author or authors.
+ * Copyright 2014-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.
@@ -29,6 +29,8 @@
* @author Aleksei Arsenev
* @author Brian Kimmig
* @author Morgan Lutz
+ * @author Haibo Liu
+ * @author Andriy Redko
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
@@ -149,4 +151,32 @@
* @since 4.2
*/
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 "";
}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/JoinTypeRelation.java b/src/main/java/org/springframework/data/elasticsearch/annotations/JoinTypeRelation.java
index f814588112..eb2e1e4623 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/JoinTypeRelation.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/JoinTypeRelation.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020-2023 the original author or authors.
+ * Copyright 2020-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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/JoinTypeRelations.java b/src/main/java/org/springframework/data/elasticsearch/annotations/JoinTypeRelations.java
index 6127b94849..2004200cf2 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/JoinTypeRelations.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/JoinTypeRelations.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020-2023 the original author or authors.
+ * Copyright 2020-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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/KnnAlgorithmType.java b/src/main/java/org/springframework/data/elasticsearch/annotations/KnnAlgorithmType.java
new file mode 100644
index 0000000000..6110e54be8
--- /dev/null
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/KnnAlgorithmType.java
@@ -0,0 +1,38 @@
+/*
+ * 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;
+ }
+}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/KnnIndexOptions.java b/src/main/java/org/springframework/data/elasticsearch/annotations/KnnIndexOptions.java
new file mode 100644
index 0000000000..56d871d3b5
--- /dev/null
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/KnnIndexOptions.java
@@ -0,0 +1,40 @@
+/*
+ * 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;
+}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/KnnSimilarity.java b/src/main/java/org/springframework/data/elasticsearch/annotations/KnnSimilarity.java
new file mode 100644
index 0000000000..d03c42a6fd
--- /dev/null
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/KnnSimilarity.java
@@ -0,0 +1,38 @@
+/*
+ * 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;
+ }
+}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/Mapping.java b/src/main/java/org/springframework/data/elasticsearch/annotations/Mapping.java
index 2cdaa29efd..c2d48c3884 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/Mapping.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/Mapping.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014-2023 the original author or authors.
+ * Copyright 2014-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.
@@ -74,7 +74,14 @@
*/
String runtimeFieldsPath() default "";
+ /**
+ * field alias definitions to be written to the index mapping
+ *
+ * @since 5.3
+ */
+ MappingAlias[] aliases() default {};
+
enum Detection {
- DEFAULT, TRUE, FALSE;
+ DEFAULT, TRUE, FALSE
}
}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/MappingAlias.java b/src/main/java/org/springframework/data/elasticsearch/annotations/MappingAlias.java
new file mode 100644
index 0000000000..791659e9d5
--- /dev/null
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/MappingAlias.java
@@ -0,0 +1,45 @@
+/*
+ * 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.Documented;
+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;
+
+/**
+ * Defines a field alias in the index mapping.
+ *
+ * @author Peter-Josef Meisch
+ * @since 5.3
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+@Documented
+@Inherited
+public @interface MappingAlias {
+ /**
+ * the name of the alias.
+ */
+ String name();
+
+ /**
+ * the path of the alias.
+ */
+ String path();
+}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/MultiField.java b/src/main/java/org/springframework/data/elasticsearch/annotations/MultiField.java
index 70f58dca9b..9dff38c1f1 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/MultiField.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/MultiField.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014-2023 the original author or authors.
+ * Copyright 2014-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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/NullValueType.java b/src/main/java/org/springframework/data/elasticsearch/annotations/NullValueType.java
index d3df4bdd94..a131b12a8e 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/NullValueType.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/NullValueType.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020-2023 the original author or authors.
+ * Copyright 2020-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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/Query.java b/src/main/java/org/springframework/data/elasticsearch/annotations/Query.java
index 0d97af4e6f..9f1b755c35 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/Query.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/Query.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013-2023 the original author or authors.
+ * Copyright 2013-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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/SearchTemplateQuery.java b/src/main/java/org/springframework/data/elasticsearch/annotations/SearchTemplateQuery.java
new file mode 100644
index 0000000000..f50675d979
--- /dev/null
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/SearchTemplateQuery.java
@@ -0,0 +1,42 @@
+/*
+ * 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();
+}
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/Setting.java b/src/main/java/org/springframework/data/elasticsearch/annotations/Setting.java
index db4288565d..926154f1f2 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/Setting.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/Setting.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014-2023 the original author or authors.
+ * Copyright 2014-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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/Similarity.java b/src/main/java/org/springframework/data/elasticsearch/annotations/Similarity.java
index dd1ce02a68..46cafd91a2 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/Similarity.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/Similarity.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2023 the original author or authors.
+ * Copyright 2019-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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/SourceFilters.java b/src/main/java/org/springframework/data/elasticsearch/annotations/SourceFilters.java
index 2b488205d2..055ecc616f 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/SourceFilters.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/SourceFilters.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2022-2023 the original author or authors.
+ * 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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/TermVector.java b/src/main/java/org/springframework/data/elasticsearch/annotations/TermVector.java
index e37a0133ff..25de2cbcad 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/TermVector.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/TermVector.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2023 the original author or authors.
+ * Copyright 2019-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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/ValueConverter.java b/src/main/java/org/springframework/data/elasticsearch/annotations/ValueConverter.java
index 2f8485d848..eb848bfed2 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/ValueConverter.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/ValueConverter.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2021-2023 the original author or authors.
+ * 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.
@@ -41,7 +41,7 @@
* Defines the class implementing the {@link PropertyValueConverter} interface. If this is a normal class, it must
* provide a default constructor with no arguments. If this is an enum and thus implementing a singleton by enum it
* must only have one enum value.
- *
+ *
* @return the class to use for conversion
*/
Class extends PropertyValueConverter> value();
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/WriteOnlyProperty.java b/src/main/java/org/springframework/data/elasticsearch/annotations/WriteOnlyProperty.java
index cfc36f4561..7704450e26 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/WriteOnlyProperty.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/WriteOnlyProperty.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2022-2023 the original author or authors.
+ * 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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/WriteTypeHint.java b/src/main/java/org/springframework/data/elasticsearch/annotations/WriteTypeHint.java
index 23fbcfd036..86a844cc18 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/WriteTypeHint.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/WriteTypeHint.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2021-2023 the original author or authors.
+ * 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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/package-info.java b/src/main/java/org/springframework/data/elasticsearch/annotations/package-info.java
index 60fe252678..4b8ccdf64e 100644
--- a/src/main/java/org/springframework/data/elasticsearch/annotations/package-info.java
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/package-info.java
@@ -1,3 +1,2 @@
-@org.springframework.lang.NonNullApi
-@org.springframework.lang.NonNullFields
+@org.jspecify.annotations.NullMarked
package org.springframework.data.elasticsearch.annotations;
diff --git a/src/main/java/org/springframework/data/elasticsearch/aot/ElasticsearchAotPredicates.java b/src/main/java/org/springframework/data/elasticsearch/aot/ElasticsearchAotPredicates.java
index 4d301a5838..c3921b8940 100644
--- a/src/main/java/org/springframework/data/elasticsearch/aot/ElasticsearchAotPredicates.java
+++ b/src/main/java/org/springframework/data/elasticsearch/aot/ElasticsearchAotPredicates.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 the original author or authors.
+ * Copyright 2023-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.
@@ -25,11 +25,11 @@
*/
public class ElasticsearchAotPredicates {
- public static final Predicate IS_REACTIVE_LIBARARY_AVAILABLE = (
+ public static final Predicate IS_REACTIVE_LIBRARY_AVAILABLE = (
lib) -> ReactiveWrappers.isAvailable(lib);
public static boolean isReactorPresent() {
- return IS_REACTIVE_LIBARARY_AVAILABLE.test(ReactiveWrappers.ReactiveLibrary.PROJECT_REACTOR);
+ return IS_REACTIVE_LIBRARY_AVAILABLE.test(ReactiveWrappers.ReactiveLibrary.PROJECT_REACTOR);
}
}
diff --git a/src/main/java/org/springframework/data/elasticsearch/aot/SpringDataElasticsearchRuntimeHints.java b/src/main/java/org/springframework/data/elasticsearch/aot/SpringDataElasticsearchRuntimeHints.java
index 4a1b344a86..100b2ae449 100644
--- a/src/main/java/org/springframework/data/elasticsearch/aot/SpringDataElasticsearchRuntimeHints.java
+++ b/src/main/java/org/springframework/data/elasticsearch/aot/SpringDataElasticsearchRuntimeHints.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 the original author or authors.
+ * Copyright 2023-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.
@@ -19,6 +19,7 @@
import java.util.Arrays;
+import org.jspecify.annotations.Nullable;
import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
@@ -32,7 +33,6 @@
import org.springframework.data.elasticsearch.core.event.ReactiveAfterLoadCallback;
import org.springframework.data.elasticsearch.core.event.ReactiveAfterSaveCallback;
import org.springframework.data.elasticsearch.core.event.ReactiveBeforeConvertCallback;
-import org.springframework.lang.Nullable;
/**
* @author Peter-Josef Meisch
diff --git a/src/main/java/org/springframework/data/elasticsearch/aot/package-info.java b/src/main/java/org/springframework/data/elasticsearch/aot/package-info.java
index 292bf8a1a1..56697c1029 100644
--- a/src/main/java/org/springframework/data/elasticsearch/aot/package-info.java
+++ b/src/main/java/org/springframework/data/elasticsearch/aot/package-info.java
@@ -1,3 +1,2 @@
-@org.springframework.lang.NonNullApi
-@org.springframework.lang.NonNullFields
+@org.jspecify.annotations.NullMarked
package org.springframework.data.elasticsearch.aot;
diff --git a/src/main/java/org/springframework/data/elasticsearch/client/ClientConfiguration.java b/src/main/java/org/springframework/data/elasticsearch/client/ClientConfiguration.java
index f7d469f4f0..f092e2bf6b 100644
--- a/src/main/java/org/springframework/data/elasticsearch/client/ClientConfiguration.java
+++ b/src/main/java/org/springframework/data/elasticsearch/client/ClientConfiguration.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2018-2023 the original author or authors.
+ * Copyright 2018-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.
@@ -25,8 +25,8 @@
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
+import org.jspecify.annotations.Nullable;
import org.springframework.data.elasticsearch.support.HttpHeaders;
-import org.springframework.lang.Nullable;
/**
* Configuration interface exposing common client configuration properties for Elasticsearch clients.
diff --git a/src/main/java/org/springframework/data/elasticsearch/client/ClientConfigurationBuilder.java b/src/main/java/org/springframework/data/elasticsearch/client/ClientConfigurationBuilder.java
index f9521d12c2..71af992127 100644
--- a/src/main/java/org/springframework/data/elasticsearch/client/ClientConfigurationBuilder.java
+++ b/src/main/java/org/springframework/data/elasticsearch/client/ClientConfigurationBuilder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2018-2023 the original author or authors.
+ * Copyright 2018-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.
@@ -25,11 +25,11 @@
import javax.net.ssl.HostnameVerifier;
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.MaybeSecureClientConfigurationBuilder;
import org.springframework.data.elasticsearch.client.ClientConfiguration.TerminalClientConfigurationBuilder;
import org.springframework.data.elasticsearch.support.HttpHeaders;
-import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
diff --git a/src/main/java/org/springframework/data/elasticsearch/client/DefaultClientConfiguration.java b/src/main/java/org/springframework/data/elasticsearch/client/DefaultClientConfiguration.java
index f41292fa8d..ea097bbb59 100644
--- a/src/main/java/org/springframework/data/elasticsearch/client/DefaultClientConfiguration.java
+++ b/src/main/java/org/springframework/data/elasticsearch/client/DefaultClientConfiguration.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2018-2023 the original author or authors.
+ * Copyright 2018-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.
@@ -24,9 +24,8 @@
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
-import org.elasticsearch.client.RestClientBuilder.HttpClientConfigCallback;
+import org.jspecify.annotations.Nullable;
import org.springframework.data.elasticsearch.support.HttpHeaders;
-import org.springframework.lang.Nullable;
/**
* Default {@link ClientConfiguration} implementation.
diff --git a/src/main/java/org/springframework/data/elasticsearch/client/ElasticsearchHost.java b/src/main/java/org/springframework/data/elasticsearch/client/ElasticsearchHost.java
index a6406dfad2..014acb6328 100644
--- a/src/main/java/org/springframework/data/elasticsearch/client/ElasticsearchHost.java
+++ b/src/main/java/org/springframework/data/elasticsearch/client/ElasticsearchHost.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2018-2023 the original author or authors.
+ * Copyright 2018-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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/client/InetSocketAddressParser.java b/src/main/java/org/springframework/data/elasticsearch/client/InetSocketAddressParser.java
index a8dc5e13f8..33f71a49ed 100644
--- a/src/main/java/org/springframework/data/elasticsearch/client/InetSocketAddressParser.java
+++ b/src/main/java/org/springframework/data/elasticsearch/client/InetSocketAddressParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2018-2023 the original author or authors.
+ * Copyright 2018-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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/client/NoReachableHostException.java b/src/main/java/org/springframework/data/elasticsearch/client/NoReachableHostException.java
index 4a28d664d0..b8a560db63 100644
--- a/src/main/java/org/springframework/data/elasticsearch/client/NoReachableHostException.java
+++ b/src/main/java/org/springframework/data/elasticsearch/client/NoReachableHostException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2018-2023 the original author or authors.
+ * Copyright 2018-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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/client/UnsupportedBackendOperation.java b/src/main/java/org/springframework/data/elasticsearch/client/UnsupportedBackendOperation.java
index 252f5524ec..0264b95c00 100644
--- a/src/main/java/org/springframework/data/elasticsearch/client/UnsupportedBackendOperation.java
+++ b/src/main/java/org/springframework/data/elasticsearch/client/UnsupportedBackendOperation.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2022-2023 the original author or authors.
+ * 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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/client/UnsupportedClientOperationException.java b/src/main/java/org/springframework/data/elasticsearch/client/UnsupportedClientOperationException.java
index bd5a539c51..322646bc66 100644
--- a/src/main/java/org/springframework/data/elasticsearch/client/UnsupportedClientOperationException.java
+++ b/src/main/java/org/springframework/data/elasticsearch/client/UnsupportedClientOperationException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2022-2023 the original author or authors.
+ * 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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/client/elc/AbstractQueryProcessor.java b/src/main/java/org/springframework/data/elasticsearch/client/elc/AbstractQueryProcessor.java
new file mode 100644
index 0000000000..ff0e1bd3a0
--- /dev/null
+++ b/src/main/java/org/springframework/data/elasticsearch/client/elc/AbstractQueryProcessor.java
@@ -0,0 +1,70 @@
+/*
+ * 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 java.util.function.Consumer;
+
+import org.jspecify.annotations.Nullable;
+import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
+import org.springframework.data.elasticsearch.core.query.Query;
+import org.springframework.data.elasticsearch.core.query.StringQuery;
+
+/**
+ * An abstract class that serves as a base for query processors. It provides a common interface and basic functionality
+ * for query processing.
+ *
+ * @author Aouichaoui Youssef
+ * @since 5.3
+ */
+public abstract class AbstractQueryProcessor {
+
+ /**
+ * Convert a spring-data-elasticsearch {@literal query} to an Elasticsearch {@literal query}.
+ *
+ * @param query spring-data-elasticsearch {@literal query}.
+ * @param queryConverter correct mapped field names and the values to the converted values.
+ * @return an Elasticsearch {@literal query}.
+ */
+
+ static co.elastic.clients.elasticsearch._types.query_dsl.@Nullable Query getEsQuery(@Nullable Query query,
+ @Nullable Consumer queryConverter) {
+ if (query == null) {
+ return null;
+ }
+
+ if (queryConverter != null) {
+ queryConverter.accept(query);
+ }
+
+ co.elastic.clients.elasticsearch._types.query_dsl.Query esQuery = null;
+
+ if (query instanceof CriteriaQuery criteriaQuery) {
+ esQuery = CriteriaQueryProcessor.createQuery(criteriaQuery.getCriteria());
+ } else if (query instanceof StringQuery stringQuery) {
+ esQuery = Queries.wrapperQueryAsQuery(stringQuery.getSource());
+ } else if (query instanceof NativeQuery nativeQuery) {
+ if (nativeQuery.getQuery() != null) {
+ esQuery = nativeQuery.getQuery();
+ } else if (nativeQuery.getSpringDataQuery() != null) {
+ esQuery = getEsQuery(nativeQuery.getSpringDataQuery(), queryConverter);
+ }
+ } else {
+ throw new IllegalArgumentException("unhandled Query implementation " + query.getClass().getName());
+ }
+
+ return esQuery;
+ }
+}
diff --git a/src/main/java/org/springframework/data/elasticsearch/client/elc/Aggregation.java b/src/main/java/org/springframework/data/elasticsearch/client/elc/Aggregation.java
index 7e66d9c05c..23e2b6ae47 100644
--- a/src/main/java/org/springframework/data/elasticsearch/client/elc/Aggregation.java
+++ b/src/main/java/org/springframework/data/elasticsearch/client/elc/Aggregation.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2022-2023 the original author or authors.
+ * 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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/client/elc/AutoCloseableElasticsearchClient.java b/src/main/java/org/springframework/data/elasticsearch/client/elc/AutoCloseableElasticsearchClient.java
index d559d4f7c7..3ce661e1fd 100644
--- a/src/main/java/org/springframework/data/elasticsearch/client/elc/AutoCloseableElasticsearchClient.java
+++ b/src/main/java/org/springframework/data/elasticsearch/client/elc/AutoCloseableElasticsearchClient.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2021-2023 the original author or authors.
+ * 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.
@@ -16,9 +16,10 @@
package org.springframework.data.elasticsearch.client.elc;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
-import co.elastic.clients.elasticsearch.cluster.ElasticsearchClusterClient;
import co.elastic.clients.transport.ElasticsearchTransport;
+import java.io.IOException;
+
import org.elasticsearch.client.RestClient;
import org.springframework.util.Assert;
@@ -37,12 +38,10 @@ public AutoCloseableElasticsearchClient(ElasticsearchTransport transport) {
}
@Override
- public void close() throws Exception {
- transport.close();
- }
-
- @Override
- public ElasticsearchClusterClient cluster() {
- return super.cluster();
+ public void close() throws IOException {
+ // since Elasticsearch 8.16 the ElasticsearchClient implements (through ApiClient) the Closeable interface and
+ // 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();
}
}
diff --git a/src/main/java/org/springframework/data/elasticsearch/client/elc/ChildTemplate.java b/src/main/java/org/springframework/data/elasticsearch/client/elc/ChildTemplate.java
index d5c1bcf4c1..4d3ebf5bd7 100644
--- a/src/main/java/org/springframework/data/elasticsearch/client/elc/ChildTemplate.java
+++ b/src/main/java/org/springframework/data/elasticsearch/client/elc/ChildTemplate.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2021-2023 the original author or authors.
+ * 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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/client/elc/ClusterTemplate.java b/src/main/java/org/springframework/data/elasticsearch/client/elc/ClusterTemplate.java
index 0454b4a452..fcba35fa7d 100644
--- a/src/main/java/org/springframework/data/elasticsearch/client/elc/ClusterTemplate.java
+++ b/src/main/java/org/springframework/data/elasticsearch/client/elc/ClusterTemplate.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2021-2023 the original author or authors.
+ * 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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/client/elc/CriteriaFilterProcessor.java b/src/main/java/org/springframework/data/elasticsearch/client/elc/CriteriaFilterProcessor.java
index 9b52c375e0..702d8501b3 100644
--- a/src/main/java/org/springframework/data/elasticsearch/client/elc/CriteriaFilterProcessor.java
+++ b/src/main/java/org/springframework/data/elasticsearch/client/elc/CriteriaFilterProcessor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2021-2023 the original author or authors.
+ * 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.
@@ -39,6 +39,7 @@
import org.springframework.data.elasticsearch.core.geo.GeoJson;
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
import org.springframework.data.elasticsearch.core.query.Criteria;
+import org.springframework.data.elasticsearch.utils.geohash.Geohash;
import org.springframework.data.geo.Box;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.Metrics;
@@ -50,6 +51,7 @@
* filter.
*
* @author Peter-Josef Meisch
+ * @author Junghoon Ban
* @since 4.4
*/
class CriteriaFilterProcessor {
@@ -68,10 +70,17 @@ public static Optional createQuery(Criteria criteria) {
for (Criteria chainedCriteria : criteria.getCriteriaChain()) {
if (chainedCriteria.isOr()) {
- BoolQuery.Builder boolQueryBuilder = QueryBuilders.bool();
- queriesForEntries(chainedCriteria).forEach(boolQueryBuilder::should);
- filterQueries.add(new Query(boolQueryBuilder.build()));
+ Collection extends Query> queriesForEntries = queriesForEntries(chainedCriteria);
+
+ if (!queriesForEntries.isEmpty()) {
+ BoolQuery.Builder boolQueryBuilder = QueryBuilders.bool();
+ queriesForEntries.forEach(boolQueryBuilder::should);
+ filterQueries.add(new Query(boolQueryBuilder.build()));
+ }
} else if (chainedCriteria.isNegating()) {
+
+ Assert.notNull(criteria.getField(), "criteria must have a field");
+
Collection extends Query> negatingFilters = buildNegatingFilter(criteria.getField().getName(),
criteria.getFilterCriteriaEntries());
filterQueries.addAll(negatingFilters);
@@ -115,6 +124,7 @@ private static Collection extends Query> buildNegatingFilter(String fieldName,
private static Collection extends Query> queriesForEntries(Criteria criteria) {
Assert.notNull(criteria.getField(), "criteria must have a field");
+
String fieldName = criteria.getField().getName();
Assert.notNull(fieldName, "Unknown field");
@@ -169,17 +179,17 @@ private static ObjectBuilder withinQuery(String fieldName, Obj
Assert.isTrue(values[1] instanceof String || values[1] instanceof Distance,
"Second element of a geo distance filter must be a text or a Distance");
- String dist = (values[1] instanceof Distance) ? extractDistanceString((Distance) values[1]) : (String) values[1];
+ String dist = (values[1] instanceof Distance distance) ? extractDistanceString(distance) : (String) values[1];
return QueryBuilders.geoDistance() //
.field(fieldName) //
.distance(dist) //
.distanceType(GeoDistanceType.Plane) //
.location(location -> {
- if (values[0]instanceof GeoPoint loc) {
+ if (values[0] instanceof GeoPoint loc) {
location.latlon(latlon -> latlon.lat(loc.getLat()).lon(loc.getLon()));
- } else if (values[0] instanceof Point) {
- GeoPoint loc = GeoPoint.fromPoint((Point) values[0]);
+ } else if (values[0] instanceof Point point) {
+ GeoPoint loc = GeoPoint.fromPoint(point);
location.latlon(latlon -> latlon.lat(loc.getLat()).lon(loc.getLon()));
} else {
String loc = (String) values[0];
@@ -220,8 +230,8 @@ private static void oneParameterBBox(GeoBoundingBoxQuery.Builder queryBuilder, O
"single-element of boundedBy filter must be type of GeoBox or Box");
GeoBox geoBBox;
- if (value instanceof Box) {
- geoBBox = GeoBox.fromBox((Box) value);
+ if (value instanceof Box box) {
+ geoBBox = GeoBox.fromBox(box);
} else {
geoBBox = (GeoBox) value;
}
@@ -244,7 +254,7 @@ private static void twoParameterBBox(GeoBoundingBoxQuery.Builder queryBuilder, O
Assert.isTrue(allElementsAreOfType(values, GeoPoint.class) || allElementsAreOfType(values, String.class),
" both elements of boundedBy filter must be type of GeoPoint or text(format lat,lon or geohash)");
- if (values[0]instanceof GeoPoint topLeft) {
+ if (values[0] instanceof GeoPoint topLeft) {
GeoPoint bottomRight = (GeoPoint) values[1];
queryBuilder.boundingBox(bb -> bb //
.tlbr(tlbr -> tlbr //
@@ -266,7 +276,10 @@ private static void twoParameterBBox(GeoBoundingBoxQuery.Builder queryBuilder, O
.tlbr(tlbr -> tlbr //
.topLeft(glb -> {
if (isGeoHash) {
- glb.geohash(gh -> gh.geohash(topLeft));
+ // although the builder in 8.13.2 supports geohash, the server throws an error, so we convert to a
+ // lat,lon string here
+ glb.text(Geohash.toLatLon(topLeft));
+ // glb.geohash(gh -> gh.geohash(topLeft));
} else {
glb.text(topLeft);
}
@@ -274,7 +287,8 @@ private static void twoParameterBBox(GeoBoundingBoxQuery.Builder queryBuilder, O
}) //
.bottomRight(glb -> {
if (isGeoHash) {
- glb.geohash(gh -> gh.geohash(bottomRight));
+ glb.text(Geohash.toLatLon(bottomRight));
+ // glb.geohash(gh -> gh.geohash(bottomRight));
} else {
glb.text(bottomRight);
}
diff --git a/src/main/java/org/springframework/data/elasticsearch/client/elc/CriteriaQueryException.java b/src/main/java/org/springframework/data/elasticsearch/client/elc/CriteriaQueryException.java
index cdb4e98e4c..cb6cccf973 100644
--- a/src/main/java/org/springframework/data/elasticsearch/client/elc/CriteriaQueryException.java
+++ b/src/main/java/org/springframework/data/elasticsearch/client/elc/CriteriaQueryException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2021-2023 the original author or authors.
+ * 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.
diff --git a/src/main/java/org/springframework/data/elasticsearch/client/elc/CriteriaQueryProcessor.java b/src/main/java/org/springframework/data/elasticsearch/client/elc/CriteriaQueryProcessor.java
index 5e01e2f81a..1c9c9ef53a 100644
--- a/src/main/java/org/springframework/data/elasticsearch/client/elc/CriteriaQueryProcessor.java
+++ b/src/main/java/org/springframework/data/elasticsearch/client/elc/CriteriaQueryProcessor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2021-2023 the original author or authors.
+ * 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.
@@ -16,22 +16,28 @@
package org.springframework.data.elasticsearch.client.elc;
import static org.springframework.data.elasticsearch.client.elc.Queries.*;
+import static org.springframework.data.elasticsearch.client.elc.TypeUtils.*;
import static org.springframework.util.StringUtils.*;
import co.elastic.clients.elasticsearch._types.FieldValue;
import co.elastic.clients.elasticsearch._types.query_dsl.ChildScoreMode;
import co.elastic.clients.elasticsearch._types.query_dsl.Operator;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
+import co.elastic.clients.elasticsearch.core.search.InnerHits;
import co.elastic.clients.json.JsonData;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import java.util.Objects;
+import org.jspecify.annotations.Nullable;
import org.springframework.data.elasticsearch.annotations.FieldType;
import org.springframework.data.elasticsearch.core.query.Criteria;
import org.springframework.data.elasticsearch.core.query.Field;
-import org.springframework.lang.Nullable;
+import org.springframework.data.elasticsearch.core.query.HasChildQuery;
+import org.springframework.data.elasticsearch.core.query.HasParentQuery;
+import org.springframework.data.elasticsearch.core.query.InnerHitsQuery;
import org.springframework.util.Assert;
/**
@@ -42,7 +48,7 @@
* @author Ezequiel Antúnez Camacho
* @since 4.4
*/
-class CriteriaQueryProcessor {
+class CriteriaQueryProcessor extends AbstractQueryProcessor {
/**
* creates a query from the criteria
@@ -110,11 +116,18 @@ public static Query createQuery(Criteria criteria) {
}
}
+ var filterQuery = CriteriaFilterProcessor.createQuery(criteria);
if (shouldQueries.isEmpty() && mustNotQueries.isEmpty() && mustQueries.isEmpty()) {
- return null;
+
+ if (filterQuery.isEmpty()) {
+ return null;
+ }
+
+ // we need something to add the filter to
+ mustQueries.add(Query.of(qb -> qb.matchAll(m -> m)));
}
- Query query = new Query.Builder().bool(boolQueryBuilder -> {
+ return new Query.Builder().bool(boolQueryBuilder -> {
if (!shouldQueries.isEmpty()) {
boolQueryBuilder.should(shouldQueries);
@@ -128,10 +141,10 @@ public static Query createQuery(Criteria criteria) {
boolQueryBuilder.must(mustQueries);
}
+ filterQuery.ifPresent(boolQueryBuilder::filter);
+
return boolQueryBuilder;
}).build();
-
- return query;
}
@Nullable
@@ -174,6 +187,12 @@ private static Query queryForEntries(Criteria criteria) {
.scoreMode(ChildScoreMode.Avg));
}
+ if (criteria.isNegating() && criteria.isOr()) {
+ final Query query = queryBuilder.build();
+ queryBuilder = new Query.Builder();
+ queryBuilder.bool(mnqb -> mnqb.mustNot(query));
+ }
+
return queryBuilder.build();
}
@@ -227,51 +246,57 @@ private static Query.Builder queryFor(Criteria.CriteriaEntry entry, Field field,
queryBuilder.queryString(queryStringQuery(fieldName, '*' + searchText, true, boost));
break;
case EXPRESSION:
- queryBuilder.queryString(queryStringQuery(fieldName, value.toString(), boost));
+ queryBuilder.queryString(queryStringQuery(fieldName, Objects.requireNonNull(value).toString(), boost));
break;
case LESS:
- queryBuilder //
- .range(rb -> rb //
- .field(fieldName) //
- .lt(JsonData.of(value)) //
- .boost(boost)); //
+ queryBuilder
+ .range(rb -> rb
+ .untyped(ut -> ut
+ .field(fieldName)
+ .lt(JsonData.of(value))
+ .boost(boost)));
break;
case LESS_EQUAL:
- queryBuilder //
- .range(rb -> rb //
- .field(fieldName) //
- .lte(JsonData.of(value)) //
- .boost(boost)); //
+ queryBuilder
+ .range(rb -> rb
+ .untyped(ut -> ut
+ .field(fieldName)
+ .lte(JsonData.of(value))
+ .boost(boost)));
break;
case GREATER:
- queryBuilder //
- .range(rb -> rb //
- .field(fieldName) //
- .gt(JsonData.of(value)) //
- .boost(boost)); //
+ queryBuilder
+ .range(rb -> rb
+ .untyped(ut -> ut
+ .field(fieldName)
+ .gt(JsonData.of(value))
+ .boost(boost)));
break;
case GREATER_EQUAL:
- queryBuilder //
- .range(rb -> rb //
- .field(fieldName) //
- .gte(JsonData.of(value)) //
- .boost(boost)); //
+ queryBuilder
+ .range(rb -> rb
+ .untyped(ut -> ut
+ .field(fieldName)
+ .gte(JsonData.of(value))
+ .boost(boost)));
break;
case BETWEEN:
Object[] ranges = (Object[]) value;
- queryBuilder //
- .range(rb -> {
- rb.field(fieldName);
- if (ranges[0] != null) {
- rb.gte(JsonData.of(ranges[0]));
- }
-
- if (ranges[1] != null) {
- rb.lte(JsonData.of(ranges[1]));
- }
- rb.boost(boost); //
- return rb;
- }); //
+ Assert.notNull(value, "value for a between condition must not be null");
+ queryBuilder
+ .range(rb -> rb
+ .untyped(ut -> {
+ ut.field(fieldName);
+ if (ranges[0] != null) {
+ ut.gte(JsonData.of(ranges[0]));
+ }
+
+ if (ranges[1] != null) {
+ ut.lte(JsonData.of(ranges[1]));
+ }
+ ut.boost(boost); //
+ return ut;
+ }));
break;
case FUZZY:
@@ -282,10 +307,10 @@ private static Query.Builder queryFor(Criteria.CriteriaEntry entry, Field field,
.boost(boost)); //
break;
case MATCHES:
- queryBuilder.match(matchQuery(fieldName, value.toString(), Operator.Or, boost));
+ queryBuilder.match(matchQuery(fieldName, Objects.requireNonNull(value).toString(), Operator.Or, boost));
break;
case MATCHES_ALL:
- queryBuilder.match(matchQuery(fieldName, value.toString(), Operator.And, boost));
+ queryBuilder.match(matchQuery(fieldName, Objects.requireNonNull(value).toString(), Operator.And, boost));
break;
case IN:
@@ -334,9 +359,35 @@ private static Query.Builder queryFor(Criteria.CriteriaEntry entry, Field field,
queryBuilder //
.regexp(rb -> rb //
.field(fieldName) //
- .value(value.toString()) //
+ .value(Objects.requireNonNull(value).toString()) //
.boost(boost)); //
break;
+ case HAS_CHILD:
+ if (value instanceof HasChildQuery query) {
+ queryBuilder.hasChild(hcb -> hcb
+ .type(query.getType())
+ .query(getEsQuery(query.getQuery(), null))
+ .innerHits(getInnerHits(query.getInnerHitsQuery()))
+ .ignoreUnmapped(query.getIgnoreUnmapped())
+ .minChildren(query.getMinChildren())
+ .maxChildren(query.getMaxChildren())
+ .scoreMode(scoreMode(query.getScoreMode())));
+ } else {
+ throw new CriteriaQueryException("value for " + fieldName + " is not a has_child query");
+ }
+ break;
+ case HAS_PARENT:
+ if (value instanceof HasParentQuery query) {
+ queryBuilder.hasParent(hpb -> hpb
+ .parentType(query.getParentType())
+ .query(getEsQuery(query.getQuery(), null))
+ .innerHits(getInnerHits(query.getInnerHitsQuery()))
+ .ignoreUnmapped(query.getIgnoreUnmapped())
+ .score(query.getScore()));
+ } else {
+ throw new CriteriaQueryException("value for " + fieldName + " is not a has_parent query");
+ }
+ break;
default:
throw new CriteriaQueryException("Could not build query for " + entry);
}
@@ -359,7 +410,7 @@ private static String orQueryString(Iterable> iterable) {
if (item != null) {
- if (sb.length() > 0) {
+ if (!sb.isEmpty()) {
sb.append(' ');
}
sb.append('"');
@@ -391,4 +442,19 @@ public static String escape(String s) {
return sb.toString();
}
+ /**
+ * Convert a spring-data-elasticsearch {@literal inner_hits} to an Elasticsearch {@literal inner_hits} query.
+ *
+ * @param query spring-data-elasticsearch {@literal inner_hits}.
+ * @return an Elasticsearch {@literal inner_hits} query.
+ */
+ @Nullable
+ private static InnerHits getInnerHits(@Nullable InnerHitsQuery query) {
+ if (query == null) {
+ return null;
+ }
+
+ return InnerHits.of(iqb -> iqb.from(query.getFrom()).size(query.getSize()).name(query.getName()));
+ }
+
}
diff --git a/src/main/java/org/springframework/data/elasticsearch/client/elc/DocumentAdapters.java b/src/main/java/org/springframework/data/elasticsearch/client/elc/DocumentAdapters.java
index 78ae3b0d52..53e8cefa7b 100644
--- a/src/main/java/org/springframework/data/elasticsearch/client/elc/DocumentAdapters.java
+++ b/src/main/java/org/springframework/data/elasticsearch/client/elc/DocumentAdapters.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2021-2023 the original author or authors.
+ * 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.
@@ -24,16 +24,9 @@
import co.elastic.clients.elasticsearch.core.search.NestedIdentity;
import co.elastic.clients.json.JsonData;
import co.elastic.clients.json.JsonpMapper;
-
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-
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;
@@ -41,199 +34,208 @@
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;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
/**
* Utility class to adapt different Elasticsearch responses to a
* {@link org.springframework.data.elasticsearch.core.document.Document}
*
* @author Peter-Josef Meisch
+ * @author Haibo Liu
+ * @author Mohamed El Harrougui
* @since 4.4
*/
final class DocumentAdapters {
- private static final Log LOGGER = LogFactory.getLog(DocumentAdapters.class);
-
- private DocumentAdapters() {}
-
- /**
- * Creates a {@link SearchDocument} from a {@link Hit} returned by the Elasticsearch client.
- *
- * @param hit the hit object
- * @param jsonpMapper to map JsonData objects
- * @return the created {@link SearchDocument}
- */
- public static SearchDocument from(Hit> hit, JsonpMapper jsonpMapper) {
-
- Assert.notNull(hit, "hit must not be null");
-
- Map> highlightFields = hit.highlight();
-
- Map innerHits = new LinkedHashMap<>();
- hit.innerHits().forEach((name, innerHitsResult) -> {
- // noinspection ReturnOfNull
- innerHits.put(name, SearchDocumentResponseBuilder.from(innerHitsResult.hits(), null, null, null, null,
- searchDocument -> null, jsonpMapper));
- });
-
- NestedMetaData nestedMetaData = from(hit.nested());
-
- Explanation explanation = from(hit.explanation());
-
- List matchedQueries = hit.matchedQueries();
-
- Function