Compare commits
165 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d2fd6b05b9 | |||
| 0f725fb9be | |||
| dab6e1708f | |||
| 4c60bb04fd | |||
| c5cf3b62d4 | |||
| 84c18d1808 | |||
| 2772c5f3d5 | |||
| 144d388203 | |||
| 5d6004f450 | |||
| 71383536d4 | |||
| b10bc3d693 | |||
| a34b363732 | |||
| e110fe12a2 | |||
| a707b0bc47 | |||
| ec563e02f4 | |||
| f32cbb81f8 | |||
| 7b782c7c62 | |||
| 6d0560751d | |||
| c68f607374 | |||
| fb9c70c51b | |||
| 0c4a641163 | |||
| d7abbc719f | |||
| bd99c90de1 | |||
| b5ad00bccf | |||
| 01f39d6807 | |||
| 19970bacc6 | |||
| d7aed4a8cc | |||
| b708fc10db | |||
| 33c253b071 | |||
| 6bb18b9a0a | |||
| e5252da066 | |||
| a49b1b52a3 | |||
| 7982ff7986 | |||
| 1c9441a1b4 | |||
| e0cc849952 | |||
| 1b50013fc2 | |||
| 5418ef9e03 | |||
| 8d81e499bc | |||
| e457b1678b | |||
| 6c34dc53f3 | |||
| 85b6acebb2 | |||
| 00155c2b31 | |||
| d0020be57d | |||
| 20a6140fe9 | |||
| cdb48c8226 | |||
| 493476567a | |||
| a7c148653f | |||
| 3092db9e7d | |||
| d8917f1cb1 | |||
| cc533b25f1 | |||
| c5231d879d | |||
| 950ca0fc2a | |||
| 95a86f558b | |||
| 8117e5a174 | |||
| 3a9a959918 | |||
| a179dd0643 | |||
| 310ea07c6f | |||
| 34a277cd7d | |||
| 878dc029ec | |||
| c931812c6a | |||
| c514e020b8 | |||
| 31a4ad715f | |||
| 03efe1b910 | |||
| 9d5d2efb40 | |||
| b7266961d9 | |||
| d96cd02572 | |||
| ceb0225850 | |||
| 5c59f73e00 | |||
| 44b1c9e848 | |||
| 1770f98a74 | |||
| bad0a80313 | |||
| 92dd6e8599 | |||
| c793be8ab4 | |||
| 07ae79f9ce | |||
| 47c84b84af | |||
| 5ba1e5dc77 | |||
| 5ddcd55942 | |||
| be4a77ad21 | |||
| 7fa3cb74a1 | |||
| ba9edf8ec8 | |||
| e4a39ae285 | |||
| 7392222793 | |||
| 2b76762007 | |||
| baec1f1419 | |||
| d693c4f81b | |||
| 94a40a7a75 | |||
| dc5bf5a606 | |||
| 1d89054d12 | |||
| 106b513d11 | |||
| a16782ec73 | |||
| 2d5f8e8219 | |||
| ad66510e9e | |||
| e1537087bf | |||
| 8eecbe6a32 | |||
| c79fe303db | |||
| b507abe327 | |||
| bec3beb1eb | |||
| 1d709f6c55 | |||
| 0beca99912 | |||
| 6d51e67948 | |||
| 0a51dbab01 | |||
| c96423d5ba | |||
| 496b8d62a4 | |||
| d2b3ba94f6 | |||
| 33973ec839 | |||
| 7f178238db | |||
| aa27bbec27 | |||
| bd6b6e92f4 | |||
| 87eb36a995 | |||
| 41cab97f78 | |||
| f4d2ff7a99 | |||
| 9472161808 | |||
| debf04b499 | |||
| 205d74b6db | |||
| 7a8a9a15f1 | |||
| c965862e82 | |||
| 6af099ea34 | |||
| 96185f94ef | |||
| ca85729ea4 | |||
| f9d01df6f7 | |||
| d16951eace | |||
| e1730ea7cc | |||
| 0f5497338a | |||
| e9ecebd9ef | |||
| 9a3f5dc4f5 | |||
| 6390aaa739 | |||
| b391a4e844 | |||
| 0a1e20579e | |||
| 1f75016977 | |||
| 3878540394 | |||
| 957fe0531f | |||
| 460b4ac0f5 | |||
| e1a2412651 | |||
| c6041fb659 | |||
| 8f745b19d1 | |||
| c16024d779 | |||
| af1d2dd641 | |||
| 06ede8d7ae | |||
| 1554c3c94f | |||
| 260dadd4d6 | |||
| b78588eec5 | |||
| b0c97ccf27 | |||
| 433d52981e | |||
| 6350514e7e | |||
| 02bd3e60f8 | |||
| 21a1fbca0f | |||
| 434de11f3d | |||
| 96b38652ab | |||
| d0ed80dfde | |||
| 362126e72d | |||
| 0e419133a2 | |||
| 8a3df63493 | |||
| fb9ccf7b44 | |||
| 1d6a1b0f2f | |||
| 72e8f41de5 | |||
| 4edf9bee41 | |||
| 8613eb26e0 | |||
| 415d5e0385 | |||
| 3833975a1a | |||
| 05ca90ecc1 | |||
| 7af76338fc | |||
| 1f4479092a | |||
| ddd795a3d3 | |||
| 612cc50b88 | |||
| d05b9f878a |
+2
-2
@@ -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
|
||||
|
||||
+3
-8
@@ -1,13 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extensions>
|
||||
<extension>
|
||||
<groupId>com.gradle</groupId>
|
||||
<artifactId>gradle-enterprise-maven-extension</artifactId>
|
||||
<version>1.19.2</version>
|
||||
</extension>
|
||||
<extension>
|
||||
<groupId>com.gradle</groupId>
|
||||
<artifactId>common-custom-user-data-maven-extension</artifactId>
|
||||
<version>1.12.4</version>
|
||||
<groupId>io.spring.develocity.conventions</groupId>
|
||||
<artifactId>develocity-conventions-maven-extension</artifactId>
|
||||
<version>0.0.22</version>
|
||||
</extension>
|
||||
</extensions>
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||
<gradleEnterprise
|
||||
xmlns="https://www.gradle.com/gradle-enterprise-maven" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="https://www.gradle.com/gradle-enterprise-maven https://www.gradle.com/schema/gradle-enterprise-maven.xsd">
|
||||
<server>
|
||||
<url>https://ge.spring.io</url>
|
||||
</server>
|
||||
<buildScan>
|
||||
<backgroundBuildScanUpload>false</backgroundBuildScanUpload>
|
||||
<captureGoalInputFiles>true</captureGoalInputFiles>
|
||||
<publishIfAuthenticated>true</publishIfAuthenticated>
|
||||
<obfuscation>
|
||||
<ipAddresses>#{{'0.0.0.0'}}</ipAddresses>
|
||||
</obfuscation>
|
||||
</buildScan>
|
||||
<buildCache>
|
||||
<local>
|
||||
<enabled>true</enabled>
|
||||
</local>
|
||||
<remote>
|
||||
<server>
|
||||
<credentials>
|
||||
<username>${env.GRADLE_ENTERPRISE_CACHE_USERNAME}</username>
|
||||
<password>${env.GRADLE_ENTERPRISE_CACHE_PASSWORD}</password>
|
||||
</credentials>
|
||||
</server>
|
||||
<enabled>true</enabled>
|
||||
<storeEnabled>#{env['GRADLE_ENTERPRISE_CACHE_USERNAME'] != null and env['GRADLE_ENTERPRISE_CACHE_PASSWORD'] != null}</storeEnabled>
|
||||
</remote>
|
||||
</buildCache>
|
||||
</gradleEnterprise>
|
||||
@@ -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
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
#Thu Dec 14 08:34:15 CET 2023
|
||||
#Thu Nov 07 09:49:32 CET 2024
|
||||
wrapperUrl=https\://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
|
||||
distributionUrl=https\://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip
|
||||
distributionUrl=https\://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip
|
||||
|
||||
Vendored
+25
-23
@@ -9,7 +9,7 @@ pipeline {
|
||||
|
||||
triggers {
|
||||
pollSCM 'H/10 * * * *'
|
||||
upstream(upstreamProjects: "spring-data-commons/3.2.x", threshold: hudson.model.Result.SUCCESS)
|
||||
upstream(upstreamProjects: "spring-data-commons/3.3.x", threshold: hudson.model.Result.SUCCESS)
|
||||
}
|
||||
|
||||
options {
|
||||
@@ -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 JENKINS_USER_NAME=${p['jenkins.user.name']} ci/verify.sh"
|
||||
sh "JENKINS_USER_NAME=${p['jenkins.user.name']} 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 JENKINS_USER_NAME=${p['jenkins.user.name']} ci/verify.sh"
|
||||
sh "JENKINS_USER_NAME=${p['jenkins.user.name']} 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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -92,24 +94,24 @@ pipeline {
|
||||
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=' + "${p['jenkins.user.name']}" + ' -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=${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=${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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-5
@@ -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 Data Elasticsearch"]
|
||||
= 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 Data Elasticsearch"]
|
||||
|
||||
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.
|
||||
|
||||
@@ -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
|
||||
|
||||
+1
-6
@@ -2,12 +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=${JENKINS_USER} -Duser.home=/tmp/jenkins-home" \
|
||||
./mvnw -s settings.xml clean -Dscan=false -Dmaven.repo.local=/tmp/jenkins-home/.m2/spring-data-elasticsearch
|
||||
./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
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# Java versions
|
||||
java.main.tag=17.0.9_9-jdk-focal
|
||||
java.next.tag=21.0.1_12-jdk-jammy
|
||||
java.main.tag=17.0.15_6-jdk-focal
|
||||
java.next.tag=22.0.2_9-jdk-jammy
|
||||
|
||||
# Docker container images - standard
|
||||
docker.java.main.image=harbor-repo.vmware.com/dockerhub-proxy-cache/library/eclipse-temurin:${java.main.tag}
|
||||
docker.java.next.image=harbor-repo.vmware.com/dockerhub-proxy-cache/library/eclipse-temurin:${java.next.tag}
|
||||
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
|
||||
@@ -14,6 +14,7 @@ docker.mongodb.7.0.version=7.0.2
|
||||
|
||||
# Supported versions of Redis
|
||||
docker.redis.6.version=6.2.13
|
||||
docker.redis.7.version=7.2.4
|
||||
|
||||
# Supported versions of Cassandra
|
||||
docker.cassandra.3.version=3.11.16
|
||||
@@ -25,9 +26,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
|
||||
artifactory.url=https://repo.spring.io
|
||||
artifactory.repository.snapshot=libs-snapshot-local
|
||||
develocity.cache.credentials=gradle_enterprise_cache_user
|
||||
develocity.access-key=gradle_enterprise_secret_access_key
|
||||
jenkins.user.name=spring-builds+jenkins
|
||||
|
||||
+1
-8
@@ -3,15 +3,8 @@
|
||||
set -euo pipefail
|
||||
|
||||
mkdir -p /tmp/jenkins-home/.m2/spring-data-elasticsearch
|
||||
chown -R 1001:1001 .
|
||||
|
||||
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=${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
|
||||
-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
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -5,12 +5,12 @@
|
||||
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-elasticsearch</artifactId>
|
||||
<version>5.2.2</version>
|
||||
<version>5.3.13</version>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.data.build</groupId>
|
||||
<artifactId>spring-data-parent</artifactId>
|
||||
<version>3.2.2</version>
|
||||
<version>3.3.13</version>
|
||||
</parent>
|
||||
|
||||
<name>Spring Data Elasticsearch</name>
|
||||
@@ -18,12 +18,11 @@
|
||||
<url>https://github.com/spring-projects/spring-data-elasticsearch</url>
|
||||
|
||||
<properties>
|
||||
<springdata.commons>3.2.2</springdata.commons>
|
||||
<springdata.commons>3.3.13</springdata.commons>
|
||||
|
||||
<!-- version of the ElasticsearchClient -->
|
||||
<elasticsearch-java>8.11.3</elasticsearch-java>
|
||||
<elasticsearch-java>8.13.4</elasticsearch-java>
|
||||
|
||||
<blockhound-junit>1.0.8.RELEASE</blockhound-junit>
|
||||
<hoverfly>0.14.4</hoverfly>
|
||||
<log4j>2.18.0</log4j>
|
||||
<jsonassert>1.5.1</jsonassert>
|
||||
@@ -248,13 +247,6 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.projectreactor.tools</groupId>
|
||||
<artifactId>blockhound-junit-platform</artifactId>
|
||||
<version>${blockhound-junit}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.skyscreamer</groupId>
|
||||
<artifactId>jsonassert</artifactId>
|
||||
@@ -324,6 +316,13 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.tngtech.archunit</groupId>
|
||||
<artifactId>archunit-junit5</artifactId>
|
||||
<version>${archunit}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@@ -436,25 +435,6 @@
|
||||
</build>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>jdk13+</id>
|
||||
<!-- on jDK13+, Blockhound needs this JVM flag set -->
|
||||
<activation>
|
||||
<jdk>[13,)</jdk>
|
||||
</activation>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>-XX:+AllowRedefinitionToAddDeleteMethods</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>antora-process-resources</id>
|
||||
<build>
|
||||
@@ -472,7 +452,7 @@
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>io.spring.maven.antora</groupId>
|
||||
<groupId>org.antora</groupId>
|
||||
<artifactId>antora-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
@@ -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
|
||||
@@ -22,13 +21,12 @@ content:
|
||||
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
|
||||
|
||||
@@ -10,3 +10,8 @@ ext:
|
||||
local: true
|
||||
scan:
|
||||
dir: target/classes/
|
||||
- run:
|
||||
command: ./mvnw package -Pdistribute
|
||||
local: true
|
||||
scan:
|
||||
dir: target/antora
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*** 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:elasticsearch.adoc[]
|
||||
** xref:elasticsearch/clients.adoc[]
|
||||
@@ -39,4 +39,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]
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,9 +1,21 @@
|
||||
[[new-features]]
|
||||
= What's new
|
||||
|
||||
[[new-features.5-2-2]]
|
||||
== New in Spring Data Elasticsearch 5.2.2
|
||||
* Upgrade to Elasticsearch 8.11.3
|
||||
[[new-features.5-3-1]]
|
||||
== New in Spring Data Elasticsearch 5.3.1
|
||||
|
||||
* Upgrade to Elasticsearch 8.13.4.
|
||||
|
||||
[[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
|
||||
|
||||
@@ -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<Statement> 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)
|
||||
|
||||
@@ -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() //
|
||||
|
||||
+2
-2
@@ -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)
|
||||
|
||||
+200
-1
@@ -316,7 +316,7 @@ Repository methods can be defined to have the following return types for returni
|
||||
|
||||
.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<Book, String> {
|
||||
@@ -361,3 +361,202 @@ 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<Book, String> {
|
||||
@Query("""
|
||||
{
|
||||
"bool":{
|
||||
"must":[
|
||||
{
|
||||
"term":{
|
||||
"name": "#{#name}"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
""")
|
||||
Page<Book> 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<Book, String> {
|
||||
@Query("""
|
||||
{
|
||||
"bool":{
|
||||
"must":[
|
||||
{
|
||||
"term":{
|
||||
"name": "#{#parameter.value}"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
""")
|
||||
Page<Book> 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<Book, String> {
|
||||
@Query("""
|
||||
{
|
||||
"bool":{
|
||||
"must":[
|
||||
{
|
||||
"term":{
|
||||
"name": "#{@queryParameter.value}"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
""")
|
||||
Page<Book> 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<Book, String> {
|
||||
@Query("""
|
||||
{
|
||||
"bool":{
|
||||
"must":[
|
||||
{
|
||||
"terms":{
|
||||
"name": #{#names}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
""")
|
||||
Page<Book> findByName(Collection<String> 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<Book, String> {
|
||||
@Query("""
|
||||
{
|
||||
"bool":{
|
||||
"must":[
|
||||
{
|
||||
"terms":{
|
||||
"name": #{#parameters.![value]}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
""")
|
||||
Page<Book> findByName(Collection<QueryParameter> parameters, Pageable pageable);
|
||||
}
|
||||
----
|
||||
This will extract all the `value` property values as a new `Collection` from `QueryParameter` collection, thus takes the same effect as above.
|
||||
====
|
||||
|
||||
.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<Book, String> {
|
||||
@Query("""
|
||||
{
|
||||
"bool":{
|
||||
"must":[
|
||||
{
|
||||
"terms":{
|
||||
"name": #{#another.![value]}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
""")
|
||||
Page<Book> findByName(@Param("another") Collection<QueryParameter> parameters, Pageable pageable);
|
||||
}
|
||||
----
|
||||
|
||||
====
|
||||
|
||||
@@ -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);
|
||||
""");
|
||||
|
||||
|
||||
@@ -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].
|
||||
|
||||
|
||||
@@ -6,9 +6,10 @@ The following table shows the Elasticsearch and Spring versions that are used by
|
||||
[cols="^,^,^,^",options="header"]
|
||||
|===
|
||||
| Spring Data Release Train | Spring Data Elasticsearch | Elasticsearch | Spring Framework
|
||||
| 2023.1 (Vaughan) | 5.2.x | 8.11.3 | 6.1.x
|
||||
| 2023.0 (Ullmann) | 5.1.x | 8.7.1 | 6.0.x
|
||||
| 2022.0 (Turing) | 5.0.xfootnote:oom[Out of maintenance] | 8.5.3 | 6.0.x
|
||||
| 2024.0 | 5.3.3 | 8.13.4 | 6.1.x
|
||||
| 2023.1 (Vaughan) | 5.2.x | 8.11.1 | 6.1.x
|
||||
| 2023.0 (Ullmann) | 5.1.xfootnote:oom[Out of maintenance] | 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
|
||||
|
||||
@@ -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]]
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
[[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.
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2022-2024 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2024 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2022-2024 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023-2024 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2024 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2024 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2024 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;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2024 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2024 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2024 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2024 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2024 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 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.
|
||||
|
||||
+4
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 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 @@ import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* @author Peter-Josef Meisch
|
||||
* @author Haibo Liu
|
||||
* @since 4.0
|
||||
*/
|
||||
@Documented
|
||||
@@ -59,6 +60,8 @@ public @interface HighlightParameters {
|
||||
|
||||
int numberOfFragments() default -1;
|
||||
|
||||
Query highlightQuery() default @Query;
|
||||
|
||||
String order() default "";
|
||||
|
||||
int phraseLimit() default -1;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2024 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2024 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.
|
||||
|
||||
+5
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023-2024 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.RetentionPolicy;
|
||||
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.
|
||||
* <p>
|
||||
* This can not be used to specify the index where an entity should be written to.
|
||||
*
|
||||
* @author Peter-Josef Meisch
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2024 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2024 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 @@ public @interface Mapping {
|
||||
*/
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2024 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2024 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2024 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2024 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2022-2024 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2024 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.
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 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 @@ public @interface ValueConverter {
|
||||
* 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();
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2022-2024 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 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.
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023-2024 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 @@ import org.springframework.data.util.ReactiveWrappers;
|
||||
*/
|
||||
public class ElasticsearchAotPredicates {
|
||||
|
||||
public static final Predicate<ReactiveWrappers.ReactiveLibrary> IS_REACTIVE_LIBARARY_AVAILABLE = (
|
||||
public static final Predicate<ReactiveWrappers.ReactiveLibrary> 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023-2024 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.
|
||||
|
||||
+10
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018-2024 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.
|
||||
@@ -233,6 +233,15 @@ public interface ClientConfiguration {
|
||||
*/
|
||||
TerminalClientConfigurationBuilder usingSsl();
|
||||
|
||||
/**
|
||||
* Connects using https if flag is true.
|
||||
*
|
||||
* @param flag whether to use https in the connection
|
||||
* @return the {@link TerminalClientConfigurationBuilder}
|
||||
* @since 5.3
|
||||
*/
|
||||
TerminalClientConfigurationBuilder usingSsl(boolean flag);
|
||||
|
||||
/**
|
||||
* Connect via {@literal https} using the given {@link SSLContext}.<br />
|
||||
* <strong>NOTE</strong> You need to leave out the protocol in
|
||||
|
||||
+8
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018-2024 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,7 +25,6 @@ import java.util.function.Supplier;
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.SSLContext;
|
||||
|
||||
import org.elasticsearch.client.RestClientBuilder.HttpClientConfigCallback;
|
||||
import org.springframework.data.elasticsearch.client.ClientConfiguration.ClientConfigurationBuilderWithRequiredEndpoint;
|
||||
import org.springframework.data.elasticsearch.client.ClientConfiguration.MaybeSecureClientConfigurationBuilder;
|
||||
import org.springframework.data.elasticsearch.client.ClientConfiguration.TerminalClientConfigurationBuilder;
|
||||
@@ -106,6 +105,13 @@ class ClientConfigurationBuilder
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TerminalClientConfigurationBuilder usingSsl(boolean flag) {
|
||||
|
||||
this.useSsl = flag;
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.client.ClientConfiguration.MaybeSecureClientConfigurationBuilder#usingSsl(javax.net.ssl.SSLContext)
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018-2024 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018-2024 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018-2024 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018-2024 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2022-2024 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2022-2024 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.
|
||||
|
||||
+70
@@ -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.springframework.data.elasticsearch.core.query.CriteriaQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.Query;
|
||||
import org.springframework.data.elasticsearch.core.query.StringQuery;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* An abstract class that serves as a base for query processors. It provides a common interface and basic functionality
|
||||
* 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}.
|
||||
*/
|
||||
@Nullable
|
||||
static co.elastic.clients.elasticsearch._types.query_dsl.Query getEsQuery(@Nullable Query query,
|
||||
@Nullable Consumer<Query> 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;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2022-2024 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.
|
||||
|
||||
+1
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 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,7 +16,6 @@
|
||||
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 org.elasticsearch.client.RestClient;
|
||||
@@ -40,9 +39,4 @@ public class AutoCloseableElasticsearchClient extends ElasticsearchClient implem
|
||||
public void close() throws Exception {
|
||||
transport.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ElasticsearchClusterClient cluster() {
|
||||
return super.cluster();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 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.
|
||||
|
||||
+27
-13
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 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.GeoBox;
|
||||
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 @@ import org.springframework.util.Assert;
|
||||
* filter.
|
||||
*
|
||||
* @author Peter-Josef Meisch
|
||||
* @author Junghoon Ban
|
||||
* @since 4.4
|
||||
*/
|
||||
class CriteriaFilterProcessor {
|
||||
@@ -68,10 +70,17 @@ class CriteriaFilterProcessor {
|
||||
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 @@ class CriteriaFilterProcessor {
|
||||
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 @@ class CriteriaFilterProcessor {
|
||||
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 @@ class CriteriaFilterProcessor {
|
||||
"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 @@ class CriteriaFilterProcessor {
|
||||
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 @@ class CriteriaFilterProcessor {
|
||||
.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 @@ class CriteriaFilterProcessor {
|
||||
}) //
|
||||
.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);
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 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.
|
||||
|
||||
+72
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 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,21 +16,27 @@
|
||||
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.springframework.data.elasticsearch.annotations.FieldType;
|
||||
import org.springframework.data.elasticsearch.core.query.Criteria;
|
||||
import org.springframework.data.elasticsearch.core.query.Field;
|
||||
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.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -42,7 +48,7 @@ import org.springframework.util.Assert;
|
||||
* @author Ezequiel Antúnez Camacho
|
||||
* @since 4.4
|
||||
*/
|
||||
class CriteriaQueryProcessor {
|
||||
class CriteriaQueryProcessor extends AbstractQueryProcessor {
|
||||
|
||||
/**
|
||||
* creates a query from the criteria
|
||||
@@ -110,11 +116,18 @@ class CriteriaQueryProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ class CriteriaQueryProcessor {
|
||||
boolQueryBuilder.must(mustQueries);
|
||||
}
|
||||
|
||||
filterQuery.ifPresent(boolQueryBuilder::filter);
|
||||
|
||||
return boolQueryBuilder;
|
||||
}).build();
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -174,6 +187,12 @@ class CriteriaQueryProcessor {
|
||||
.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,7 +246,7 @@ class CriteriaQueryProcessor {
|
||||
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 //
|
||||
@@ -259,6 +278,7 @@ class CriteriaQueryProcessor {
|
||||
break;
|
||||
case BETWEEN:
|
||||
Object[] ranges = (Object[]) value;
|
||||
Assert.notNull(value, "value for a between condition must not be null");
|
||||
queryBuilder //
|
||||
.range(rb -> {
|
||||
rb.field(fieldName);
|
||||
@@ -282,10 +302,10 @@ class CriteriaQueryProcessor {
|
||||
.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 +354,35 @@ class CriteriaQueryProcessor {
|
||||
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 +405,7 @@ class CriteriaQueryProcessor {
|
||||
|
||||
if (item != null) {
|
||||
|
||||
if (sb.length() > 0) {
|
||||
if (!sb.isEmpty()) {
|
||||
sb.append(' ');
|
||||
}
|
||||
sb.append('"');
|
||||
@@ -391,4 +437,19 @@ class CriteriaQueryProcessor {
|
||||
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()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 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.
|
||||
@@ -49,6 +49,7 @@ import org.springframework.util.Assert;
|
||||
* {@link org.springframework.data.elasticsearch.core.document.Document}
|
||||
*
|
||||
* @author Peter-Josef Meisch
|
||||
* @author Haibo Liu
|
||||
* @since 4.4
|
||||
*/
|
||||
final class DocumentAdapters {
|
||||
@@ -73,7 +74,7 @@ final class DocumentAdapters {
|
||||
Map<String, SearchDocumentResponse> innerHits = new LinkedHashMap<>();
|
||||
hit.innerHits().forEach((name, innerHitsResult) -> {
|
||||
// noinspection ReturnOfNull
|
||||
innerHits.put(name, SearchDocumentResponseBuilder.from(innerHitsResult.hits(), null, null, null, null,
|
||||
innerHits.put(name, SearchDocumentResponseBuilder.from(innerHitsResult.hits(), null, null, null, null, null,
|
||||
searchDocument -> null, jsonpMapper));
|
||||
});
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2022-2024 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2022-2024 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2022-2024 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 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.
|
||||
|
||||
+12
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 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.
|
||||
@@ -31,6 +31,10 @@ import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
||||
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
|
||||
/**
|
||||
* Base class for a @{@link org.springframework.context.annotation.Configuration} class to set up the Elasticsearch
|
||||
* connection using the Elasticsearch Client. This class exposes different parts of the setup as Spring beans. Deriving
|
||||
@@ -118,7 +122,13 @@ public abstract class ElasticsearchConfiguration extends ElasticsearchConfigurat
|
||||
*/
|
||||
@Bean
|
||||
public JsonpMapper jsonpMapper() {
|
||||
return new JacksonJsonpMapper();
|
||||
// we need to create our own objectMapper that keeps null values in order to provide the storeNullValue
|
||||
// functionality. The one Elasticsearch would provide removes the nulls. We remove unwanted nulls before they get
|
||||
// into this mapper, so we can safely keep them here.
|
||||
var objectMapper = (new ObjectMapper())
|
||||
.configure(SerializationFeature.INDENT_OUTPUT, false)
|
||||
.setSerializationInclusion(JsonInclude.Include.ALWAYS);
|
||||
return new JacksonJsonpMapper(objectMapper);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 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.
|
||||
@@ -40,6 +40,7 @@ import org.springframework.data.elasticsearch.VersionConflictException;
|
||||
* appropriate: any other exception may have resulted from user code, and should not be translated.
|
||||
*
|
||||
* @author Peter-Josef Meisch
|
||||
* @author Junghoon Ban
|
||||
* @since 4.4
|
||||
*/
|
||||
public class ElasticsearchExceptionTranslator implements PersistenceExceptionTranslator {
|
||||
@@ -59,7 +60,7 @@ public class ElasticsearchExceptionTranslator implements PersistenceExceptionTra
|
||||
*/
|
||||
public RuntimeException translateException(Throwable throwable) {
|
||||
|
||||
RuntimeException runtimeException = throwable instanceof RuntimeException ? (RuntimeException) throwable
|
||||
RuntimeException runtimeException = throwable instanceof RuntimeException ex ? ex
|
||||
: new RuntimeException(throwable.getMessage(), throwable);
|
||||
RuntimeException potentiallyTranslatedException = translateExceptionIfPossible(runtimeException);
|
||||
|
||||
|
||||
+92
-42
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 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.
|
||||
@@ -29,6 +29,7 @@ import co.elastic.clients.transport.Version;
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@@ -50,14 +51,7 @@ import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverte
|
||||
import org.springframework.data.elasticsearch.core.document.Document;
|
||||
import org.springframework.data.elasticsearch.core.document.SearchDocumentResponse;
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
import org.springframework.data.elasticsearch.core.query.BaseQueryBuilder;
|
||||
import org.springframework.data.elasticsearch.core.query.BulkOptions;
|
||||
import org.springframework.data.elasticsearch.core.query.ByQueryResponse;
|
||||
import org.springframework.data.elasticsearch.core.query.IndexQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.MoreLikeThisQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.Query;
|
||||
import org.springframework.data.elasticsearch.core.query.SearchTemplateQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.UpdateQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.*;
|
||||
import org.springframework.data.elasticsearch.core.query.UpdateResponse;
|
||||
import org.springframework.data.elasticsearch.core.reindex.ReindexRequest;
|
||||
import org.springframework.data.elasticsearch.core.reindex.ReindexResponse;
|
||||
@@ -72,6 +66,7 @@ import org.springframework.util.Assert;
|
||||
* @author Peter-Josef Meisch
|
||||
* @author Hamid Rahimi
|
||||
* @author Illia Ulianov
|
||||
* @author Haibo Liu
|
||||
* @since 4.4
|
||||
*/
|
||||
public class ElasticsearchTemplate extends AbstractElasticsearchTemplate {
|
||||
@@ -175,6 +170,11 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate {
|
||||
doBulkOperation(queries, bulkOptions, index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByQueryResponse delete(DeleteQuery query, Class<?> clazz) {
|
||||
return delete(query, clazz, getIndexCoordinatesFor(clazz));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByQueryResponse delete(Query query, Class<?> clazz, IndexCoordinates index) {
|
||||
|
||||
@@ -188,6 +188,18 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate {
|
||||
return responseConverter.byQueryResponse(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByQueryResponse delete(DeleteQuery query, Class<?> clazz, IndexCoordinates index) {
|
||||
Assert.notNull(query, "query must not be null");
|
||||
|
||||
DeleteByQueryRequest request = requestConverter.documentDeleteByQueryRequest(query, routingResolver.getRouting(),
|
||||
clazz, index, getRefreshPolicy());
|
||||
|
||||
DeleteByQueryResponse response = execute(client -> client.deleteByQuery(request));
|
||||
|
||||
return responseConverter.byQueryResponse(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UpdateResponse update(UpdateQuery updateQuery, IndexCoordinates index) {
|
||||
|
||||
@@ -437,13 +449,10 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate {
|
||||
Assert.notNull(queries, "queries must not be null");
|
||||
Assert.notNull(clazz, "clazz must not be null");
|
||||
|
||||
List<MultiSearchQueryParameter> multiSearchQueryParameters = new ArrayList<>(queries.size());
|
||||
for (Query query : queries) {
|
||||
multiSearchQueryParameters.add(new MultiSearchQueryParameter(query, clazz, getIndexCoordinatesFor(clazz)));
|
||||
}
|
||||
|
||||
int size = queries.size();
|
||||
// noinspection unchecked
|
||||
return doMultiSearch(multiSearchQueryParameters).stream().map(searchHits -> (SearchHits<T>) searchHits)
|
||||
return multiSearch(queries, Collections.nCopies(size, clazz), Collections.nCopies(size, index))
|
||||
.stream().map(searchHits -> (SearchHits<T>) searchHits)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@@ -454,14 +463,7 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate {
|
||||
Assert.notNull(classes, "classes must not be null");
|
||||
Assert.isTrue(queries.size() == classes.size(), "queries and classes must have the same size");
|
||||
|
||||
List<MultiSearchQueryParameter> multiSearchQueryParameters = new ArrayList<>(queries.size());
|
||||
Iterator<Class<?>> it = classes.iterator();
|
||||
for (Query query : queries) {
|
||||
Class<?> clazz = it.next();
|
||||
multiSearchQueryParameters.add(new MultiSearchQueryParameter(query, clazz, getIndexCoordinatesFor(clazz)));
|
||||
}
|
||||
|
||||
return doMultiSearch(multiSearchQueryParameters);
|
||||
return multiSearch(queries, classes, classes.stream().map(this::getIndexCoordinatesFor).toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -473,14 +475,7 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate {
|
||||
Assert.notNull(index, "index must not be null");
|
||||
Assert.isTrue(queries.size() == classes.size(), "queries and classes must have the same size");
|
||||
|
||||
List<MultiSearchQueryParameter> multiSearchQueryParameters = new ArrayList<>(queries.size());
|
||||
Iterator<Class<?>> it = classes.iterator();
|
||||
for (Query query : queries) {
|
||||
Class<?> clazz = it.next();
|
||||
multiSearchQueryParameters.add(new MultiSearchQueryParameter(query, clazz, index));
|
||||
}
|
||||
|
||||
return doMultiSearch(multiSearchQueryParameters);
|
||||
return multiSearch(queries, classes, Collections.nCopies(queries.size(), index));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -497,16 +492,50 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate {
|
||||
Iterator<Class<?>> it = classes.iterator();
|
||||
Iterator<IndexCoordinates> indexesIt = indexes.iterator();
|
||||
|
||||
Assert.isTrue(!queries.isEmpty(), "queries should have at least 1 query");
|
||||
boolean isSearchTemplateQuery = queries.get(0) instanceof SearchTemplateQuery;
|
||||
|
||||
for (Query query : queries) {
|
||||
Assert.isTrue((query instanceof SearchTemplateQuery) == isSearchTemplateQuery,
|
||||
"SearchTemplateQuery can't be mixed with other types of query in multiple search");
|
||||
|
||||
Class<?> clazz = it.next();
|
||||
IndexCoordinates index = indexesIt.next();
|
||||
multiSearchQueryParameters.add(new MultiSearchQueryParameter(query, clazz, index));
|
||||
}
|
||||
|
||||
return doMultiSearch(multiSearchQueryParameters);
|
||||
return multiSearch(multiSearchQueryParameters, isSearchTemplateQuery);
|
||||
}
|
||||
|
||||
private List<SearchHits<?>> multiSearch(List<MultiSearchQueryParameter> multiSearchQueryParameters,
|
||||
boolean isSearchTemplateQuery) {
|
||||
return isSearchTemplateQuery ? doMultiTemplateSearch(multiSearchQueryParameters.stream()
|
||||
.map(p -> new MultiSearchTemplateQueryParameter((SearchTemplateQuery) p.query, p.clazz, p.index))
|
||||
.toList())
|
||||
: doMultiSearch(multiSearchQueryParameters);
|
||||
}
|
||||
|
||||
private List<SearchHits<?>> doMultiTemplateSearch(
|
||||
List<MultiSearchTemplateQueryParameter> mSearchTemplateQueryParameters) {
|
||||
MsearchTemplateRequest request = requestConverter.searchMsearchTemplateRequest(mSearchTemplateQueryParameters,
|
||||
routingResolver.getRouting());
|
||||
|
||||
MsearchTemplateResponse<EntityAsMap> response = execute(
|
||||
client -> client.msearchTemplate(request, EntityAsMap.class));
|
||||
List<MultiSearchResponseItem<EntityAsMap>> responseItems = response.responses();
|
||||
|
||||
Assert.isTrue(mSearchTemplateQueryParameters.size() == responseItems.size(),
|
||||
"number of response items does not match number of requests");
|
||||
|
||||
int size = mSearchTemplateQueryParameters.size();
|
||||
List<Class<?>> classes = mSearchTemplateQueryParameters
|
||||
.stream().map(MultiSearchTemplateQueryParameter::clazz).collect(Collectors.toList());
|
||||
List<IndexCoordinates> indices = mSearchTemplateQueryParameters
|
||||
.stream().map(MultiSearchTemplateQueryParameter::index).collect(Collectors.toList());
|
||||
|
||||
return getSearchHitsFromMsearchResponse(size, classes, indices, responseItems);
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private List<SearchHits<?>> doMultiSearch(List<MultiSearchQueryParameter> multiSearchQueryParameters) {
|
||||
|
||||
MsearchRequest request = requestConverter.searchMsearchRequest(multiSearchQueryParameters,
|
||||
@@ -518,22 +547,37 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate {
|
||||
Assert.isTrue(multiSearchQueryParameters.size() == responseItems.size(),
|
||||
"number of response items does not match number of requests");
|
||||
|
||||
List<SearchHits<?>> searchHitsList = new ArrayList<>(multiSearchQueryParameters.size());
|
||||
int size = multiSearchQueryParameters.size();
|
||||
List<Class<?>> classes = multiSearchQueryParameters
|
||||
.stream().map(MultiSearchQueryParameter::clazz).collect(Collectors.toList());
|
||||
List<IndexCoordinates> indices = multiSearchQueryParameters
|
||||
.stream().map(MultiSearchQueryParameter::index).collect(Collectors.toList());
|
||||
|
||||
Iterator<MultiSearchQueryParameter> queryIterator = multiSearchQueryParameters.iterator();
|
||||
return getSearchHitsFromMsearchResponse(size, classes, indices, responseItems);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link MsearchResponse} and {@link MsearchTemplateResponse} share the same {@link MultiSearchResponseItem}
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private List<SearchHits<?>> getSearchHitsFromMsearchResponse(int size, List<Class<?>> classes,
|
||||
List<IndexCoordinates> indices, List<MultiSearchResponseItem<EntityAsMap>> responseItems) {
|
||||
List<SearchHits<?>> searchHitsList = new ArrayList<>(size);
|
||||
Iterator<Class<?>> clazzIter = classes.iterator();
|
||||
Iterator<IndexCoordinates> indexIter = indices.iterator();
|
||||
Iterator<MultiSearchResponseItem<EntityAsMap>> responseIterator = responseItems.iterator();
|
||||
|
||||
while (queryIterator.hasNext()) {
|
||||
MultiSearchQueryParameter queryParameter = queryIterator.next();
|
||||
while (clazzIter.hasNext() && indexIter.hasNext()) {
|
||||
MultiSearchResponseItem<EntityAsMap> responseItem = responseIterator.next();
|
||||
|
||||
if (responseItem.isResult()) {
|
||||
|
||||
Class clazz = queryParameter.clazz;
|
||||
Class clazz = clazzIter.next();
|
||||
IndexCoordinates index = indexIter.next();
|
||||
ReadDocumentCallback<?> documentCallback = new ReadDocumentCallback<>(elasticsearchConverter, clazz,
|
||||
queryParameter.index);
|
||||
index);
|
||||
SearchDocumentResponseCallback<SearchHits<?>> callback = new ReadSearchDocumentResponseCallback<>(clazz,
|
||||
queryParameter.index);
|
||||
index);
|
||||
|
||||
SearchHits<?> searchHits = callback.doWith(
|
||||
SearchDocumentResponseBuilder.from(responseItem.result(), getEntityCreator(documentCallback), jsonpMapper));
|
||||
@@ -541,8 +585,8 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate {
|
||||
searchHitsList.add(searchHits);
|
||||
} else {
|
||||
if (LOGGER.isWarnEnabled()) {
|
||||
LOGGER
|
||||
.warn(String.format("multisearch responsecontains failure: {}", responseItem.failure().error().reason()));
|
||||
LOGGER.warn(String.format("multisearch response contains failure: %s",
|
||||
responseItem.failure().error().reason()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -556,6 +600,12 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate {
|
||||
record MultiSearchQueryParameter(Query query, Class<?> clazz, IndexCoordinates index) {
|
||||
}
|
||||
|
||||
/**
|
||||
* value class combining the information needed for a single query in a template multisearch request.
|
||||
*/
|
||||
record MultiSearchTemplateQueryParameter(SearchTemplateQuery query, Class<?> clazz, IndexCoordinates index) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String openPointInTime(IndexCoordinates index, Duration keepAlive, Boolean ignoreUnavailable) {
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 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.
|
||||
|
||||
+15
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2022-2024 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.
|
||||
@@ -35,14 +35,17 @@ import org.springframework.util.StringUtils;
|
||||
* {@link co.elastic.clients.elasticsearch.core.search.Highlight}.
|
||||
*
|
||||
* @author Peter-Josef Meisch
|
||||
* @author Haibo Liu
|
||||
* @since 4.4
|
||||
*/
|
||||
class HighlightQueryBuilder {
|
||||
private final MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext;
|
||||
private final RequestConverter requestConverter;
|
||||
|
||||
HighlightQueryBuilder(
|
||||
MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext) {
|
||||
MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext, RequestConverter requestConverter) {
|
||||
this.mappingContext = mappingContext;
|
||||
this.requestConverter = requestConverter;
|
||||
}
|
||||
|
||||
public co.elastic.clients.elasticsearch.core.search.Highlight getHighlight(Highlight highlight,
|
||||
@@ -52,7 +55,7 @@ class HighlightQueryBuilder {
|
||||
|
||||
// in the old implementation we could use one addParameters method, but in the new Elasticsearch client
|
||||
// the builder for highlight and highlightfield share no code
|
||||
addParameters(highlight.getParameters(), highlightBuilder);
|
||||
addParameters(highlight.getParameters(), highlightBuilder, type);
|
||||
|
||||
for (HighlightField highlightField : highlight.getFields()) {
|
||||
String mappedName = mapFieldName(highlightField.getName(), type);
|
||||
@@ -69,7 +72,7 @@ class HighlightQueryBuilder {
|
||||
* the builder for highlight and highlight fields don't share code, so we have these two methods here that basically are almost copies
|
||||
*/
|
||||
private void addParameters(HighlightParameters parameters,
|
||||
co.elastic.clients.elasticsearch.core.search.Highlight.Builder builder) {
|
||||
co.elastic.clients.elasticsearch.core.search.Highlight.Builder builder, @Nullable Class<?> type) {
|
||||
|
||||
if (StringUtils.hasLength(parameters.getBoundaryChars())) {
|
||||
builder.boundaryChars(parameters.getBoundaryChars());
|
||||
@@ -103,6 +106,10 @@ class HighlightQueryBuilder {
|
||||
builder.numberOfFragments(parameters.getNumberOfFragments());
|
||||
}
|
||||
|
||||
if (parameters.getHighlightQuery() != null) {
|
||||
builder.highlightQuery(requestConverter.getQuery(parameters.getHighlightQuery(), type));
|
||||
}
|
||||
|
||||
if (StringUtils.hasLength(parameters.getOrder())) {
|
||||
builder.order(highlighterOrder(parameters.getOrder()));
|
||||
}
|
||||
@@ -174,6 +181,10 @@ class HighlightQueryBuilder {
|
||||
builder.numberOfFragments(parameters.getNumberOfFragments());
|
||||
}
|
||||
|
||||
if (parameters.getHighlightQuery() != null) {
|
||||
builder.highlightQuery(requestConverter.getQuery(parameters.getHighlightQuery(), type));
|
||||
}
|
||||
|
||||
if (StringUtils.hasLength(parameters.getOrder())) {
|
||||
builder.order(highlighterOrder(parameters.getOrder()));
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 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.
|
||||
@@ -19,7 +19,6 @@ import co.elastic.clients.json.JsonpMapper;
|
||||
import jakarta.json.stream.JsonGenerator;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
@@ -44,17 +43,13 @@ final class JsonUtils {
|
||||
mapper.serialize(object, generator);
|
||||
generator.close();
|
||||
String json = "{}";
|
||||
try {
|
||||
json = baos.toString("UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
LOGGER.warn("could not read json", e);
|
||||
}
|
||||
|
||||
json = baos.toString(StandardCharsets.UTF_8);
|
||||
return json;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String queryToJson(@Nullable co.elastic.clients.elasticsearch._types.query_dsl.Query query, JsonpMapper mapper) {
|
||||
public static String queryToJson(@Nullable co.elastic.clients.elasticsearch._types.query_dsl.Query query,
|
||||
JsonpMapper mapper) {
|
||||
|
||||
if (query == null) {
|
||||
return null;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2024 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,6 +16,7 @@
|
||||
package org.springframework.data.elasticsearch.client.elc;
|
||||
|
||||
import co.elastic.clients.elasticsearch._types.KnnQuery;
|
||||
import co.elastic.clients.elasticsearch._types.KnnSearch;
|
||||
import co.elastic.clients.elasticsearch._types.SortOptions;
|
||||
import co.elastic.clients.elasticsearch._types.aggregations.Aggregation;
|
||||
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
|
||||
@@ -54,6 +55,7 @@ public class NativeQuery extends BaseQuery {
|
||||
|
||||
private Map<String, JsonData> searchExtensions = Collections.emptyMap();
|
||||
@Nullable private KnnQuery knnQuery;
|
||||
@Nullable private List<KnnSearch> knnSearches = Collections.emptyList();
|
||||
|
||||
public NativeQuery(NativeQueryBuilder builder) {
|
||||
super(builder);
|
||||
@@ -71,6 +73,7 @@ public class NativeQuery extends BaseQuery {
|
||||
}
|
||||
this.springDataQuery = builder.getSpringDataQuery();
|
||||
this.knnQuery = builder.getKnnQuery();
|
||||
this.knnSearches = builder.getKnnSearches();
|
||||
}
|
||||
|
||||
public NativeQuery(@Nullable Query query) {
|
||||
@@ -129,6 +132,14 @@ public class NativeQuery extends BaseQuery {
|
||||
return knnQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 5.3.1
|
||||
*/
|
||||
@Nullable
|
||||
public List<KnnSearch> getKnnSearches() {
|
||||
return knnSearches;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public org.springframework.data.elasticsearch.core.query.Query getSpringDataQuery() {
|
||||
return springDataQuery;
|
||||
|
||||
+14
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2022-2024 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.
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.springframework.data.elasticsearch.client.elc;
|
||||
|
||||
import co.elastic.clients.elasticsearch._types.KnnQuery;
|
||||
import co.elastic.clients.elasticsearch._types.KnnSearch;
|
||||
import co.elastic.clients.elasticsearch._types.SortOptions;
|
||||
import co.elastic.clients.elasticsearch._types.aggregations.Aggregation;
|
||||
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
|
||||
@@ -26,6 +27,7 @@ import co.elastic.clients.util.ObjectBuilder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -47,11 +49,12 @@ public class NativeQueryBuilder extends BaseQueryBuilder<NativeQuery, NativeQuer
|
||||
private final Map<String, Aggregation> aggregations = new LinkedHashMap<>();
|
||||
@Nullable private Suggester suggester;
|
||||
@Nullable private FieldCollapse fieldCollapse;
|
||||
private List<SortOptions> sortOptions = new ArrayList<>();
|
||||
private Map<String, JsonData> searchExtensions = new LinkedHashMap<>();
|
||||
private final List<SortOptions> sortOptions = new ArrayList<>();
|
||||
private final Map<String, JsonData> searchExtensions = new LinkedHashMap<>();
|
||||
|
||||
@Nullable private org.springframework.data.elasticsearch.core.query.Query springDataQuery;
|
||||
@Nullable private KnnQuery knnQuery;
|
||||
@Nullable private List<KnnSearch> knnSearches = Collections.emptyList();
|
||||
|
||||
public NativeQueryBuilder() {}
|
||||
|
||||
@@ -92,6 +95,14 @@ public class NativeQueryBuilder extends BaseQueryBuilder<NativeQuery, NativeQuer
|
||||
return knnQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 5.3.1
|
||||
*/
|
||||
@Nullable
|
||||
public List<KnnSearch> getKnnSearches() {
|
||||
return knnSearches;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public org.springframework.data.elasticsearch.core.query.Query getSpringDataQuery() {
|
||||
return springDataQuery;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2022-2024 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.
|
||||
|
||||
@@ -1,174 +0,0 @@
|
||||
/*
|
||||
* Copyright 2022-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.client.elc;
|
||||
|
||||
import co.elastic.clients.elasticsearch._types.FieldValue;
|
||||
import co.elastic.clients.elasticsearch._types.LatLonGeoLocation;
|
||||
import co.elastic.clients.elasticsearch._types.query_dsl.IdsQuery;
|
||||
import co.elastic.clients.elasticsearch._types.query_dsl.MatchAllQuery;
|
||||
import co.elastic.clients.elasticsearch._types.query_dsl.MatchQuery;
|
||||
import co.elastic.clients.elasticsearch._types.query_dsl.Operator;
|
||||
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
|
||||
import co.elastic.clients.elasticsearch._types.query_dsl.QueryStringQuery;
|
||||
import co.elastic.clients.elasticsearch._types.query_dsl.TermQuery;
|
||||
import co.elastic.clients.elasticsearch._types.query_dsl.WildcardQuery;
|
||||
import co.elastic.clients.elasticsearch._types.query_dsl.WrapperQuery;
|
||||
import co.elastic.clients.util.ObjectBuilder;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Utility class simplifying the creation of some more complex queries and type.
|
||||
*
|
||||
* @author Peter-Josef Meisch
|
||||
* @since 4.4
|
||||
* @deprecated since 5.1, use {@link Queries} instead.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public final class QueryBuilders {
|
||||
|
||||
private QueryBuilders() {}
|
||||
|
||||
public static IdsQuery idsQuery(List<String> ids) {
|
||||
|
||||
Assert.notNull(ids, "ids must not be null");
|
||||
|
||||
return IdsQuery.of(i -> i.values(ids));
|
||||
}
|
||||
|
||||
public static Query idsQueryAsQuery(List<String> ids) {
|
||||
|
||||
Assert.notNull(ids, "ids must not be null");
|
||||
|
||||
Function<Query.Builder, ObjectBuilder<Query>> builder = b -> b.ids(idsQuery(ids));
|
||||
|
||||
return builder.apply(new Query.Builder()).build();
|
||||
}
|
||||
|
||||
public static MatchQuery matchQuery(String fieldName, String query, @Nullable Operator operator,
|
||||
@Nullable Float boost) {
|
||||
|
||||
Assert.notNull(fieldName, "fieldName must not be null");
|
||||
Assert.notNull(query, "query must not be null");
|
||||
|
||||
return MatchQuery.of(mb -> mb.field(fieldName).query(FieldValue.of(query)).operator(operator).boost(boost));
|
||||
}
|
||||
|
||||
public static Query matchQueryAsQuery(String fieldName, String query, @Nullable Operator operator,
|
||||
@Nullable Float boost) {
|
||||
|
||||
Function<Query.Builder, ObjectBuilder<Query>> builder = b -> b.match(matchQuery(fieldName, query, operator, boost));
|
||||
|
||||
return builder.apply(new Query.Builder()).build();
|
||||
}
|
||||
|
||||
public static MatchAllQuery matchAllQuery() {
|
||||
|
||||
return MatchAllQuery.of(b -> b);
|
||||
}
|
||||
|
||||
public static Query matchAllQueryAsQuery() {
|
||||
|
||||
Function<Query.Builder, ObjectBuilder<Query>> builder = b -> b.matchAll(matchAllQuery());
|
||||
|
||||
return builder.apply(new Query.Builder()).build();
|
||||
}
|
||||
|
||||
public static QueryStringQuery queryStringQuery(String fieldName, String query, @Nullable Float boost) {
|
||||
return queryStringQuery(fieldName, query, null, null, boost);
|
||||
}
|
||||
|
||||
public static QueryStringQuery queryStringQuery(String fieldName, String query, Operator defaultOperator,
|
||||
@Nullable Float boost) {
|
||||
return queryStringQuery(fieldName, query, null, defaultOperator, boost);
|
||||
}
|
||||
|
||||
public static QueryStringQuery queryStringQuery(String fieldName, String query, @Nullable Boolean analyzeWildcard,
|
||||
@Nullable Float boost) {
|
||||
return queryStringQuery(fieldName, query, analyzeWildcard, null, boost);
|
||||
}
|
||||
|
||||
public static QueryStringQuery queryStringQuery(String fieldName, String query, @Nullable Boolean analyzeWildcard,
|
||||
@Nullable Operator defaultOperator, @Nullable Float boost) {
|
||||
|
||||
Assert.notNull(fieldName, "fieldName must not be null");
|
||||
Assert.notNull(query, "query must not be null");
|
||||
|
||||
return QueryStringQuery.of(qs -> qs.fields(fieldName).query(query).analyzeWildcard(analyzeWildcard)
|
||||
.defaultOperator(defaultOperator).boost(boost));
|
||||
}
|
||||
|
||||
public static TermQuery termQuery(String fieldName, String value) {
|
||||
|
||||
Assert.notNull(fieldName, "fieldName must not be null");
|
||||
Assert.notNull(value, "value must not be null");
|
||||
|
||||
return TermQuery.of(t -> t.field(fieldName).value(FieldValue.of(value)));
|
||||
}
|
||||
|
||||
public static Query termQueryAsQuery(String fieldName, String value) {
|
||||
|
||||
Function<Query.Builder, ObjectBuilder<Query>> builder = q -> q.term(termQuery(fieldName, value));
|
||||
return builder.apply(new Query.Builder()).build();
|
||||
}
|
||||
|
||||
public static WildcardQuery wildcardQuery(String field, String value) {
|
||||
|
||||
Assert.notNull(field, "field must not be null");
|
||||
Assert.notNull(value, "value must not be null");
|
||||
|
||||
return WildcardQuery.of(w -> w.field(field).wildcard(value));
|
||||
}
|
||||
|
||||
public static Query wildcardQueryAsQuery(String field, String value) {
|
||||
Function<Query.Builder, ObjectBuilder<Query>> builder = q -> q.wildcard(wildcardQuery(field, value));
|
||||
return builder.apply(new Query.Builder()).build();
|
||||
}
|
||||
|
||||
public static Query wrapperQueryAsQuery(String query) {
|
||||
|
||||
Function<Query.Builder, ObjectBuilder<Query>> builder = q -> q.wrapper(wrapperQuery(query));
|
||||
|
||||
return builder.apply(new Query.Builder()).build();
|
||||
}
|
||||
|
||||
public static WrapperQuery wrapperQuery(String query) {
|
||||
|
||||
Assert.notNull(query, "query must not be null");
|
||||
|
||||
String encodedValue = Base64.getEncoder().encodeToString(query.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
return WrapperQuery.of(wq -> wq.query(encodedValue));
|
||||
}
|
||||
|
||||
public static LatLonGeoLocation latLon(GeoPoint geoPoint) {
|
||||
|
||||
Assert.notNull(geoPoint, "geoPoint must not be null");
|
||||
|
||||
return latLon(geoPoint.getLat(), geoPoint.getLon());
|
||||
}
|
||||
|
||||
public static LatLonGeoLocation latLon(double lat, double lon) {
|
||||
return LatLonGeoLocation.of(_0 -> _0.lat(lat).lon(lon));
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user