Compare commits

...

65 Commits
main ... 5.1.7

Author SHA1 Message Date
Mark Paluch
033b3fbf55
Release version 5.1.7 (2023.0.7).
See #2770
2023-12-15 13:15:05 +01:00
Mark Paluch
b9c8c2ef7e
Prepare 5.1.7 (2023.0.7).
See #2770
2023-12-15 13:14:52 +01:00
Mark Paluch
37c78e4289
Update CI properties.
See #2770
2023-12-14 08:50:13 +01:00
Mark Paluch
0122f61ec0
Upgrade to Maven Wrapper 3.9.6.
See #2800
2023-12-14 08:37:40 +01:00
Peter-Josef Meisch
b775357524
Fix type of returned sort values.
Original Pull Request #2786
Closes #2777

(cherry picked from commit 3833975a1ad76ef9c90b1260b090ff1eb9af523c)
(cherry picked from commit 0fb98eda39532ba1091a27a6acffe732c27d846f)
2023-11-30 21:09:49 +01:00
Mark Paluch
c9fe8a29b9
Introduce property for Jenkins user and Artifactory server details.
Closes #2781
2023-11-27 11:18:52 +01:00
Mark Paluch
c444bbd65f
After release cleanups.
See #2736
2023-11-17 13:41:01 +01:00
Mark Paluch
9c1b001da1
Prepare next development iteration.
See #2736
2023-11-17 13:40:59 +01:00
Mark Paluch
ea234c7b68
Release version 5.1.6 (2023.0.6).
See #2736
2023-11-17 13:38:04 +01:00
Mark Paluch
42af6e375c
Prepare 5.1.6 (2023.0.6).
See #2736
2023-11-17 13:37:52 +01:00
Peter-Josef Meisch
5dfd05992f
Upgrade dependency of deprecated Elasticsearch client to 7.17.15.
Origina Pull Request #2769
Closes #2765
2023-11-15 21:38:17 +01:00
Peter-Josef Meisch
64cf9566d9
Use routing info on delete operations.
Original Pull Request #2755
Closes #2754

(cherry picked from commit 9abcacb2e9dfcebc9629d563072bdb85632630a9)
2023-11-06 22:17:04 +01:00
Peter-Josef Meisch
2c857178f4
Fix reactive native sort.
Original Pull Request #2746
Closes #2745

(cherry picked from commit 73fe0869e67db5aa45302658db14a930aa8cf32f)
2023-10-23 21:50:50 +02:00
Peter-Josef Meisch
f087d5aac3
Fix field parameters in search request creation.
Original Pull Request #2739
Closes #2727
2023-10-14 11:17:09 +02:00
John Blum
fbcb76f8ad
After release cleanups.
See #2699
2023-10-13 08:09:35 -07:00
John Blum
ba06741c93
Prepare next development iteration.
See #2699
2023-10-13 08:09:33 -07:00
John Blum
a228629c7d
Release version 5.1.5 (2023.0.5).
See #2699
2023-10-13 08:01:15 -07:00
John Blum
6fd688f3a2
Prepare 5.1.5 (2023.0.5).
See #2699
2023-10-13 08:00:48 -07:00
Peter-Josef Meisch
7d85f0bdd8
Upgrade to Elasticsearch 7.17.14.
Original Pull Request #2732
2023-10-13 08:37:45 +02:00
John Blum
c7534fa8b9
Upgrade to Maven Wrapper 3.9.5.
See #2715
2023-10-04 18:22:43 -07:00
John Blum
fe9e0b5d0c
Update CI properties.
See #2699
2023-10-04 17:46:55 -07:00
Peter-Josef Meisch
d26d01bab1 Fix converting of Range<?> in Lists.
Original Pull Request #2707
Closes #2706

(cherry picked from commit 3330d65edf37d3f07d50ed229002ce7a6b9b0b64)
2023-09-23 12:53:19 +02:00
Mark Paluch
026be264fe
After release cleanups.
See #2674
2023-09-15 10:55:36 +02:00
Mark Paluch
fd1ba5869d
Prepare next development iteration.
See #2674
2023-09-15 10:55:34 +02:00
Mark Paluch
7f3035dab5
Release version 5.1.4 (2023.0.4).
See #2674
2023-09-15 10:52:26 +02:00
Mark Paluch
a5c4867684
Prepare 5.1.4 (2023.0.4).
See #2674
2023-09-15 10:52:12 +02:00
Peter-Josef Meisch
572cc7ffea
Fix refresh policy in UpdateQuery.
Original Pull Request #2696
Closes #2692

(cherry picked from commit 2d0aee08ce00d84dd874b0d46da731b688f1ce61)
2023-09-13 21:49:19 +02:00
Peter-Josef Meisch
4e7bcac5f5
Upgrade deprecated client to Elasticsearch-7.17.13.
Original Pull Request #2694
Closes #2688
2023-09-13 19:38:50 +02:00
Peter-Josef Meisch
4628908e84
Polishing.
(cherry picked from commit a82952b12435d069c2fb6904528b6f71ece40c78)
2023-09-03 15:44:09 +02:00
Sébastien Comeau
922f4b1760
Fix: missing PhraseSuggestion.Entry.Option's score and collateMatch values.
Original Pull Request #2680
Closes #2681

(cherry picked from commit 7c466395c42e3802be03879f2ac2055170b4692e)
2023-09-03 15:44:08 +02:00
Peter-Josef Meisch
4614c62bb5
Fix search_after field values (#2679)
Closes #2678

(cherry picked from commit 9adc4d2b368fc600e58ac5d15c02cdc78c0dd743)
2023-08-28 20:27:21 +02:00
Mark Paluch
063020f8b3
After release cleanups.
See #2631
2023-08-18 14:07:36 +02:00
Mark Paluch
0c98c419c9
Prepare next development iteration.
See #2631
2023-08-18 14:07:34 +02:00
Mark Paluch
3f085b2675
Release version 5.1.3 (2023.0.3).
See #2631
2023-08-18 14:04:04 +02:00
Mark Paluch
42aeb48b43
Prepare 5.1.3 (2023.0.3).
See #2631
2023-08-18 14:03:49 +02:00
Julia Lee
449910b4f7
Update CI properties.
See #2631
2023-08-14 11:29:43 -04:00
Julia Lee
2e99f5b2e0
Upgrade to Maven Wrapper 3.9.4.
See #2669
2023-08-14 07:55:32 -04:00
Peter-Josef Meisch
9b9136d852 Fix similarity field mapping.
Original Pull Request #2666
Closes #2659

(cherry picked from commit 8c5ff92cd2ec2177452dc0aa1b9307bdfcfa4e75)
2023-08-13 21:40:31 +02:00
Peter-Josef Meisch
a266d7c46a
Upgrade deprecated dependency to Elasticsearch 7.17.12.
Original Pull Request #2655
#Closes #2651
2023-07-30 19:51:01 +02:00
Peter-Josef Meisch
c045a8ae29
Fix MappingElasticsearchConverter.
Original Pull Request #2637
Closes #2627

(cherry picked from commit d9bb9911f91f2da8723e579fb3962ecf13a5a651)
2023-07-18 22:51:45 +02:00
Mark Paluch
11c87a1251
After release cleanups.
See #2595
2023-07-14 13:57:59 +02:00
Mark Paluch
c9e9bf757e
Prepare next development iteration.
See #2595
2023-07-14 13:57:58 +02:00
Mark Paluch
db8d89aeff
Release version 5.1.2 (2023.0.2).
See #2595
2023-07-14 13:54:08 +02:00
Mark Paluch
0ed14e7caa
Prepare 5.1.2 (2023.0.2).
See #2595
2023-07-14 13:52:55 +02:00
Peter-Josef Meisch
d0658affc3
Upgrade to Elasticsearch 7.17.11.
Original Pull Request #2625
Closes #2622
2023-07-12 20:05:40 +02:00
Mark Paluch
7c10128cec
Update CI properties.
See #2595
2023-07-03 09:49:00 +02:00
Mark Paluch
6e3535d68d
Upgrade to Maven Wrapper 3.9.3.
See #2614
2023-07-03 09:48:29 +02:00
Peter-Josef Meisch
121b47e1be
Fix IndicesBoost error.
Original Pull Request #2606
Closes #2598

(cherry picked from commit d9fd722bb6af81068fb9b723b77c60efddbf06d3)
2023-06-27 22:28:16 +02:00
Greg L. Turnquist
3abe6d9c1b
Stop posting build status on internal Slack.
See #2603
2023-06-26 13:38:20 -05:00
seunghyun.cheong
d43b44ba9c
Adding GeoDistanceOrder's direction in request.
Original Pull Request #2602
Closes #2601

(cherry picked from commit 8a164b103937d6911f388ecd106996578119a599)

Polishing

(cherry picked from commit b7570ffa957254d114e161cf73e173135fb3ee54)

add implementation for old client
2023-06-24 11:16:14 +02:00
John Blum
a715d2836d
After release cleanups.
See #2548
2023-06-16 08:13:31 -07:00
John Blum
a69b95867a
Prepare next development iteration.
See #2548
2023-06-16 08:13:28 -07:00
John Blum
d424195c8b
Release version 5.1.1 (2023.0.1).
See #2548
2023-06-16 08:05:37 -07:00
John Blum
44d1614a20
Prepare 5.1.1 (2023.0.1).
See #2548
2023-06-16 08:05:07 -07:00
Mark Paluch
7b6823cc31
Upgrade to Maven Wrapper 3.9.2.
See #2588
2023-06-13 08:54:05 +02:00
Mark Paluch
2e43c7800b
Reformat pom.xml.
See #2585
2023-06-06 10:57:04 +02:00
Mark Paluch
59968e8118
Use snapshot and milestone repositories instead of libs-snapshot and libs-milestone.
Closes #2585
2023-06-06 10:56:48 +02:00
Peter-Josef Meisch
a5934442bf
Fix reactive save of Flux.
Original Pull Request #2581
Closes #2576

(cherry picked from commit d6b55406142abe2f72d2da29f7180621d0380b08)
2023-06-02 17:39:16 +02:00
Peter-Josef Meisch
89afa819f3
Polishing
(cherry picked from commit 6edd3cf1fe98d11ddd4b42102b01b84e8a2c0e0f)
2023-05-17 20:23:23 +02:00
Pierre Mazieres @Semarchy
5561a5b1ae
"BaseQuery" class : the "build" method does not apply to the "runtimeFields" field.
Original Pull Request #2568
Closes #2567

(cherry picked from commit 7b527c44511d0e45e0246ae2ee758cd522685aeb)
2023-05-17 20:23:23 +02:00
Peter-Josef Meisch
23a5071ee5
Upgrade to Elasticsearch 8.7.1.
Closes #2541

(cherry picked from commit af924c2cbcab1ab25f80ab4c446356e7ebde3339)
2023-05-12 22:35:53 +02:00
Peter-Josef Meisch
d1324a26db
Documentation misses link to migration page 5.0 -> 5.1.
Original Pull Request #2554
Closes #2553
2023-05-12 18:59:21 +02:00
Mark Paluch
34e3e8f5da
Update Jenkins triggers after GA release.
See #2532
2023-05-12 14:47:15 +02:00
Christoph Strobl
1571b9b4e2
After release cleanups.
See #2532
2023-05-12 14:19:11 +02:00
Christoph Strobl
78e7dd2764
Prepare next development iteration.
See #2532
2023-05-12 14:19:10 +02:00
37 changed files with 1233 additions and 648 deletions

View File

@ -1,3 +1,3 @@
#Thu Apr 06 16:16:37 CEST 2023
#Thu Dec 14 08:37:40 CET 2023
wrapperUrl=https\://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
distributionUrl=https\://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.1/apache-maven-3.9.1-bin.zip
distributionUrl=https\://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip

25
Jenkinsfile vendored
View File

@ -9,7 +9,7 @@ pipeline {
triggers {
pollSCM 'H/10 * * * *'
upstream(upstreamProjects: "spring-data-commons/main", threshold: hudson.model.Result.SUCCESS)
upstream(upstreamProjects: "spring-data-commons/3.1.x", threshold: hudson.model.Result.SUCCESS)
}
options {
@ -38,8 +38,8 @@ pipeline {
steps {
script {
docker.image(p['docker.java.main.image']).inside(p['docker.java.inside.docker']) {
sh 'PROFILE=none ci/verify.sh'
sh "ci/clean.sh"
sh "PROFILE=none JENKINS_USER_NAME=${p['jenkins.user.name']} ci/verify.sh"
sh "JENKINS_USER_NAME=${p['jenkins.user.name']} ci/clean.sh"
}
}
}
@ -65,8 +65,8 @@ pipeline {
steps {
script {
docker.image(p['docker.java.next.image']).inside(p['docker.java.inside.docker']) {
sh 'PROFILE=none ci/verify.sh'
sh "ci/clean.sh"
sh "PROFILE=none JENKINS_USER_NAME=${p['jenkins.user.name']} ci/verify.sh"
sh "JENKINS_USER_NAME=${p['jenkins.user.name']} ci/clean.sh"
}
}
}
@ -86,22 +86,21 @@ pipeline {
label 'data'
}
options { timeout(time: 20, unit: 'MINUTES') }
environment {
ARTIFACTORY = credentials("${p['artifactory.credentials']}")
}
steps {
script {
docker.image(p['docker.java.main.image']).inside(p['docker.java.inside.basic']) {
sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -s settings.xml -Pci,artifactory -Dmaven.repo.local=/tmp/jenkins-home/.m2/spring-data-elasticsearch-non-root ' +
'-Dartifactory.server=https://repo.spring.io ' +
sh 'MAVEN_OPTS="-Duser.name=' + "${p['jenkins.user.name']}" + ' -Duser.home=/tmp/jenkins-home" ' +
"./mvnw -s settings.xml -Pci,artifactory -Dmaven.repo.local=/tmp/jenkins-home/.m2/spring-data-elasticsearch-non-root " +
"-Dartifactory.server=${p['artifactory.url']} " +
"-Dartifactory.username=${ARTIFACTORY_USR} " +
"-Dartifactory.password=${ARTIFACTORY_PSW} " +
"-Dartifactory.staging-repository=libs-snapshot-local " +
"-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'
"-Dmaven.test.skip=true clean deploy -U -B"
}
}
}
@ -111,10 +110,6 @@ pipeline {
post {
changed {
script {
slackSend(
color: (currentBuild.currentResult == 'SUCCESS') ? 'good' : 'danger',
channel: '#spring-data-dev',
message: "${currentBuild.fullDisplayName} - `${currentBuild.currentResult}`\n${env.BUILD_URL}")
emailext(
subject: "[${currentBuild.fullDisplayName}] ${currentBuild.currentResult}",
mimeType: 'text/html',

View File

@ -137,9 +137,9 @@ To use the Release candidate versions of the upcoming major version, use our Mav
</dependency>
<repository>
<id>spring-libs-snapshot</id>
<id>spring-snapshot</id>
<name>Spring Snapshot Repository</name>
<url>https://repo.spring.io/libs-milestone</url>
<url>https://repo.spring.io/milestone</url>
</repository>
----
@ -154,9 +154,9 @@ If you'd rather like the latest snapshots of the upcoming major version, use our
</dependency>
<repository>
<id>spring-libs-snapshot</id>
<id>spring-snapshot</id>
<name>Spring Snapshot Repository</name>
<url>https://repo.spring.io/libs-snapshot</url>
<url>https://repo.spring.io/snapshot</url>
</repository>
----

View File

@ -2,5 +2,7 @@
set -euo pipefail
MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" \
export JENKINS_USER=${JENKINS_USER_NAME}
MAVEN_OPTS="-Duser.name=${JENKINS_USER} -Duser.home=/tmp/jenkins-home" \
./mvnw -s settings.xml clean -Dmaven.repo.local=/tmp/jenkins-home/.m2/spring-data-elasticsearch

View File

@ -1,5 +1,5 @@
# Java versions
java.main.tag=17.0.6_10-jdk-focal
java.main.tag=17.0.9_9-jdk-focal
java.next.tag=20-jdk-jammy
# Docker container images - standard
@ -7,15 +7,15 @@ docker.java.main.image=harbor-repo.vmware.com/dockerhub-proxy-cache/library/ecli
docker.java.next.image=harbor-repo.vmware.com/dockerhub-proxy-cache/library/eclipse-temurin:${java.next.tag}
# Supported versions of MongoDB
docker.mongodb.4.4.version=4.4.18
docker.mongodb.5.0.version=5.0.14
docker.mongodb.6.0.version=6.0.4
docker.mongodb.4.4.version=4.4.25
docker.mongodb.5.0.version=5.0.21
docker.mongodb.6.0.version=6.0.10
# Supported versions of Redis
docker.redis.6.version=6.2.10
docker.redis.6.version=6.2.13
# Supported versions of Cassandra
docker.cassandra.3.version=3.11.14
docker.cassandra.3.version=3.11.16
# Docker environment settings
docker.java.inside.basic=-v $HOME:/tmp/jenkins-home
@ -25,3 +25,6 @@ docker.java.inside.docker=-u root -v /var/run/docker.sock:/var/run/docker.sock -
docker.registry=
docker.credentials=hub.docker.com-springbuildmaster
artifactory.credentials=02bd1690-b54f-4c9f-819d-a77cb7a9822c
artifactory.url=https://repo.spring.io
artifactory.repository.snapshot=libs-snapshot-local
jenkins.user.name=spring-builds+jenkins

View File

@ -5,6 +5,8 @@ set -euo pipefail
mkdir -p /tmp/jenkins-home/.m2/spring-data-elasticsearch
chown -R 1001:1001 .
MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" \
export JENKINS_USER=${JENKINS_USER_NAME}
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

917
pom.xml
View File

@ -1,486 +1,471 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>5.1.0</version>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>5.1.7</version>
<parent>
<groupId>org.springframework.data.build</groupId>
<artifactId>spring-data-parent</artifactId>
<version>3.1.0</version>
</parent>
<parent>
<groupId>org.springframework.data.build</groupId>
<artifactId>spring-data-parent</artifactId>
<version>3.1.7</version>
</parent>
<name>Spring Data Elasticsearch</name>
<description>Spring Data Implementation for Elasticsearch</description>
<name>Spring Data Elasticsearch</name>
<description>Spring Data Implementation for Elasticsearch</description>
<url>https://github.com/spring-projects/spring-data-elasticsearch</url>
<properties>
<springdata.commons>3.1.7</springdata.commons>
<!-- version of the RestHighLevelClient -->
<elasticsearch-rhlc>7.17.15</elasticsearch-rhlc>
<!-- version of the new ElasticsearchClient -->
<elasticsearch-java>8.7.1</elasticsearch-java>
<log4j>2.18.0</log4j>
<!-- netty dependency can be removed once the WebClient code is gone -->
<netty>4.1.90.Final</netty>
<blockhound-junit>1.0.8.RELEASE</blockhound-junit>
<hoverfly>0.14.4</hoverfly>
<jsonassert>1.5.1</jsonassert>
<testcontainers>1.18.0</testcontainers>
<wiremock>2.35.0</wiremock>
<java-module-name>spring.data.elasticsearch</java-module-name>
<!--
properties defining the maven phase for the tests and integration tests
set to "none" to disable the corresponding test execution (-Dmvn.unit-test.goal=none)
default execution for unit-test: "test", for the integration tests: "integration-test"
-->
<mvn.unit-test.goal>test</mvn.unit-test.goal>
<mvn.integration-test-elasticsearch.goal>integration-test</mvn.integration-test-elasticsearch.goal>
</properties>
<developers>
<developer>
<id>biomedcentral</id>
<name>BioMed Central Development Team</name>
<timezone>+0</timezone>
</developer>
<developer>
<id>cstrobl</id>
<name>Christoph Strobl</name>
<email>cstrobl at pivotal.io</email>
<organization>Pivotal</organization>
<organizationUrl>https://www.pivotal.io</organizationUrl>
<roles>
<role>Developer</role>
</roles>
<timezone>+1</timezone>
</developer>
<developer>
<id>mpaluch</id>
<name>Mark Paluch</name>
<email>mpaluch at pivotal.io</email>
<organization>Pivotal</organization>
<organizationUrl>https://www.pivotal.io</organizationUrl>
<roles>
<role>Developer</role>
</roles>
<timezone>+1</timezone>
</developer>
</developers>
<scm>
<url>https://github.com/spring-projects/spring-data-elasticsearch</url>
<connection>scm:git:git://github.com/spring-projects/spring-data-elasticsearch.git</connection>
<developerConnection>scm:git:ssh://git@github.com/spring-projects/spring-data-elasticsearch.git
</developerConnection>
</scm>
<properties>
<springdata.commons>3.1.0</springdata.commons>
<ciManagement>
<system>Bamboo</system>
<url>https://build.spring.io/browse/SPRINGDATAES</url>
</ciManagement>
<!-- version of the RestHighLevelClient -->
<elasticsearch-rhlc>7.17.9</elasticsearch-rhlc>
<!-- version of the new ElasticsearchClient -->
<elasticsearch-java>8.7.0</elasticsearch-java>
<log4j>2.18.0</log4j>
<!-- netty dependency can be removed once the WebClient code is gone -->
<netty>4.1.90.Final</netty>
<blockhound-junit>1.0.8.RELEASE</blockhound-junit>
<hoverfly>0.14.4</hoverfly>
<jsonassert>1.5.1</jsonassert>
<testcontainers>1.18.0</testcontainers>
<wiremock>2.35.0</wiremock>
<java-module-name>spring.data.elasticsearch</java-module-name>
<!--
properties defining the maven phase for the tests and integration tests
set to "none" to disable the corresponding test execution (-Dmvn.unit-test.goal=none)
default execution for unit-test: "test", for the integration tests: "integration-test"
-->
<mvn.unit-test.goal>test</mvn.unit-test.goal>
<mvn.integration-test-elasticsearch.goal>integration-test</mvn.integration-test-elasticsearch.goal>
</properties>
<developers>
<developer>
<id>biomedcentral</id>
<name>BioMed Central Development Team</name>
<timezone>+0</timezone>
</developer>
<developer>
<id>cstrobl</id>
<name>Christoph Strobl</name>
<email>cstrobl at pivotal.io</email>
<organization>Pivotal</organization>
<organizationUrl>https://www.pivotal.io</organizationUrl>
<roles>
<role>Developer</role>
</roles>
<timezone>+1</timezone>
</developer>
<developer>
<id>mpaluch</id>
<name>Mark Paluch</name>
<email>mpaluch at pivotal.io</email>
<organization>Pivotal</organization>
<organizationUrl>https://www.pivotal.io</organizationUrl>
<roles>
<role>Developer</role>
</roles>
<timezone>+1</timezone>
</developer>
</developers>
<scm>
<url>https://github.com/spring-projects/spring-data-elasticsearch</url>
<connection>scm:git:git://github.com/spring-projects/spring-data-elasticsearch.git</connection>
<developerConnection>scm:git:ssh://git@github.com/spring-projects/spring-data-elasticsearch.git
</developerConnection>
</scm>
<ciManagement>
<system>Bamboo</system>
<url>https://build.spring.io/browse/SPRINGDATAES</url>
</ciManagement>
<issueManagement>
<system>GitHub</system>
<url>https://github.com/spring-projects/spring-data-elasticsearch/issues</url>
</issueManagement>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-bom</artifactId>
<version>${netty}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<issueManagement>
<system>GitHub</system>
<url>https://github.com/spring-projects/spring-data-elasticsearch/issues</url>
</issueManagement>
<dependencyManagement>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>
<!-- SPRING DATA -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
<version>${springdata.commons}</version>
</dependency>
<!-- Reactive Infrastructure -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webflux</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.projectreactor.netty</groupId>
<artifactId>reactor-netty-http</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
<!-- optional Elasticsearch RestHighLevelClient, deprecated in SDE 5.0 -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>${elasticsearch-rhlc}</version>
<optional>true</optional>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- new Elasticsearch client, needs the low-level rest client and json api -->
<dependency>
<groupId>co.elastic.clients</groupId>
<artifactId>elasticsearch-java</artifactId>
<version>${elasticsearch-java}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId> <!-- is Apache 2-->
<version>${elasticsearch-java}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Jackson JSON Mapper -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- CDI -->
<dependency>
<groupId>javax.interceptor</groupId>
<artifactId>javax.interceptor-api</artifactId>
<version>1.2.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>jakarta.enterprise</groupId>
<artifactId>jakarta.enterprise.cdi-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<version>${jakarta-annotation-api}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.openwebbeans</groupId>
<artifactId>openwebbeans-se</artifactId>
<classifier>jakarta</classifier>
<version>${webbeans}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.openwebbeans</groupId>
<artifactId>openwebbeans-spi</artifactId>
<classifier>jakarta</classifier>
<version>${webbeans}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.openwebbeans</groupId>
<artifactId>openwebbeans-impl</artifactId>
<classifier>jakarta</classifier>
<version>${webbeans}</version>
<scope>test</scope>
</dependency>
<!-- Test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>${slf4j}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
<version>${log4j}</version>
<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>
<version>${jsonassert}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock-jre8</artifactId>
<version>${wiremock}</version>
<scope>test</scope>
<exclusions>
<!-- these exclusions are needed because of Elasticsearch JarHell-->
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
<exclusion>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.specto</groupId>
<artifactId>hoverfly-java-junit5</artifactId>
<version>${hoverfly}</version>
<scope>test</scope>
</dependency>
<!-- Upgrade xbean to 4.5 to prevent incompatibilities due to ASM versions -->
<dependency>
<groupId>org.apache.xbean</groupId>
<artifactId>xbean-asm5-shaded</artifactId>
<version>4.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>${mockito}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>elasticsearch</artifactId>
<version>${testcontainers}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-bom</artifactId>
<version>${netty}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/versions.properties</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<excludes>
<exclude>**/versions.properties</exclude>
</excludes>
</resource>
</resources>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>
<!-- SPRING DATA -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
<version>${springdata.commons}</version>
</dependency>
<!-- Reactive Infrastructure -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webflux</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.projectreactor.netty</groupId>
<artifactId>reactor-netty-http</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
<!-- optional Elasticsearch RestHighLevelClient, deprecated in SDE 5.0 -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>${elasticsearch-rhlc}</version>
<optional>true</optional>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- new Elasticsearch client, needs the low-level rest client and json api -->
<dependency>
<groupId>co.elastic.clients</groupId>
<artifactId>elasticsearch-java</artifactId>
<version>${elasticsearch-java}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId> <!-- is Apache 2-->
<version>${elasticsearch-java}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Jackson JSON Mapper -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- CDI -->
<dependency>
<groupId>javax.interceptor</groupId>
<artifactId>javax.interceptor-api</artifactId>
<version>1.2.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>jakarta.enterprise</groupId>
<artifactId>jakarta.enterprise.cdi-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<version>${jakarta-annotation-api}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.openwebbeans</groupId>
<artifactId>openwebbeans-se</artifactId>
<classifier>jakarta</classifier>
<version>${webbeans}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.openwebbeans</groupId>
<artifactId>openwebbeans-spi</artifactId>
<classifier>jakarta</classifier>
<version>${webbeans}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.openwebbeans</groupId>
<artifactId>openwebbeans-impl</artifactId>
<classifier>jakarta</classifier>
<version>${webbeans}</version>
<scope>test</scope>
</dependency>
<!-- Test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>${slf4j}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
<version>${log4j}</version>
<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>
<version>${jsonassert}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock-jre8</artifactId>
<version>${wiremock}</version>
<scope>test</scope>
<exclusions>
<!-- these exclusions are needed because of Elasticsearch JarHell-->
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
<exclusion>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.specto</groupId>
<artifactId>hoverfly-java-junit5</artifactId>
<version>${hoverfly}</version>
<scope>test</scope>
</dependency>
<!-- Upgrade xbean to 4.5 to prevent incompatibilities due to ASM versions -->
<dependency>
<groupId>org.apache.xbean</groupId>
<artifactId>xbean-asm5-shaded</artifactId>
<version>4.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>${mockito}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>elasticsearch</artifactId>
<version>${testcontainers}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/versions.properties</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<excludes>
<exclude>**/versions.properties</exclude>
</excludes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<useSystemClassLoader>true</useSystemClassLoader>
<useFile>false</useFile>
<includes>
<include>**/*Tests.java</include>
<include>**/*Test.java</include>
</includes>
<systemPropertyVariables>
<es.set.netty.runtime.available.processors>false</es.set.netty.runtime.available.processors>
</systemPropertyVariables>
</configuration>
<executions>
<!-- the default-test execution runs only the unit tests -->
<execution>
<id>default-test</id>
<phase>${mvn.unit-test.goal}</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<excludedGroups>integration-test</excludedGroups>
</configuration>
</execution>
<!-- execution to run the integration tests against Elasticsearch -->
<execution>
<id>integration-test-elasticsearch</id>
<phase>${mvn.integration-test-elasticsearch.goal}</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<groups>integration-test</groups>
<systemPropertyVariables>
<sde.integration-test.environment>elasticsearch</sde.integration-test.environment>
</systemPropertyVariables>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>ci</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<useSystemClassLoader>true</useSystemClassLoader>
<useFile>false</useFile>
<includes>
<include>**/*Tests.java</include>
<include>**/*Test.java</include>
</includes>
<systemPropertyVariables>
<es.set.netty.runtime.available.processors>false</es.set.netty.runtime.available.processors>
</systemPropertyVariables>
</configuration>
<executions>
<!-- the default-test execution runs only the unit tests -->
<execution>
<id>default-test</id>
<phase>${mvn.unit-test.goal}</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<excludedGroups>integration-test</excludedGroups>
</configuration>
</execution>
<!-- execution to run the integration tests against Elasticsearch -->
<execution>
<id>integration-test-elasticsearch</id>
<phase>${mvn.integration-test-elasticsearch.goal}</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<groups>integration-test</groups>
<systemPropertyVariables>
<sde.integration-test.environment>elasticsearch</sde.integration-test.environment>
</systemPropertyVariables>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<configuration>
<checkstyleRules>
<module name="Checker">
<!-- Configure checker to use UTF-8 encoding -->
<property name="charset" value="UTF-8"/>
<module name="io.spring.nohttp.checkstyle.check.NoHttpCheck"/>
</module>
</checkstyleRules>
<includes>**/*</includes>
<excludes>
.git/**/*,target/**/*,**/target/**/*,.idea/**/*,**/spring.schemas,**/*.svg,mvnw,mvnw.cmd,**/*.policy
</excludes>
<sourceDirectories>./</sourceDirectories>
</configuration>
</plugin>
</plugins>
</build>
</build>
</profile>
<profiles>
<profile>
<id>ci</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<configuration>
<checkstyleRules>
<module name="Checker">
<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>
</profiles>
<!-- Configure checker to use UTF-8 encoding -->
<property name="charset" value="UTF-8"/>
<module name="io.spring.nohttp.checkstyle.check.NoHttpCheck"/>
</module>
</checkstyleRules>
<includes>**/*</includes>
<excludes>
.git/**/*,target/**/*,**/target/**/*,.idea/**/*,**/spring.schemas,**/*.svg,mvnw,mvnw.cmd,**/*.policy
</excludes>
<sourceDirectories>./</sourceDirectories>
</configuration>
</plugin>
</plugins>
</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>
</profiles>
<repositories>
<repository>
<id>spring-libs-release</id>
<url>https://repo.spring.io/libs-release</url>
</repository>
<repository>
<id>local-maven-repo</id>
<url>file:///${project.basedir}/src/test/resources/local-maven-repo</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-plugins-release</id>
<url>https://repo.spring.io/plugins-release</url>
</pluginRepository>
</pluginRepositories>
<repositories>
</repositories>
</project>

View File

@ -17,9 +17,9 @@ include::reference/elasticsearch-new.adoc[leveloffset=+1]
* Version Control - https://github.com/spring-projects/spring-data-elasticsearch
* API Documentation - https://docs.spring.io/spring-data/elasticsearch/docs/current/api/
* Bugtracker - https://github.com/spring-projects/spring-data-elasticsearch/issues
* Release repository - https://repo.spring.io/libs-release
* Milestone repository - https://repo.spring.io/libs-milestone
* Snapshot repository - https://repo.spring.io/libs-snapshot
* Release repository - https://repo1.maven.org/maven2/
* Milestone repository - https://repo.spring.io/milestone/
* Snapshot repository - https://repo.spring.io/snapshot/
[[preface.requirements]]
== Requirements
@ -37,7 +37,7 @@ built and tested.
[cols="^,^,^,^,^",options="header"]
|===
| Spring Data Release Train | Spring Data Elasticsearch | Elasticsearch | Spring Framework | Spring Boot
| 2023.0 (Ullmann) | 5.1.x | 8.7.0 | 6.0.x | 3.1.x
| 2023.0 (Ullmann) | 5.1.x | 8.7.1 | 6.0.x | 3.1.x
| 2022.0 (Turing) | 5.0.x | 8.5.3 | 6.0.x | 3.0.x
| 2021.2 (Raj) | 4.4.xfootnote:oom[Out of maintenance] | 7.17.3 | 5.3.x | 2.7.x
| 2021.1 (Q) | 4.3.xfootnote:oom[] | 7.15.2 | 5.3.x | 2.6.x

View File

@ -15,4 +15,6 @@ include::elasticsearch-migration-guide-4.3-4.4.adoc[]
include::elasticsearch-migration-guide-4.4-5.0.adoc[]
include::elasticsearch-migration-guide-5.0-5.1.adoc[]
:leveloffset: -1

View File

@ -138,7 +138,7 @@ final class DocumentAdapters {
document.setPrimaryTerm(hit.primaryTerm() != null && hit.primaryTerm() > 0 ? hit.primaryTerm() : 0);
float score = hit.score() != null ? hit.score().floatValue() : Float.NaN;
return new SearchDocumentAdapter(document, score, hit.sort().stream().map(TypeUtils::toString).toArray(),
return new SearchDocumentAdapter(document, score, hit.sort().stream().map(TypeUtils::toObject).toArray(),
documentFields, highlightFields, innerHits, nestedMetaData, explanation, matchedQueries, hit.routing());
}

View File

@ -16,18 +16,24 @@
package org.springframework.data.elasticsearch.client.elc;
import static org.springframework.data.elasticsearch.client.elc.TypeUtils.*;
import static org.springframework.util.CollectionUtils.isEmpty;
import static org.springframework.util.CollectionUtils.*;
import co.elastic.clients.elasticsearch._types.*;
import co.elastic.clients.elasticsearch._types.Conflicts;
import co.elastic.clients.elasticsearch._types.InlineScript;
import co.elastic.clients.elasticsearch._types.OpType;
import co.elastic.clients.elasticsearch._types.SortOptions;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.VersionType;
import co.elastic.clients.elasticsearch._types.WaitForActiveShardOptions;
import co.elastic.clients.elasticsearch._types.mapping.FieldType;
import co.elastic.clients.elasticsearch._types.mapping.RuntimeField;
import co.elastic.clients.elasticsearch._types.mapping.RuntimeFieldType;
import co.elastic.clients.elasticsearch._types.query_dsl.FieldAndFormat;
import co.elastic.clients.elasticsearch._types.query_dsl.Like;
import co.elastic.clients.elasticsearch.cluster.*;
import co.elastic.clients.elasticsearch.cluster.DeleteComponentTemplateRequest;
import co.elastic.clients.elasticsearch.cluster.ExistsComponentTemplateRequest;
import co.elastic.clients.elasticsearch.cluster.GetComponentTemplateRequest;
import co.elastic.clients.elasticsearch.cluster.HealthRequest;
import co.elastic.clients.elasticsearch.cluster.PutComponentTemplateRequest;
import co.elastic.clients.elasticsearch.core.*;
import co.elastic.clients.elasticsearch.core.bulk.BulkOperation;
@ -52,7 +58,12 @@ import java.io.ByteArrayInputStream;
import java.io.StringReader;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
@ -988,7 +999,7 @@ class RequestConverter {
.docAsUpsert(query.getDocAsUpsert()) //
.ifSeqNo(query.getIfSeqNo() != null ? Long.valueOf(query.getIfSeqNo()) : null) //
.ifPrimaryTerm(query.getIfPrimaryTerm() != null ? Long.valueOf(query.getIfPrimaryTerm()) : null) //
.refresh(refresh(refreshPolicy)) //
.refresh(query.getRefreshPolicy() != null ? refresh(query.getRefreshPolicy()) : refresh(refreshPolicy)) //
.retryOnConflict(query.getRetryOnConflict()) //
;
@ -1175,10 +1186,9 @@ class RequestConverter {
}
if (!isEmpty(query.getFields())) {
bb.fields(fb -> {
query.getFields().forEach(fb::field);
return fb;
});
var fieldAndFormats = query.getFields().stream()
.map(field -> FieldAndFormat.of(b -> b.field(field))).toList();
bb.fields(fieldAndFormats);
}
if (!isEmpty(query.getStoredFields())) {
@ -1208,8 +1218,7 @@ class RequestConverter {
}
if (!isEmpty(query.getSearchAfter())) {
bb.searchAfter(query.getSearchAfter().stream().map(it -> FieldValue.of(it.toString()))
.collect(Collectors.toList()));
bb.searchAfter(query.getSearchAfter().stream().map(TypeUtils::toFieldValue).toList());
}
query.getRescorerQueries().forEach(rescorerQuery -> bb.rescore(getRescore(rescorerQuery)));
@ -1233,11 +1242,9 @@ class RequestConverter {
}
if (!isEmpty(query.getIndicesBoost())) {
Map<String, Double> boosts = new LinkedHashMap<>();
query.getIndicesBoost()
.forEach(indexBoost -> boosts.put(indexBoost.getIndexName(), (double) indexBoost.getBoost()));
// noinspection unchecked
bb.indicesBoost(boosts);
bb.indicesBoost(query.getIndicesBoost().stream()
.map(indexBoost -> Map.of(indexBoost.getIndexName(), Double.valueOf(indexBoost.getBoost())))
.collect(Collectors.toList()));
}
query.getScriptedFields().forEach(scriptedField -> bb.scriptFields(scriptedField.getFieldName(),
@ -1313,10 +1320,9 @@ class RequestConverter {
}
if (!isEmpty(query.getFields())) {
builder.fields(fb -> {
query.getFields().forEach(fb::field);
return fb;
});
var fieldAndFormats = query.getFields().stream()
.map(field -> FieldAndFormat.of(b -> b.field(field))).toList();
builder.fields(fieldAndFormats);
}
if (!isEmpty(query.getStoredFields())) {
@ -1335,14 +1341,6 @@ class RequestConverter {
builder.minScore((double) query.getMinScore());
}
if (query.getSort() != null) {
List<SortOptions> sortOptions = getSortOptions(query.getSort(), persistentEntity);
if (!sortOptions.isEmpty()) {
builder.sort(sortOptions);
}
}
addHighlight(query, builder);
query.getScriptedFields().forEach(scriptedField -> builder.scriptFields(scriptedField.getFieldName(),
@ -1351,6 +1349,15 @@ class RequestConverter {
if (query instanceof NativeQuery) {
prepareNativeSearch((NativeQuery) query, builder);
}
// query.getSort() must be checked after prepareNativeSearch as this already might hav a sort set that must have
// higher priority
if (query.getSort() != null) {
List<SortOptions> sortOptions = getSortOptions(query.getSort(), persistentEntity);
if (!sortOptions.isEmpty()) {
builder.sort(sortOptions);
}
}
if (query.getTrackTotalHits() != null) {
// logic from the RHLC, choose between -1 and Integer.MAX_VALUE
@ -1365,8 +1372,7 @@ class RequestConverter {
}
if (!isEmpty(query.getSearchAfter())) {
builder.searchAfter(
query.getSearchAfter().stream().map(it -> FieldValue.of(it.toString())).collect(Collectors.toList()));
builder.searchAfter(query.getSearchAfter().stream().map(TypeUtils::toFieldValue).toList());
}
query.getRescorerQueries().forEach(rescorerQuery -> builder.rescore(getRescore(rescorerQuery)));
@ -1399,11 +1405,9 @@ class RequestConverter {
}
if (!isEmpty(query.getIndicesBoost())) {
Map<String, Double> boosts = new LinkedHashMap<>();
query.getIndicesBoost()
.forEach(indexBoost -> boosts.put(indexBoost.getIndexName(), (double) indexBoost.getBoost()));
// noinspection unchecked
builder.indicesBoost(boosts);
builder.indicesBoost(query.getIndicesBoost().stream()
.map(indexBoost -> Map.of(indexBoost.getIndexName(), Double.valueOf(indexBoost.getBoost())))
.collect(Collectors.toList()));
}
if (!isEmpty(query.getDocValueFields())) {
@ -1477,8 +1481,9 @@ class RequestConverter {
return SortOptions.of(so -> so //
.geoDistance(gd -> gd //
.field(fieldName) //
.location(loc -> loc.latlon(Queries.latLon(geoDistanceOrder.getGeoPoint())))//
.location(loc -> loc.latlon(Queries.latLon(geoDistanceOrder.getGeoPoint()))) //
.distanceType(geoDistanceType(geoDistanceOrder.getDistanceType())).mode(sortMode(finalMode)) //
.order(sortOrder(geoDistanceOrder.getDirection())) //
.unit(distanceUnit(geoDistanceOrder.getUnit())) //
.ignoreUnmapped(geoDistanceOrder.getIgnoreUnmapped())));
} else {
@ -1537,8 +1542,11 @@ class RequestConverter {
builder //
.suggest(query.getSuggester()) //
.collapse(query.getFieldCollapse()) //
.sort(query.getSortOptions()) //
.knn(query.getKnnQuery());
.sort(query.getSortOptions());
if (query.getKnnQuery() != null) {
builder.knn(query.getKnnQuery());
}
if (!isEmpty(query.getAggregations())) {
builder.aggregations(query.getAggregations());

View File

@ -219,7 +219,8 @@ class SearchDocumentResponseBuilder {
var phraseSuggestOptions = phraseSuggest.options();
List<PhraseSuggestion.Entry.Option> options = new ArrayList<>();
phraseSuggestOptions.forEach(optionES -> options
.add(new PhraseSuggestion.Entry.Option(optionES.text(), optionES.highlighted(), null, null)));
.add(new PhraseSuggestion.Entry.Option(optionES.text(), optionES.highlighted(), optionES.score(),
optionES.collateMatch())));
entries.add(new PhraseSuggestion.Entry(phraseSuggest.text(), phraseSuggest.offset(), phraseSuggest.length(),
options, null));
});

View File

@ -18,8 +18,15 @@ package org.springframework.data.elasticsearch.client.elc;
import co.elastic.clients.elasticsearch._types.*;
import co.elastic.clients.elasticsearch._types.mapping.FieldType;
import co.elastic.clients.elasticsearch._types.mapping.TypeMapping;
import co.elastic.clients.elasticsearch.core.search.*;
import co.elastic.clients.elasticsearch.core.search.BoundaryScanner;
import co.elastic.clients.elasticsearch.core.search.HighlighterEncoder;
import co.elastic.clients.elasticsearch.core.search.HighlighterFragmenter;
import co.elastic.clients.elasticsearch.core.search.HighlighterOrder;
import co.elastic.clients.elasticsearch.core.search.HighlighterTagsSchema;
import co.elastic.clients.elasticsearch.core.search.HighlighterType;
import co.elastic.clients.elasticsearch.core.search.ScoreMode;
import co.elastic.clients.elasticsearch.indices.IndexSettings;
import co.elastic.clients.json.JsonData;
import java.io.StringReader;
import java.time.Duration;
@ -28,10 +35,16 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.RefreshPolicy;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.data.elasticsearch.core.query.*;
import org.springframework.data.elasticsearch.core.query.GeoDistanceOrder;
import org.springframework.data.elasticsearch.core.query.IndexQuery;
import org.springframework.data.elasticsearch.core.query.IndicesOptions;
import org.springframework.data.elasticsearch.core.query.Order;
import org.springframework.data.elasticsearch.core.query.Query;
import org.springframework.data.elasticsearch.core.query.RescorerQuery;
import org.springframework.data.elasticsearch.core.query.UpdateResponse;
import org.springframework.data.elasticsearch.core.reindex.ReindexRequest;
import org.springframework.lang.Nullable;
@ -155,6 +168,40 @@ final class TypeUtils {
}
}
@Nullable
static FieldValue toFieldValue(@Nullable Object fieldValue) {
if (fieldValue == null) {
return FieldValue.NULL;
}
if (fieldValue instanceof Boolean b) {
return b ? FieldValue.TRUE : FieldValue.FALSE;
}
if (fieldValue instanceof String s) {
return FieldValue.of(s);
}
if (fieldValue instanceof Long l) {
return FieldValue.of(l);
}
if (fieldValue instanceof Integer i) {
return FieldValue.of((long) i);
}
if (fieldValue instanceof Double d) {
return FieldValue.of(d);
}
if (fieldValue instanceof Float f) {
return FieldValue.of((double) f);
}
return FieldValue.of(JsonData.of(fieldValue));
}
@Nullable
static GeoDistanceType geoDistanceType(GeoDistanceOrder.DistanceType distanceType) {
@ -165,6 +212,20 @@ final class TypeUtils {
}
@Nullable
static SortOrder sortOrder(@Nullable Sort.Direction direction) {
if (direction == null) {
return null;
}
return switch (direction) {
case ASC -> SortOrder.Asc;
case DESC -> SortOrder.Desc;
};
}
@Nullable
static HighlighterFragmenter highlighterFragmenter(@Nullable String value) {

View File

@ -348,8 +348,8 @@ class RequestFactory {
for (String aliasName : parametersAliases) {
Alias alias = new Alias(aliasName);
//noinspection DuplicatedCode
if (parameters.getRouting() != null) {
// noinspection DuplicatedCode
if (parameters.getRouting() != null) {
alias.routing(parameters.getRouting());
}
@ -526,7 +526,8 @@ class RequestFactory {
// endregion
// region delete
public DeleteByQueryRequest deleteByQueryRequest(Query query, @Nullable String routing, Class<?> clazz, IndexCoordinates index) {
public DeleteByQueryRequest deleteByQueryRequest(Query query, @Nullable String routing, Class<?> clazz,
IndexCoordinates index) {
SearchRequest searchRequest = searchRequest(query, routing, clazz, index);
DeleteByQueryRequest deleteByQueryRequest = new DeleteByQueryRequest(index.getIndexNames()) //
.setQuery(searchRequest.source().query()) //
@ -754,10 +755,11 @@ class RequestFactory {
return searchRequest;
}
public SearchRequest searchRequest(Query query, @Nullable String routing, @Nullable Class<?> clazz, IndexCoordinates index) {
public SearchRequest searchRequest(Query query, @Nullable String routing, @Nullable Class<?> clazz,
IndexCoordinates index) {
elasticsearchConverter.updateQuery(query, clazz);
SearchRequest searchRequest = prepareSearchRequest(query, routing,clazz, index);
SearchRequest searchRequest = prepareSearchRequest(query, routing, clazz, index);
QueryBuilder elasticsearchQuery = getQuery(query);
QueryBuilder elasticsearchFilter = getFilter(query);
@ -771,7 +773,8 @@ class RequestFactory {
}
private SearchRequest prepareSearchRequest(Query query, @Nullable String routing, @Nullable Class<?> clazz, IndexCoordinates indexCoordinates) {
private SearchRequest prepareSearchRequest(Query query, @Nullable String routing, @Nullable Class<?> clazz,
IndexCoordinates indexCoordinates) {
String[] indexNames = indexCoordinates.getIndexNames();
Assert.notNull(indexNames, "No index defined for Query");
@ -968,6 +971,8 @@ class RequestFactory {
sort.ignoreUnmapped(geoDistanceOrder.getIgnoreUnmapped());
}
sort.order(order.isAscending() ? SortOrder.ASC : SortOrder.DESC);
return sort;
} else {
FieldSortBuilder sort = SortBuilders //

View File

@ -225,42 +225,42 @@ abstract public class AbstractReactiveElasticsearchTemplate
return Flux.defer(() -> {
Sinks.Many<T> sink = Sinks.many().unicast().onBackpressureBuffer();
entities //
.bufferTimeout(bulkSize, Duration.ofMillis(200)) //
.subscribe(new Subscriber<List<T>>() {
private Subscription subscription;
private AtomicBoolean upstreamComplete = new AtomicBoolean(false);
entities.window(bulkSize) //
.concatMap(flux -> flux.collectList()) //
.subscribe(new Subscriber<List<T>>() {
private Subscription subscription;
private AtomicBoolean upstreamComplete = new AtomicBoolean(false);
@Override
public void onSubscribe(Subscription subscription) {
this.subscription = subscription;
subscription.request(1);
}
@Override
public void onSubscribe(Subscription subscription) {
this.subscription = subscription;
subscription.request(1);
}
@Override
public void onNext(List<T> entityList) {
saveAll(entityList, index) //
.map(sink::tryEmitNext) //
.doOnComplete(() -> {
if (!upstreamComplete.get()) {
subscription.request(1);
} else {
sink.tryEmitComplete();
}
}).subscribe();
}
@Override
public void onNext(List<T> entityList) {
saveAll(entityList, index) //
.map(sink::tryEmitNext) //
.doOnComplete(() -> {
if (!upstreamComplete.get()) {
subscription.request(1);
} else {
sink.tryEmitComplete();
}
}).subscribe();
}
@Override
public void onError(Throwable throwable) {
subscription.cancel();
sink.tryEmitError(throwable);
}
@Override
public void onError(Throwable throwable) {
subscription.cancel();
sink.tryEmitError(throwable);
}
@Override
public void onComplete() {
upstreamComplete.set(true);
}
});
@Override
public void onComplete() {
upstreamComplete.set(true);
}
});
return sink.asFlux();
});
@ -748,6 +748,12 @@ abstract public class AbstractReactiveElasticsearchTemplate
public abstract Mono<String> getClusterVersion();
@Nullable
public String getEntityRouting(Object entity) {
return entityOperations.forEntity(entity, converter.getConversionService(), routingResolver)
.getRouting();
}
/**
* Value class to capture client independent information from a response to an index request.
*/

View File

@ -117,6 +117,17 @@ public interface ReactiveElasticsearchOperations
ReactiveClusterOperations cluster();
// region routing
/**
* gets the routing for an entity.
*
* @param entity the entity
* @return the routing, may be null if not set.
* @since 5.2
*/
@Nullable
String getEntityRouting(Object entity);
// region customizations
/**
* Returns a copy of this instance with the same configuration, but that uses a different {@link RoutingResolver} to
* obtain routing information.

View File

@ -32,9 +32,19 @@ public abstract class AbstractRangePropertyValueConverter<T> extends AbstractPro
protected static final String LTE_FIELD = "lte";
protected static final String GT_FIELD = "gt";
protected static final String GTE_FIELD = "gte";
private final Class<?> genericType;
public AbstractRangePropertyValueConverter(PersistentProperty<?> property) {
/**
* @param property the property this convertrer belongs to
* @param genericType the generic type of the Range
*/
public AbstractRangePropertyValueConverter(PersistentProperty<?> property, Class<?> genericType) {
super(property);
this.genericType = genericType;
}
public Class<?> getGenericType() {
return genericType;
}
@Override
@ -117,10 +127,6 @@ public abstract class AbstractRangePropertyValueConverter<T> extends AbstractPro
protected abstract String format(T value);
protected Class<?> getGenericType() {
return getProperty().getTypeInformation().getTypeArguments().get(0).getType();
}
protected abstract T parse(String value);
}

View File

@ -33,9 +33,9 @@ public class DateRangePropertyValueConverter extends AbstractRangePropertyValueC
private final List<ElasticsearchDateConverter> dateConverters;
public DateRangePropertyValueConverter(PersistentProperty<?> property,
List<ElasticsearchDateConverter> dateConverters) {
Class<?> genericType, List<ElasticsearchDateConverter> dateConverters) {
super(property);
super(property, genericType);
this.dateConverters = dateConverters;
}

View File

@ -919,7 +919,7 @@ public class MappingElasticsearchConverter
Class<?> elementType = element == null ? null : element.getClass();
if (elementType == null || conversions.isSimpleType(elementType)) {
if (elementType == null || isSimpleType(elementType)) {
collection.add(getPotentiallyConvertedSimpleWrite(element,
componentType != null ? componentType.getType() : Object.class));
} else if (element instanceof Collection || elementType.isArray()) {

View File

@ -23,8 +23,12 @@ import org.springframework.data.mapping.PersistentProperty;
*/
public class NumberRangePropertyValueConverter extends AbstractRangePropertyValueConverter<Number> {
public NumberRangePropertyValueConverter(PersistentProperty<?> property) {
super(property);
/**
* @param property the property this convertrer belongs to
* @param genericType the generic type of the Range
*/
public NumberRangePropertyValueConverter(PersistentProperty<?> property, Class<?> genericType) {
super(property, genericType);
}
@Override

View File

@ -34,9 +34,9 @@ public class TemporalRangePropertyValueConverter extends AbstractRangePropertyVa
private final List<ElasticsearchDateConverter> dateConverters;
public TemporalRangePropertyValueConverter(PersistentProperty<?> property,
List<ElasticsearchDateConverter> dateConverters) {
Class<?> genericType, List<ElasticsearchDateConverter> dateConverters) {
super(property);
super(property, genericType);
Assert.notEmpty(dateConverters, "dateConverters must not be empty.");
this.dateConverters = dateConverters;

View File

@ -332,6 +332,8 @@ public final class MappingParameters {
if (!Similarity.Default.equals(similarity)) {
objectNode.put(FIELD_PARAM_SIMILARITY, similarity);
// similarity must have index explicitly set, otherwise Elasticsearch returns an error
objectNode.put(FIELD_PARAM_INDEX, index);
}
if (termVector != TermVector.none) {

View File

@ -20,6 +20,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.function.Supplier;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@ -56,6 +57,7 @@ import org.springframework.data.mapping.model.FieldNamingStrategy;
import org.springframework.data.mapping.model.Property;
import org.springframework.data.mapping.model.PropertyNameFieldNamingStrategy;
import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
@ -168,6 +170,18 @@ public class SimpleElasticsearchPersistentProperty extends
return;
}
Supplier<Class<?>> getGenericType = () -> {
TypeInformation<?> typeInformation = getTypeInformation();
if (typeInformation.isCollectionLike()) {
// we have a collection of Range<?>
typeInformation = typeInformation.getComponentType();
}
Class<?> genericType = typeInformation.getTypeArguments().get(0).getType();
return genericType;
};
switch (field.type()) {
case Date:
case Date_Nanos: {
@ -197,11 +211,11 @@ public class SimpleElasticsearchPersistentProperty extends
return;
}
Class<?> genericType = getTypeInformation().getTypeArguments().get(0).getType();
var genericType = getGenericType.get();
if (TemporalAccessor.class.isAssignableFrom(genericType)) {
propertyValueConverter = new TemporalRangePropertyValueConverter(this, dateConverters);
propertyValueConverter = new TemporalRangePropertyValueConverter(this, genericType, dateConverters);
} else if (Date.class.isAssignableFrom(genericType)) {
propertyValueConverter = new DateRangePropertyValueConverter(this, dateConverters);
propertyValueConverter = new DateRangePropertyValueConverter(this, genericType, dateConverters);
} else {
LOGGER.warn(
String.format("Unsupported generic type '{%s' for date range property '%s'.", genericType, getName()));
@ -216,7 +230,7 @@ public class SimpleElasticsearchPersistentProperty extends
return;
}
Class<?> genericType = getTypeInformation().getTypeArguments().get(0).getType();
var genericType = getGenericType.get();
if ((field.type() == FieldType.Integer_Range && !Integer.class.isAssignableFrom(genericType))
|| (field.type() == FieldType.Float_Range && !Float.class.isAssignableFrom(genericType))
|| (field.type() == FieldType.Long_Range && !Long.class.isAssignableFrom(genericType))
@ -226,7 +240,7 @@ public class SimpleElasticsearchPersistentProperty extends
return;
}
propertyValueConverter = new NumberRangePropertyValueConverter(this);
propertyValueConverter = new NumberRangePropertyValueConverter(this, genericType);
break;
}
case Ip_Range: {

View File

@ -74,7 +74,7 @@ public class BaseQuery implements Query {
protected List<RescorerQuery> rescorerQueries = new ArrayList<>();
@Nullable protected Boolean requestCache;
protected List<IdWithRouting> idsWithRouting = Collections.emptyList();
protected final List<RuntimeField> runtimeFields = new ArrayList<>();
protected List<RuntimeField> runtimeFields = new ArrayList<>();
@Nullable protected PointInTime pointInTime;
private boolean queryIsUpdatedByConverter = false;
@Nullable private Integer reactiveBatchSize = null;
@ -117,6 +117,7 @@ public class BaseQuery implements Query {
this.expandWildcards = builder.getExpandWildcards();
this.docValueFields = builder.getDocValueFields();
this.scriptedFields = builder.getScriptedFields();
this.runtimeFields = builder.getRuntimeFields();
}
/**

View File

@ -39,6 +39,7 @@ import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.BaseQuery;
import org.springframework.data.elasticsearch.core.query.MoreLikeThisQuery;
import org.springframework.data.elasticsearch.core.query.Query;
import org.springframework.data.elasticsearch.core.routing.RoutingResolver;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.data.util.StreamUtils;
import org.springframework.data.util.Streamable;
@ -223,7 +224,7 @@ public class SimpleElasticsearchRepository<T, ID> implements ElasticsearchReposi
Assert.notNull(id, "Cannot delete entity with id 'null'.");
doDelete(id, getIndexCoordinates());
doDelete(id, null, getIndexCoordinates());
}
@Override
@ -231,7 +232,7 @@ public class SimpleElasticsearchRepository<T, ID> implements ElasticsearchReposi
Assert.notNull(entity, "Cannot delete 'null' entity.");
doDelete(extractIdFromBean(entity), getIndexCoordinates());
doDelete(extractIdFromBean(entity), operations.getEntityRouting(entity), getIndexCoordinates());
}
@Override
@ -271,10 +272,14 @@ public class SimpleElasticsearchRepository<T, ID> implements ElasticsearchReposi
deleteAllById(ids);
}
private void doDelete(@Nullable ID id, IndexCoordinates indexCoordinates) {
private void doDelete(@Nullable ID id, @Nullable String routing, IndexCoordinates indexCoordinates) {
if (id != null) {
executeAndRefresh(operations -> operations.delete(stringIdRepresentation(id), indexCoordinates));
executeAndRefresh(operations -> {
var ops = routing != null ? operations.withRouting(RoutingResolver.just(routing)) : operations;
// noinspection DataFlowIssue
return ops.delete(stringIdRepresentation(id), indexCoordinates);
});
}
}

View File

@ -31,6 +31,7 @@ import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersiste
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.BaseQuery;
import org.springframework.data.elasticsearch.core.query.Query;
import org.springframework.data.elasticsearch.core.routing.RoutingResolver;
import org.springframework.data.elasticsearch.repository.ReactiveElasticsearchRepository;
import org.springframework.util.Assert;
@ -196,7 +197,10 @@ public class SimpleReactiveElasticsearchRepository<T, ID> implements ReactiveEla
public Mono<Void> delete(T entity) {
Assert.notNull(entity, "Entity must not be null!");
return operations.delete(entity, entityInformation.getIndexCoordinates()) //
var routing = operations.getEntityRouting(entity);
var ops = routing != null ? operations.withRouting(RoutingResolver.just(routing)) : operations;
return ops.delete(entity, entityInformation.getIndexCoordinates()) //
.then(doRefresh());
}

View File

@ -1,4 +1,4 @@
Spring Data Elasticsearch 5.1 GA (2023.0.0)
Spring Data Elasticsearch 5.1.7 (2023.0.7)
Copyright (c) [2013-2022] Pivotal Software, Inc.
This product is licensed to you under the Apache License, Version 2.0 (the "License").
@ -13,3 +13,10 @@ conditions of the subcomponent's license, as noted in the LICENSE file.

View File

@ -0,0 +1,111 @@
/*
* Copyright 2023 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.core.search.HitsMetadata;
import co.elastic.clients.elasticsearch.core.search.Suggestion;
import co.elastic.clients.elasticsearch.core.search.TotalHitsRelation;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import java.util.ArrayList;
import java.util.List;
import org.assertj.core.api.SoftAssertions;
import org.json.JSONException;
import org.junit.jupiter.api.Test;
import org.springframework.data.elasticsearch.core.document.SearchDocumentResponse;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
/**
* Tests for the factory class to create {@link SearchDocumentResponse} instances.
*
* @author Sébastien Comeau
* @since 5.2
*/
class SearchDocumentResponseBuilderUnitTests {
private JacksonJsonpMapper jsonpMapper = new JacksonJsonpMapper();
@Test // #2681
void shouldGetPhraseSuggestion() throws JSONException {
// arrange
final var hitsMetadata = new HitsMetadata.Builder<EntityAsMap>()
.total(total -> total
.value(0)
.relation(TotalHitsRelation.Eq))
.hits(new ArrayList<>())
.build();
final var suggestionTest = new Suggestion.Builder<EntityAsMap>()
.phrase(phrase -> phrase
.text("National")
.offset(0)
.length(8)
.options(option -> option
.text("nations")
.highlighted("highlighted-nations")
.score(0.11480146)
.collateMatch(false))
.options(option -> option
.text("national")
.highlighted("highlighted-national")
.score(0.08063514)
.collateMatch(false)))
.build();
final var sortProperties = ImmutableMap.<String, List<Suggestion<EntityAsMap>>> builder()
.put("suggestionTest", ImmutableList.of(suggestionTest))
.build();
// act
final var actual = SearchDocumentResponseBuilder.from(hitsMetadata, null, null, null, sortProperties, null,
jsonpMapper);
// assert
SoftAssertions softly = new SoftAssertions();
softly.assertThat(actual).isNotNull();
softly.assertThat(actual.getSuggest()).isNotNull();
softly.assertThat(actual.getSuggest().getSuggestions()).isNotNull().hasSize(1);
final var actualSuggestion = actual.getSuggest().getSuggestions().get(0);
softly.assertThat(actualSuggestion.getName()).isEqualTo("suggestionTest");
softly.assertThat(actualSuggestion.getEntries()).isNotNull().hasSize(1);
final var actualEntry = actualSuggestion.getEntries().get(0);
softly.assertThat(actualEntry).isNotNull();
softly.assertThat(actualEntry.getText()).isEqualTo("National");
softly.assertThat(actualEntry.getOffset()).isEqualTo(0);
softly.assertThat(actualEntry.getLength()).isEqualTo(8);
softly.assertThat(actualEntry.getOptions()).isNotNull().hasSize(2);
final var actualOption1 = actualEntry.getOptions().get(0);
softly.assertThat(actualOption1.getText()).isEqualTo("nations");
softly.assertThat(actualOption1.getHighlighted()).isEqualTo("highlighted-nations");
softly.assertThat(actualOption1.getScore()).isEqualTo(0.11480146);
softly.assertThat(actualOption1.getCollateMatch()).isEqualTo(false);
final var actualOption2 = actualEntry.getOptions().get(1);
softly.assertThat(actualOption2.getText()).isEqualTo("national");
softly.assertThat(actualOption2.getHighlighted()).isEqualTo("highlighted-national");
softly.assertThat(actualOption2.getScore()).isEqualTo(0.08063514);
softly.assertThat(actualOption2.getCollateMatch()).isEqualTo(false);
softly.assertAll();
}
}

View File

@ -18,6 +18,7 @@ package org.springframework.data.elasticsearch.core;
import static org.assertj.core.api.Assertions.*;
import static org.springframework.data.elasticsearch.client.elc.Queries.*;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.aggregations.Aggregate;
import co.elastic.clients.elasticsearch._types.aggregations.Buckets;
import co.elastic.clients.elasticsearch._types.aggregations.StringTermsAggregate;
@ -27,9 +28,12 @@ import co.elastic.clients.elasticsearch.core.search.FieldCollapse;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.client.elc.Aggregation;
import org.springframework.data.elasticsearch.client.elc.ElasticsearchAggregation;
import org.springframework.data.elasticsearch.client.elc.NativeQuery;
@ -48,6 +52,51 @@ import org.springframework.test.context.ContextConfiguration;
@ContextConfiguration(classes = ReactiveElasticsearchELCIntegrationTests.Config.class)
public class ReactiveElasticsearchELCIntegrationTests extends ReactiveElasticsearchIntegrationTests {
@Test // #2745
@DisplayName("should use sort defined in native unbounded query")
void shouldUseSortDefinedInNativeUnboundedQuery() {
var entity1 = randomEntity(null);
entity1.setRate(7);
var entity2 = randomEntity(null);
entity2.setRate(5);
var entity3 = randomEntity(null);
entity3.setRate(11);
operations.saveAll(List.of(entity1, entity2, entity3), SampleEntity.class).blockLast();
var query = NativeQuery.builder()
.withQuery(qb -> qb
.matchAll(m -> m))
.withSort(sob -> sob
.field(f -> f
.field("rate")
.order(SortOrder.Asc)))
.withPageable(Pageable.unpaged())
.build();
var rates = operations.search(query, SampleEntity.class)
.map(SearchHit::getContent)
.map(SampleEntity::getRate)
.collectList().block();
assertThat(rates).containsExactly(5, 7, 11);
query = NativeQuery.builder()
.withQuery(qb -> qb
.matchAll(m -> m))
.withSort(sob -> sob
.field(f -> f
.field("rate")
.order(SortOrder.Desc)))
.withPageable(Pageable.unpaged())
.build();
rates = operations.search(query, SampleEntity.class)
.map(SearchHit::getContent)
.map(SampleEntity::getRate)
.collectList().block();
assertThat(rates).containsExactly(11, 7, 5);
}
@Configuration
@Import({ ReactiveElasticsearchTemplateConfiguration.class })
static class Config {

View File

@ -28,6 +28,7 @@ import java.lang.Boolean;
import java.lang.Integer;
import java.lang.Long;
import java.lang.Object;
import java.time.Duration;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
@ -98,7 +99,7 @@ import org.springframework.util.StringUtils;
@SpringIntegrationTest
public abstract class ReactiveElasticsearchIntegrationTests {
@Autowired private ReactiveElasticsearchOperations operations;
@Autowired protected ReactiveElasticsearchOperations operations;
@Autowired private IndexNameProvider indexNameProvider;
// region Setup
@ -1181,7 +1182,7 @@ public abstract class ReactiveElasticsearchIntegrationTests {
}).verifyComplete();
}
@Test // #2496
@Test // #2496, #2576
@DisplayName("should save data from Flux and return saved data in a flux")
void shouldSaveDataFromFluxAndReturnSavedDataInAFlux() {
@ -1190,9 +1191,11 @@ public abstract class ReactiveElasticsearchIntegrationTests {
.mapToObj(SampleEntity::of) //
.collect(Collectors.toList());
var entityFlux = Flux.fromIterable(entityList);
// we add a random delay to make suure the underlying implementation handles irregular incoming data
var entities = Flux.fromIterable(entityList).concatMap(
entity -> Mono.just(entity).delay(Duration.ofMillis((long) (Math.random() * 10))).thenReturn(entity));
operations.save(entityFlux, SampleEntity.class).collectList() //
operations.save(entities, SampleEntity.class).collectList() //
.as(StepVerifier::create) //
.consumeNextWith(savedEntities -> {
assertThat(savedEntities).isEqualTo(entityList);
@ -1202,7 +1205,7 @@ public abstract class ReactiveElasticsearchIntegrationTests {
// endregion
// region Helper functions
private SampleEntity randomEntity(String message) {
protected SampleEntity randomEntity(@Nullable String message) {
SampleEntity entity = new SampleEntity();
entity.setId(UUID.randomUUID().toString());

View File

@ -31,6 +31,7 @@ import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import org.springframework.data.elasticsearch.annotations.Mapping;
import org.springframework.data.elasticsearch.annotations.ScriptedField;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.Criteria;
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
@ -95,6 +96,88 @@ public abstract class RuntimeFieldsIntegrationTests {
assertThat(searchHits.getSearchHit(0).getId()).isEqualTo("1");
}
@Test // #2727
@DisplayName("should return runtime fields values")
void shouldReturnRuntimeFieldsValues() {
var entity = new SAREntity();
entity.setId("42");
entity.setValue(3);
operations.save(entity);
var runtimeField1 = getRuntimeField("scriptedValue1", 2);
var runtimeField2 = getRuntimeField("scriptedValue2", 3);
var query = CriteriaQuery.builder(Criteria.where("value").is(3)).build();
query.addRuntimeField(runtimeField1);
query.addRuntimeField(runtimeField2);
query.addSourceFilter(new FetchSourceFilterBuilder().withIncludes("*").build());
query.addFields("scriptedValue1", "scriptedValue2");
var searchHits = operations.search(query, SAREntity.class);
assertThat(searchHits.getTotalHits()).isEqualTo(1);
var foundEntity = searchHits.getSearchHit(0).getContent();
assertThat(foundEntity.value).isEqualTo(3);
assertThat(foundEntity.getScriptedValue1()).isEqualTo(6);
assertThat(foundEntity.getScriptedValue2()).isEqualTo(9);
}
@Document(indexName = "#{@indexNameProvider.indexName()}-sar")
public static class SAREntity {
@Nullable private String id;
@Field(type = FieldType.Integer)
@Nullable Integer value;
@ScriptedField
@Nullable Integer scriptedValue1;
@ScriptedField
@Nullable Integer scriptedValue2;
// getter and setter omitted
@Nullable
public String getId() {
return id;
}
public void setId(@Nullable String id) {
this.id = id;
}
@Nullable
public Integer getValue() {
return value;
}
public void setValue(@Nullable Integer value) {
this.value = value;
}
@Nullable
public Integer getScriptedValue1() {
return scriptedValue1;
}
public void setScriptedValue1(@Nullable Integer scriptedValue1) {
this.scriptedValue1 = scriptedValue1;
}
@Nullable
public Integer getScriptedValue2() {
return scriptedValue2;
}
public void setScriptedValue2(@Nullable Integer scriptedValue2) {
this.scriptedValue2 = scriptedValue2;
}
}
private static RuntimeField getRuntimeField(String fieldName, int factor) {
return new RuntimeField(
fieldName,
"long",
String.format("emit(doc['value'].size() > 0 ? doc['value'].value * %d : 0)", factor));
}
@Test // #2431
@DisplayName("should return value from runtime field defined in mapping")
void shouldReturnValueFromRuntimeFieldDefinedInMapping() {

View File

@ -909,22 +909,109 @@ public class MappingElasticsearchConverterUnitTests {
assertEquals(expected, document.toJson(), false);
}
@Test // #2627
@DisplayName("should write Map containing collection containing map")
void shouldWriteMapContainingCollectionContainingMap() throws JSONException {
class EntityWithMapCollectionMap {
Map<String, Object> map;
}
class InnerEntity {
String prop1;
String prop2;
public InnerEntity() {}
public InnerEntity(String prop1, String prop2) {
this.prop1 = prop1;
this.prop2 = prop2;
}
}
var entity = new EntityWithMapCollectionMap();
entity.map = Collections.singletonMap("collection",
Collections.singletonList(Collections.singletonMap("destination", new InnerEntity("prop1", "prop2"))));
var expected = """
{
"_class": "org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverterUnitTests$1EntityWithMapCollectionMap",
"map": {
"collection": [
{
"destination": {
"_class": "org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverterUnitTests$1InnerEntity",
"prop1": "prop1",
"prop2": "prop2"
}
}
]
}
}
""";
Document document = Document.create();
mappingElasticsearchConverter.write(entity, document);
assertEquals(expected, document.toJson(), false);
}
@Nested
class RangeTests {
static final String JSON = "{"
+ "\"_class\":\"org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverterUnitTests$RangeTests$RangeEntity\","
+ "\"integerRange\":{\"gt\":\"1\",\"lt\":\"10\"}," //
+ "\"floatRange\":{\"gte\":\"1.2\",\"lte\":\"2.5\"}," //
+ "\"longRange\":{\"gt\":\"2\",\"lte\":\"5\"}," //
+ "\"doubleRange\":{\"gte\":\"3.2\",\"lt\":\"7.4\"}," //
+ "\"dateRange\":{\"gte\":\"1970-01-01T00:00:00.000Z\",\"lte\":\"1970-01-01T01:00:00.000Z\"}," //
+ "\"localDateRange\":{\"gte\":\"2021-07-06\"}," //
+ "\"localTimeRange\":{\"gte\":\"00:30:00.000\",\"lt\":\"02:30:00.000\"}," //
+ "\"localDateTimeRange\":{\"gt\":\"2021-01-01T00:30:00.000\",\"lt\":\"2021-01-01T02:30:00.000\"}," //
+ "\"offsetTimeRange\":{\"gte\":\"00:30:00.000+02:00\",\"lt\":\"02:30:00.000+02:00\"}," //
+ "\"zonedDateTimeRange\":{\"gte\":\"2021-01-01T00:30:00.000+02:00\",\"lte\":\"2021-01-01T00:30:00.000+02:00\"}," //
+ "\"nullRange\":null}";
static final String JSON = """
{
"_class": "org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverterUnitTests$RangeTests$RangeEntity",
"integerRange": {
"gt": "1",
"lt": "10"
},
"floatRange": {
"gte": "1.2",
"lte": "2.5"
},
"longRange": {
"gt": "2",
"lte": "5"
},
"doubleRange": {
"gte": "3.2",
"lt": "7.4"
},
"dateRange": {
"gte": "1970-01-01T00:00:00.000Z",
"lte": "1970-01-01T01:00:00.000Z"
},
"localDateRange": {
"gte": "2021-07-06"
},
"localTimeRange": {
"gte": "00:30:00.000",
"lt": "02:30:00.000"
},
"localDateTimeRange": {
"gt": "2021-01-01T00:30:00.000",
"lt": "2021-01-01T02:30:00.000"
},
"offsetTimeRange": {
"gte": "00:30:00.000+02:00",
"lt": "02:30:00.000+02:00"
},
"zonedDateTimeRange": {
"gte": "2021-01-01T00:30:00.000+02:00",
"lte": "2021-01-01T00:30:00.000+02:00"
},
"nullRange": null,
"integerRangeList": [
{
"gte": "2",
"lte": "5"
}
]
}
""";
@Test
public void shouldReadRanges() throws JSONException {
@ -955,6 +1042,7 @@ public class MappingElasticsearchConverterUnitTests {
assertThat(e.getZonedDateTimeRange()).isEqualTo(
Range.just(ZonedDateTime.of(LocalDate.of(2021, 1, 1), LocalTime.of(0, 30), ZoneOffset.ofHours(2))));
assertThat(e.getNullRange()).isNull();
assertThat(e.getIntegerRangeList()).containsExactly(Range.closed(2, 5));
});
}
@ -978,8 +1066,7 @@ public class MappingElasticsearchConverterUnitTests {
entity.setZonedDateTimeRange(
Range.just(ZonedDateTime.of(LocalDate.of(2021, 1, 1), LocalTime.of(0, 30), ZoneOffset.ofHours(2))));
entity.setNullRange(null);
// when
entity.setIntegerRangeList(List.of(Range.closed(2, 5)));
Document document = mappingElasticsearchConverter.mapObject(entity);
// then
@ -1004,6 +1091,8 @@ public class MappingElasticsearchConverterUnitTests {
@Field(type = FieldType.Date_Range) private Range<ZonedDateTime> zonedDateTimeRange;
@Field(type = FieldType.Date_Range, storeNullValue = true) private Range<ZonedDateTime> nullRange;
@Field(type = FieldType.Integer_Range) private List<Range<Integer>> integerRangeList;
public String getId() {
return id;
}
@ -1100,6 +1189,13 @@ public class MappingElasticsearchConverterUnitTests {
this.nullRange = nullRange;
}
public List<Range<Integer>> getIntegerRangeList() {
return integerRangeList;
}
public void setIntegerRangeList(List<Range<Integer>> integerRangeList) {
this.integerRangeList = integerRangeList;
}
}
}
@ -1953,12 +2049,12 @@ public class MappingElasticsearchConverterUnitTests {
@Language("JSON")
var expected = """
{
"_class": "org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverterUnitTests$FieldNameDotsEntity",
"id": "42",
"dotted.field": "dotted field"
}
""";
{
"_class": "org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverterUnitTests$FieldNameDotsEntity",
"id": "42",
"dotted.field": "dotted field"
}
""";
var entity = new FieldNameDotsEntity();
entity.setId("42");
entity.setDottedField("dotted field");
@ -3192,6 +3288,7 @@ public class MappingElasticsearchConverterUnitTests {
this.mapToNotWriteWhenEmpty = mapToNotWriteWhenEmpty;
}
}
static class FieldNameDotsEntity {
@Id
@Nullable private String id;

View File

@ -63,13 +63,14 @@ public class PropertyValueConvertersUnitTests {
converters.add(new DatePropertyValueConverter(persistentProperty,
Collections.singletonList(ElasticsearchDateConverter.of(DateFormat.basic_date))));
Class<?> genericType = Object.class;
converters.add(new DateRangePropertyValueConverter(persistentProperty,
Collections.singletonList(ElasticsearchDateConverter.of(DateFormat.basic_date))));
converters.add(new NumberRangePropertyValueConverter(persistentProperty));
genericType, Collections.singletonList(ElasticsearchDateConverter.of(DateFormat.basic_date))));
converters.add(new NumberRangePropertyValueConverter(persistentProperty, genericType));
converters.add(new TemporalPropertyValueConverter(persistentProperty,
Collections.singletonList(ElasticsearchDateConverter.of(DateFormat.basic_date))));
converters.add(new TemporalRangePropertyValueConverter(persistentProperty,
Collections.singletonList(ElasticsearchDateConverter.of(DateFormat.basic_date))));
genericType, Collections.singletonList(ElasticsearchDateConverter.of(DateFormat.basic_date))));
return converters.stream().map(propertyValueConverter -> arguments(
Named.of(propertyValueConverter.getClass().getSimpleName(), propertyValueConverter)));

View File

@ -287,6 +287,12 @@ public abstract class MappingBuilderIntegrationTests extends MappingContextBaseT
indexOps.createWithMapping();
}
@Test // #2659
@DisplayName("should write correct mapping for dense vector property")
void shouldWriteCorrectMappingForDenseVectorProperty() {
operations.indexOps(SimilarityEntity.class).createWithMapping();
}
// region Entities
@Document(indexName = "#{@indexNameProvider.indexName()}")
static class Book {
@ -916,5 +922,14 @@ public abstract class MappingBuilderIntegrationTests extends MappingContextBaseT
@Nullable
@Field(name = "dotted.field", type = Text) private String dottedField;
}
@Document(indexName = "#{@indexNameProvider.indexName()}")
static class SimilarityEntity {
@Nullable
@Id private String id;
@Field(type = FieldType.Dense_Vector, dims = 42, similarity = "cosine") private double[] denseVector;
}
// endregion
}

View File

@ -62,7 +62,7 @@ public abstract class SearchAfterIntegrationTests {
@Test
@Order(java.lang.Integer.MAX_VALUE)
void cleanup() {
operations.indexOps(IndexCoordinates.of(indexNameProvider.getPrefix() + "*")).delete();
operations.indexOps(IndexCoordinates.of(indexNameProvider.getPrefix() + '*')).delete();
}
@Test // #1143
@ -85,11 +85,11 @@ public abstract class SearchAfterIntegrationTests {
query.setSearchAfter(searchAfter);
SearchHits<Entity> searchHits = operations.search(query, Entity.class);
if (searchHits.getSearchHits().size() == 0) {
if (searchHits.getSearchHits().isEmpty()) {
break;
}
foundEntities.addAll(searchHits.stream().map(SearchHit::getContent).collect(Collectors.toList()));
searchAfter = searchHits.getSearchHit((int) (searchHits.getSearchHits().size() - 1)).getSortValues();
foundEntities.addAll(searchHits.stream().map(SearchHit::getContent).toList());
searchAfter = searchHits.getSearchHit(searchHits.getSearchHits().size() - 1).getSortValues();
if (++loop > 10) {
fail("loop not terminating");
@ -99,16 +99,69 @@ public abstract class SearchAfterIntegrationTests {
assertThat(foundEntities).containsExactlyElementsOf(entities);
}
@Test // #2678
@DisplayName("should be able to handle different search after type values including null")
void shouldBeAbleToHandleDifferentSearchAfterTypeValuesIncludingNull() {
List<Entity> entities = IntStream.rangeClosed(1, 10)
.mapToObj(i -> {
var message = (i % 2 == 0) ? null : "message " + i;
var value = (i % 3 == 0) ? null : (long) i;
return new Entity((long) i, message, value);
})
.collect(Collectors.toList());
operations.save(entities);
Query query = Query.findAll();
query.setPageable(PageRequest.of(0, 3));
query.addSort(Sort.by(Sort.Direction.ASC, "id"));
query.addSort(Sort.by(Sort.Direction.ASC, "keyword"));
query.addSort(Sort.by(Sort.Direction.ASC, "value"));
List<Object> searchAfter = null;
List<Entity> foundEntities = new ArrayList<>();
int loop = 0;
do {
query.setSearchAfter(searchAfter);
SearchHits<Entity> searchHits = operations.search(query, Entity.class);
if (searchHits.getSearchHits().isEmpty()) {
break;
}
foundEntities.addAll(searchHits.stream().map(SearchHit::getContent).toList());
searchAfter = searchHits.getSearchHit(searchHits.getSearchHits().size() - 1).getSortValues();
if (++loop > 10) {
fail("loop not terminating");
}
} while (true);
assertThat(foundEntities).containsExactlyElementsOf(entities);
}
@SuppressWarnings("unused")
@Document(indexName = "#{@indexNameProvider.indexName()}")
private static class Entity {
@Nullable
@Id private Long id;
@Nullable
@Field(type = FieldType.Text) private String message;
@Field(type = FieldType.Keyword) private String keyword;
public Entity(@Nullable Long id, @Nullable String message) {
@Nullable
@Field(type = FieldType.Long) private Long value;
public Entity() {}
public Entity(@Nullable Long id, @Nullable String keyword) {
this.id = id;
this.message = message;
this.keyword = keyword;
}
public Entity(@Nullable Long id, @Nullable String keyword, @Nullable Long value) {
this.id = id;
this.keyword = keyword;
this.value = value;
}
@Nullable
@ -121,30 +174,44 @@ public abstract class SearchAfterIntegrationTests {
}
@Nullable
public String getMessage() {
return message;
public String getKeyword() {
return keyword;
}
public void setMessage(@Nullable String message) {
this.message = message;
public void setKeyword(@Nullable String keyword) {
this.keyword = keyword;
}
@Nullable
public Long getValue() {
return value;
}
public void setValue(@Nullable Long value) {
this.value = value;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof Entity entity))
if (o == null || getClass() != o.getClass())
return false;
Entity entity = (Entity) o;
if (!Objects.equals(id, entity.id))
return false;
return Objects.equals(message, entity.message);
if (!Objects.equals(keyword, entity.keyword))
return false;
return Objects.equals(value, entity.value);
}
@Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + (message != null ? message.hashCode() : 0);
result = 31 * result + (keyword != null ? keyword.hashCode() : 0);
result = 31 * result + (value != null ? value.hashCode() : 0);
return result;
}
}

View File

@ -1590,6 +1590,41 @@ public abstract class CustomMethodRepositoryIntegrationTests implements NewElast
assertThat(searchHits.getSearchHit(2).getId()).isEqualTo("oslo");
}
@Test // #2601
void shouldUseGeoSortReverseParameter() {
GeoPoint munich = new GeoPoint(48.137154, 11.5761247);
GeoPoint berlin = new GeoPoint(52.520008, 13.404954);
GeoPoint vienna = new GeoPoint(48.20849, 16.37208);
GeoPoint oslo = new GeoPoint(59.9127, 10.7461);
List<SampleEntity> entities = new ArrayList<>();
SampleEntity entity1 = new SampleEntity();
entity1.setId("berlin");
entity1.setLocation(berlin);
entities.add(entity1);
SampleEntity entity2 = new SampleEntity();
entity2.setId("vienna");
entity2.setLocation(vienna);
entities.add(entity2);
SampleEntity entity3 = new SampleEntity();
entity3.setId("oslo");
entity3.setLocation(oslo);
entities.add(entity3);
repository.saveAll(entities);
SearchHits<SampleEntity> searchHits = repository
.searchBy(Sort.by(new GeoDistanceOrder("location", munich).with(Sort.Direction.DESC)));
assertThat(searchHits.getTotalHits()).isEqualTo(3);
assertThat(searchHits.getSearchHit(0).getId()).isEqualTo("oslo");
assertThat(searchHits.getSearchHit(1).getId()).isEqualTo("berlin");
assertThat(searchHits.getSearchHit(2).getId()).isEqualTo("vienna");
}
@Test // DATAES-749
void shouldReturnSearchPage() {
List<SampleEntity> entities = createSampleEntities("abc", 20);

View File

@ -15,7 +15,7 @@
#
#
sde.testcontainers.image-name=docker.elastic.co/elasticsearch/elasticsearch
sde.testcontainers.image-version=8.7.0
sde.testcontainers.image-version=8.7.1
#
#
# needed as we do a DELETE /* at the end of the tests, will be required from 8.0 on, produces a warning since 7.13