mirror of
https://github.com/spring-projects/spring-data-elasticsearch.git
synced 2025-08-15 22:13:27 +00:00
Compare commits
51 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
d2960d764f | ||
|
8bb0a60450 | ||
|
e33fe4d9fd | ||
|
0fd1b96ef3 | ||
|
30bc91c753 | ||
|
92806d2e11 | ||
|
2dd0a6771f | ||
|
79e0260f48 | ||
|
8d79a3efcf | ||
|
d785c6c33c | ||
|
c89368ce42 | ||
|
c0781efbaa | ||
|
d371404f90 | ||
|
cc5b4fa635 | ||
|
deae205fd4 | ||
|
796a5ebe34 | ||
|
2c63ba4097 | ||
|
fe255c1bdc | ||
|
6f89e17451 | ||
|
0ad4fcb2eb | ||
|
4c3281f1eb | ||
|
303438ae63 | ||
|
254948d1c9 | ||
|
0bb239a674 | ||
|
3336ceade8 | ||
|
e7398df948 | ||
|
a7ed13db83 | ||
|
7db3dc1a37 | ||
|
0cabc3372e | ||
|
ab2fba6581 | ||
|
45a0e2213f | ||
|
8c8c0eba4f | ||
|
90b366cf5f | ||
|
c5d93c5cd2 | ||
|
2ac1085d03 | ||
|
e0760e8567 | ||
|
f8860c890a | ||
|
3a00ef4375 | ||
|
ad6022f64c | ||
|
da384e5eda | ||
|
8ab1a4f098 | ||
|
40972b21e0 | ||
|
85af54635d | ||
|
105607f6d6 | ||
|
d0ee4efd87 | ||
|
9c900eca21 | ||
|
8cfe165754 | ||
|
30bfee24f0 | ||
|
f339fda512 | ||
|
b2a480df83 | ||
|
f765ecac69 |
117
.mvn/wrapper/MavenWrapperDownloader.java
vendored
Normal file
117
.mvn/wrapper/MavenWrapperDownloader.java
vendored
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2007-present 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.
|
||||||
|
*/
|
||||||
|
import java.net.*;
|
||||||
|
import java.io.*;
|
||||||
|
import java.nio.channels.*;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
public class MavenWrapperDownloader {
|
||||||
|
|
||||||
|
private static final String WRAPPER_VERSION = "0.5.6";
|
||||||
|
/**
|
||||||
|
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
|
||||||
|
*/
|
||||||
|
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
|
||||||
|
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
|
||||||
|
* use instead of the default one.
|
||||||
|
*/
|
||||||
|
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
|
||||||
|
".mvn/wrapper/maven-wrapper.properties";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Path where the maven-wrapper.jar will be saved to.
|
||||||
|
*/
|
||||||
|
private static final String MAVEN_WRAPPER_JAR_PATH =
|
||||||
|
".mvn/wrapper/maven-wrapper.jar";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the property which should be used to override the default download url for the wrapper.
|
||||||
|
*/
|
||||||
|
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
|
||||||
|
|
||||||
|
public static void main(String args[]) {
|
||||||
|
System.out.println("- Downloader started");
|
||||||
|
File baseDirectory = new File(args[0]);
|
||||||
|
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
|
||||||
|
|
||||||
|
// If the maven-wrapper.properties exists, read it and check if it contains a custom
|
||||||
|
// wrapperUrl parameter.
|
||||||
|
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
|
||||||
|
String url = DEFAULT_DOWNLOAD_URL;
|
||||||
|
if(mavenWrapperPropertyFile.exists()) {
|
||||||
|
FileInputStream mavenWrapperPropertyFileInputStream = null;
|
||||||
|
try {
|
||||||
|
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
|
||||||
|
Properties mavenWrapperProperties = new Properties();
|
||||||
|
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
|
||||||
|
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if(mavenWrapperPropertyFileInputStream != null) {
|
||||||
|
mavenWrapperPropertyFileInputStream.close();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
// Ignore ...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.println("- Downloading from: " + url);
|
||||||
|
|
||||||
|
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
|
||||||
|
if(!outputFile.getParentFile().exists()) {
|
||||||
|
if(!outputFile.getParentFile().mkdirs()) {
|
||||||
|
System.out.println(
|
||||||
|
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
|
||||||
|
try {
|
||||||
|
downloadFileFromURL(url, outputFile);
|
||||||
|
System.out.println("Done");
|
||||||
|
System.exit(0);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
System.out.println("- Error downloading");
|
||||||
|
e.printStackTrace();
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
|
||||||
|
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
|
||||||
|
String username = System.getenv("MVNW_USERNAME");
|
||||||
|
char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
|
||||||
|
Authenticator.setDefault(new Authenticator() {
|
||||||
|
@Override
|
||||||
|
protected PasswordAuthentication getPasswordAuthentication() {
|
||||||
|
return new PasswordAuthentication(username, password);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
URL website = new URL(urlString);
|
||||||
|
ReadableByteChannel rbc;
|
||||||
|
rbc = Channels.newChannel(website.openStream());
|
||||||
|
FileOutputStream fos = new FileOutputStream(destination);
|
||||||
|
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
|
||||||
|
fos.close();
|
||||||
|
rbc.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
BIN
.mvn/wrapper/maven-wrapper.jar
vendored
Executable file → Normal file
BIN
.mvn/wrapper/maven-wrapper.jar
vendored
Executable file → Normal file
Binary file not shown.
4
.mvn/wrapper/maven-wrapper.properties
vendored
Executable file → Normal file
4
.mvn/wrapper/maven-wrapper.properties
vendored
Executable file → Normal file
@ -1 +1,3 @@
|
|||||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip
|
#Fri Sep 10 15:39:43 CEST 2021
|
||||||
|
wrapperUrl=https\://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
|
||||||
|
distributionUrl=https\://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.2/apache-maven-3.8.2-bin.zip
|
||||||
|
17
Jenkinsfile
vendored
17
Jenkinsfile
vendored
@ -3,7 +3,7 @@ pipeline {
|
|||||||
|
|
||||||
triggers {
|
triggers {
|
||||||
pollSCM 'H/10 * * * *'
|
pollSCM 'H/10 * * * *'
|
||||||
upstream(upstreamProjects: "spring-data-commons/master", threshold: hudson.model.Result.SUCCESS)
|
upstream(upstreamProjects: "spring-data-commons/2.5.x", threshold: hudson.model.Result.SUCCESS)
|
||||||
}
|
}
|
||||||
|
|
||||||
options {
|
options {
|
||||||
@ -15,7 +15,7 @@ pipeline {
|
|||||||
stage("test: baseline (jdk8)") {
|
stage("test: baseline (jdk8)") {
|
||||||
when {
|
when {
|
||||||
anyOf {
|
anyOf {
|
||||||
branch 'master'
|
branch '4.2.x'
|
||||||
not { triggeredBy 'UpstreamCause' }
|
not { triggeredBy 'UpstreamCause' }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -26,6 +26,7 @@ pipeline {
|
|||||||
|
|
||||||
environment {
|
environment {
|
||||||
DOCKER_HUB = credentials('hub.docker.com-springbuildmaster')
|
DOCKER_HUB = credentials('hub.docker.com-springbuildmaster')
|
||||||
|
ARTIFACTORY = credentials('02bd1690-b54f-4c9f-819d-a77cb7a9822c')
|
||||||
}
|
}
|
||||||
|
|
||||||
steps {
|
steps {
|
||||||
@ -44,7 +45,7 @@ pipeline {
|
|||||||
stage("Test other configurations") {
|
stage("Test other configurations") {
|
||||||
when {
|
when {
|
||||||
allOf {
|
allOf {
|
||||||
branch 'master'
|
branch '4.2.x'
|
||||||
not { triggeredBy 'UpstreamCause' }
|
not { triggeredBy 'UpstreamCause' }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -57,6 +58,7 @@ pipeline {
|
|||||||
|
|
||||||
environment {
|
environment {
|
||||||
DOCKER_HUB = credentials('hub.docker.com-springbuildmaster')
|
DOCKER_HUB = credentials('hub.docker.com-springbuildmaster')
|
||||||
|
ARTIFACTORY = credentials('02bd1690-b54f-4c9f-819d-a77cb7a9822c')
|
||||||
}
|
}
|
||||||
|
|
||||||
steps {
|
steps {
|
||||||
@ -80,6 +82,7 @@ pipeline {
|
|||||||
|
|
||||||
environment {
|
environment {
|
||||||
DOCKER_HUB = credentials('hub.docker.com-springbuildmaster')
|
DOCKER_HUB = credentials('hub.docker.com-springbuildmaster')
|
||||||
|
ARTIFACTORY = credentials('02bd1690-b54f-4c9f-819d-a77cb7a9822c')
|
||||||
}
|
}
|
||||||
|
|
||||||
steps {
|
steps {
|
||||||
@ -100,7 +103,7 @@ pipeline {
|
|||||||
stage('Release to artifactory') {
|
stage('Release to artifactory') {
|
||||||
when {
|
when {
|
||||||
anyOf {
|
anyOf {
|
||||||
branch 'master'
|
branch '4.2.x'
|
||||||
not { triggeredBy 'UpstreamCause' }
|
not { triggeredBy 'UpstreamCause' }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -117,7 +120,7 @@ pipeline {
|
|||||||
script {
|
script {
|
||||||
docker.withRegistry('', 'hub.docker.com-springbuildmaster') {
|
docker.withRegistry('', 'hub.docker.com-springbuildmaster') {
|
||||||
docker.image('adoptopenjdk/openjdk8:latest').inside('-v $HOME:/tmp/jenkins-home') {
|
docker.image('adoptopenjdk/openjdk8:latest').inside('-v $HOME:/tmp/jenkins-home') {
|
||||||
sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -Pci,artifactory -Dmaven.repo.local=/tmp/jenkins-home/.m2/spring-data-elasticsearch-non-root ' +
|
sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -s settings.xml -Pci,artifactory -Dmaven.repo.local=/tmp/jenkins-home/.m2/spring-data-elasticsearch-non-root ' +
|
||||||
'-Dartifactory.server=https://repo.spring.io ' +
|
'-Dartifactory.server=https://repo.spring.io ' +
|
||||||
"-Dartifactory.username=${ARTIFACTORY_USR} " +
|
"-Dartifactory.username=${ARTIFACTORY_USR} " +
|
||||||
"-Dartifactory.password=${ARTIFACTORY_PSW} " +
|
"-Dartifactory.password=${ARTIFACTORY_PSW} " +
|
||||||
@ -132,7 +135,7 @@ pipeline {
|
|||||||
}
|
}
|
||||||
stage('Publish documentation') {
|
stage('Publish documentation') {
|
||||||
when {
|
when {
|
||||||
branch 'master'
|
branch '4.2.x'
|
||||||
}
|
}
|
||||||
agent {
|
agent {
|
||||||
label 'data'
|
label 'data'
|
||||||
@ -147,7 +150,7 @@ pipeline {
|
|||||||
script {
|
script {
|
||||||
docker.withRegistry('', 'hub.docker.com-springbuildmaster') {
|
docker.withRegistry('', 'hub.docker.com-springbuildmaster') {
|
||||||
docker.image('adoptopenjdk/openjdk8:latest').inside('-v $HOME:/tmp/jenkins-home') {
|
docker.image('adoptopenjdk/openjdk8:latest').inside('-v $HOME:/tmp/jenkins-home') {
|
||||||
sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -Pci,distribute -Dmaven.repo.local=/tmp/jenkins-home/.m2/spring-data-elasticsearch-non-root ' +
|
sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -s settings.xml -Pci,distribute -Dmaven.repo.local=/tmp/jenkins-home/.m2/spring-data-elasticsearch-non-root ' +
|
||||||
'-Dartifactory.server=https://repo.spring.io ' +
|
'-Dartifactory.server=https://repo.spring.io ' +
|
||||||
"-Dartifactory.username=${ARTIFACTORY_USR} " +
|
"-Dartifactory.username=${ARTIFACTORY_USR} " +
|
||||||
"-Dartifactory.password=${ARTIFACTORY_PSW} " +
|
"-Dartifactory.password=${ARTIFACTORY_PSW} " +
|
||||||
|
202
LICENSE.txt
Normal file
202
LICENSE.txt
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
https://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright {yyyy} {name of copyright owner}
|
||||||
|
|
||||||
|
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.
|
@ -3,4 +3,4 @@
|
|||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" \
|
MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" \
|
||||||
./mvnw clean -Dmaven.repo.local=/tmp/jenkins-home/.m2/spring-data-elasticsearch
|
./mvnw -s settings.xml clean -Dmaven.repo.local=/tmp/jenkins-home/.m2/spring-data-elasticsearch
|
||||||
|
@ -6,5 +6,5 @@ mkdir -p /tmp/jenkins-home/.m2/spring-data-elasticsearch
|
|||||||
chown -R 1001:1001 .
|
chown -R 1001:1001 .
|
||||||
|
|
||||||
MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" \
|
MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" \
|
||||||
./mvnw \
|
./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
|
34
mvnw
vendored
34
mvnw
vendored
@ -8,7 +8,7 @@
|
|||||||
# "License"); you may not use this file except in compliance
|
# "License"); you may not use this file except in compliance
|
||||||
# with the License. You may obtain a copy of the License at
|
# with the License. You may obtain a copy of the License at
|
||||||
#
|
#
|
||||||
# https://www.apache.org/licenses/LICENSE-2.0
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing,
|
# Unless required by applicable law or agreed to in writing,
|
||||||
# software distributed under the License is distributed on an
|
# software distributed under the License is distributed on an
|
||||||
@ -19,7 +19,7 @@
|
|||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
# Maven2 Start Up Batch script
|
# Maven Start Up Batch script
|
||||||
#
|
#
|
||||||
# Required ENV vars:
|
# Required ENV vars:
|
||||||
# ------------------
|
# ------------------
|
||||||
@ -114,7 +114,6 @@ if $mingw ; then
|
|||||||
M2_HOME="`(cd "$M2_HOME"; pwd)`"
|
M2_HOME="`(cd "$M2_HOME"; pwd)`"
|
||||||
[ -n "$JAVA_HOME" ] &&
|
[ -n "$JAVA_HOME" ] &&
|
||||||
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
|
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
|
||||||
# TODO classpath?
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$JAVA_HOME" ]; then
|
if [ -z "$JAVA_HOME" ]; then
|
||||||
@ -212,7 +211,11 @@ else
|
|||||||
if [ "$MVNW_VERBOSE" = true ]; then
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
|
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
|
||||||
fi
|
fi
|
||||||
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
|
if [ -n "$MVNW_REPOURL" ]; then
|
||||||
|
jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
|
||||||
|
else
|
||||||
|
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
|
||||||
|
fi
|
||||||
while IFS="=" read key value; do
|
while IFS="=" read key value; do
|
||||||
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
|
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
|
||||||
esac
|
esac
|
||||||
@ -221,22 +224,38 @@ else
|
|||||||
echo "Downloading from: $jarUrl"
|
echo "Downloading from: $jarUrl"
|
||||||
fi
|
fi
|
||||||
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
|
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
|
||||||
|
if $cygwin; then
|
||||||
|
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
|
||||||
|
fi
|
||||||
|
|
||||||
if command -v wget > /dev/null; then
|
if command -v wget > /dev/null; then
|
||||||
if [ "$MVNW_VERBOSE" = true ]; then
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
echo "Found wget ... using wget"
|
echo "Found wget ... using wget"
|
||||||
fi
|
fi
|
||||||
|
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||||
wget "$jarUrl" -O "$wrapperJarPath"
|
wget "$jarUrl" -O "$wrapperJarPath"
|
||||||
|
else
|
||||||
|
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
|
||||||
|
fi
|
||||||
elif command -v curl > /dev/null; then
|
elif command -v curl > /dev/null; then
|
||||||
if [ "$MVNW_VERBOSE" = true ]; then
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
echo "Found curl ... using curl"
|
echo "Found curl ... using curl"
|
||||||
fi
|
fi
|
||||||
curl -o "$wrapperJarPath" "$jarUrl"
|
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||||
|
curl -o "$wrapperJarPath" "$jarUrl" -f
|
||||||
|
else
|
||||||
|
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
|
||||||
|
fi
|
||||||
|
|
||||||
else
|
else
|
||||||
if [ "$MVNW_VERBOSE" = true ]; then
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
echo "Falling back to using Java to download"
|
echo "Falling back to using Java to download"
|
||||||
fi
|
fi
|
||||||
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
|
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
|
||||||
|
# For Cygwin, switch paths to Windows format before running javac
|
||||||
|
if $cygwin; then
|
||||||
|
javaClass=`cygpath --path --windows "$javaClass"`
|
||||||
|
fi
|
||||||
if [ -e "$javaClass" ]; then
|
if [ -e "$javaClass" ]; then
|
||||||
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
|
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
|
||||||
if [ "$MVNW_VERBOSE" = true ]; then
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
@ -277,6 +296,11 @@ if $cygwin; then
|
|||||||
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
|
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Provide a "standardized" way to retrieve the CLI args that will
|
||||||
|
# work with both Windows and non-Windows executions.
|
||||||
|
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
|
||||||
|
export MAVEN_CMD_LINE_ARGS
|
||||||
|
|
||||||
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||||
|
|
||||||
exec "$JAVACMD" \
|
exec "$JAVACMD" \
|
||||||
|
33
mvnw.cmd
vendored
Executable file → Normal file
33
mvnw.cmd
vendored
Executable file → Normal file
@ -7,7 +7,7 @@
|
|||||||
@REM "License"); you may not use this file except in compliance
|
@REM "License"); you may not use this file except in compliance
|
||||||
@REM with the License. You may obtain a copy of the License at
|
@REM with the License. You may obtain a copy of the License at
|
||||||
@REM
|
@REM
|
||||||
@REM https://www.apache.org/licenses/LICENSE-2.0
|
@REM http://www.apache.org/licenses/LICENSE-2.0
|
||||||
@REM
|
@REM
|
||||||
@REM Unless required by applicable law or agreed to in writing,
|
@REM Unless required by applicable law or agreed to in writing,
|
||||||
@REM software distributed under the License is distributed on an
|
@REM software distributed under the License is distributed on an
|
||||||
@ -18,7 +18,7 @@
|
|||||||
@REM ----------------------------------------------------------------------------
|
@REM ----------------------------------------------------------------------------
|
||||||
|
|
||||||
@REM ----------------------------------------------------------------------------
|
@REM ----------------------------------------------------------------------------
|
||||||
@REM Maven2 Start Up Batch script
|
@REM Maven Start Up Batch script
|
||||||
@REM
|
@REM
|
||||||
@REM Required ENV vars:
|
@REM Required ENV vars:
|
||||||
@REM JAVA_HOME - location of a JDK home dir
|
@REM JAVA_HOME - location of a JDK home dir
|
||||||
@ -37,7 +37,7 @@
|
|||||||
@echo off
|
@echo off
|
||||||
@REM set title of command window
|
@REM set title of command window
|
||||||
title %0
|
title %0
|
||||||
@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
|
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
|
||||||
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
||||||
|
|
||||||
@REM set %HOME% to equivalent of $HOME
|
@REM set %HOME% to equivalent of $HOME
|
||||||
@ -120,23 +120,44 @@ SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
|
|||||||
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
|
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
|
||||||
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||||
|
|
||||||
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
|
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
|
||||||
FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO (
|
|
||||||
|
FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
|
||||||
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
|
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
|
||||||
)
|
)
|
||||||
|
|
||||||
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||||
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
|
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||||
if exist %WRAPPER_JAR% (
|
if exist %WRAPPER_JAR% (
|
||||||
|
if "%MVNW_VERBOSE%" == "true" (
|
||||||
echo Found %WRAPPER_JAR%
|
echo Found %WRAPPER_JAR%
|
||||||
|
)
|
||||||
) else (
|
) else (
|
||||||
|
if not "%MVNW_REPOURL%" == "" (
|
||||||
|
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
|
||||||
|
)
|
||||||
|
if "%MVNW_VERBOSE%" == "true" (
|
||||||
echo Couldn't find %WRAPPER_JAR%, downloading it ...
|
echo Couldn't find %WRAPPER_JAR%, downloading it ...
|
||||||
echo Downloading from: %DOWNLOAD_URL%
|
echo Downloading from: %DOWNLOAD_URL%
|
||||||
powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"
|
)
|
||||||
|
|
||||||
|
powershell -Command "&{"^
|
||||||
|
"$webclient = new-object System.Net.WebClient;"^
|
||||||
|
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
|
||||||
|
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
|
||||||
|
"}"^
|
||||||
|
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
|
||||||
|
"}"
|
||||||
|
if "%MVNW_VERBOSE%" == "true" (
|
||||||
echo Finished downloading %WRAPPER_JAR%
|
echo Finished downloading %WRAPPER_JAR%
|
||||||
)
|
)
|
||||||
|
)
|
||||||
@REM End of extension
|
@REM End of extension
|
||||||
|
|
||||||
|
@REM Provide a "standardized" way to retrieve the CLI args that will
|
||||||
|
@REM work with both Windows and non-Windows executions.
|
||||||
|
set MAVEN_CMD_LINE_ARGS=%*
|
||||||
|
|
||||||
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
|
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
|
||||||
if ERRORLEVEL 1 goto error
|
if ERRORLEVEL 1 goto error
|
||||||
goto end
|
goto end
|
||||||
|
14
pom.xml
14
pom.xml
@ -5,12 +5,12 @@
|
|||||||
|
|
||||||
<groupId>org.springframework.data</groupId>
|
<groupId>org.springframework.data</groupId>
|
||||||
<artifactId>spring-data-elasticsearch</artifactId>
|
<artifactId>spring-data-elasticsearch</artifactId>
|
||||||
<version>4.2.0</version>
|
<version>4.2.5</version>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.data.build</groupId>
|
<groupId>org.springframework.data.build</groupId>
|
||||||
<artifactId>spring-data-parent</artifactId>
|
<artifactId>spring-data-parent</artifactId>
|
||||||
<version>2.5.0</version>
|
<version>2.5.5</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<name>Spring Data Elasticsearch</name>
|
<name>Spring Data Elasticsearch</name>
|
||||||
@ -19,10 +19,10 @@
|
|||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<commonslang>2.6</commonslang>
|
<commonslang>2.6</commonslang>
|
||||||
<elasticsearch>7.12.0</elasticsearch>
|
<elasticsearch>7.12.1</elasticsearch>
|
||||||
<log4j>2.13.3</log4j>
|
<log4j>2.13.3</log4j>
|
||||||
<netty>4.1.52.Final</netty>
|
<netty>4.1.52.Final</netty>
|
||||||
<springdata.commons>2.5.0</springdata.commons>
|
<springdata.commons>2.5.5</springdata.commons>
|
||||||
<testcontainers>1.15.1</testcontainers>
|
<testcontainers>1.15.1</testcontainers>
|
||||||
<java-module-name>spring.data.elasticsearch</java-module-name>
|
<java-module-name>spring.data.elasticsearch</java-module-name>
|
||||||
</properties>
|
</properties>
|
||||||
@ -488,7 +488,6 @@
|
|||||||
<id>local-maven-repo</id>
|
<id>local-maven-repo</id>
|
||||||
<url>file:///${project.basedir}/src/test/resources/local-maven-repo</url>
|
<url>file:///${project.basedir}/src/test/resources/local-maven-repo</url>
|
||||||
</repository>
|
</repository>
|
||||||
|
|
||||||
</repositories>
|
</repositories>
|
||||||
|
|
||||||
<pluginRepositories>
|
<pluginRepositories>
|
||||||
@ -496,11 +495,6 @@
|
|||||||
<id>spring-plugins-release</id>
|
<id>spring-plugins-release</id>
|
||||||
<url>https://repo.spring.io/plugins-release</url>
|
<url>https://repo.spring.io/plugins-release</url>
|
||||||
</pluginRepository>
|
</pluginRepository>
|
||||||
<pluginRepository>
|
|
||||||
<id>bintray-plugins</id>
|
|
||||||
<name>bintray-plugins</name>
|
|
||||||
<url>https://jcenter.bintray.com</url>
|
|
||||||
</pluginRepository>
|
|
||||||
</pluginRepositories>
|
</pluginRepositories>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
29
settings.xml
Normal file
29
settings.xml
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
|
||||||
|
https://maven.apache.org/xsd/settings-1.0.0.xsd">
|
||||||
|
|
||||||
|
<servers>
|
||||||
|
<server>
|
||||||
|
<id>spring-plugins-release</id>
|
||||||
|
<username>${env.ARTIFACTORY_USR}</username>
|
||||||
|
<password>${env.ARTIFACTORY_PSW}</password>
|
||||||
|
</server>
|
||||||
|
<server>
|
||||||
|
<id>spring-libs-snapshot</id>
|
||||||
|
<username>${env.ARTIFACTORY_USR}</username>
|
||||||
|
<password>${env.ARTIFACTORY_PSW}</password>
|
||||||
|
</server>
|
||||||
|
<server>
|
||||||
|
<id>spring-libs-milestone</id>
|
||||||
|
<username>${env.ARTIFACTORY_USR}</username>
|
||||||
|
<password>${env.ARTIFACTORY_PSW}</password>
|
||||||
|
</server>
|
||||||
|
<server>
|
||||||
|
<id>spring-libs-release</id>
|
||||||
|
<username>${env.ARTIFACTORY_USR}</username>
|
||||||
|
<password>${env.ARTIFACTORY_PSW}</password>
|
||||||
|
</server>
|
||||||
|
</servers>
|
||||||
|
|
||||||
|
</settings>
|
@ -34,7 +34,7 @@ The following table shows the Elasticsearch versions that are used by Spring Dat
|
|||||||
[cols="^,^,^,^,^",options="header"]
|
[cols="^,^,^,^,^",options="header"]
|
||||||
|===
|
|===
|
||||||
| Spring Data Release Train | Spring Data Elasticsearch | Elasticsearch | Spring Framework | Spring Boot
|
| Spring Data Release Train | Spring Data Elasticsearch | Elasticsearch | Spring Framework | Spring Boot
|
||||||
| 2021.0 (Pascal)footnote:cdv[Currently in development] | 4.2.xfootnote:cdv[] | 7.12.0 | 5.3.xfootnote:cdv[] | 2.4.xfootnote:cdv[]
|
| 2021.0 (Pascal) | 4.2.1 | 7.12.1 | 5.3.7 | 2.5.x
|
||||||
| 2020.0 (Ockham) | 4.1.x | 7.9.3 | 5.3.2 | 2.4.x
|
| 2020.0 (Ockham) | 4.1.x | 7.9.3 | 5.3.2 | 2.4.x
|
||||||
| Neumann | 4.0.x | 7.6.2 | 5.2.12 |2.3.x
|
| Neumann | 4.0.x | 7.6.2 | 5.2.12 |2.3.x
|
||||||
| Moore | 3.2.x |6.8.12 | 5.2.12| 2.2.x
|
| Moore | 3.2.x |6.8.12 | 5.2.12| 2.2.x
|
||||||
|
@ -30,11 +30,15 @@ public class Person implements Persistable<Long> {
|
|||||||
@Id private Long id;
|
@Id private Long id;
|
||||||
private String lastName;
|
private String lastName;
|
||||||
private String firstName;
|
private String firstName;
|
||||||
|
@CreatedDate
|
||||||
@Field(type = FieldType.Date, format = DateFormat.basic_date_time)
|
@Field(type = FieldType.Date, format = DateFormat.basic_date_time)
|
||||||
private Instant createdDate;
|
private Instant createdDate;
|
||||||
|
@CreatedBy
|
||||||
private String createdBy
|
private String createdBy
|
||||||
@Field(type = FieldType.Date, format = DateFormat.basic_date_time)
|
@Field(type = FieldType.Date, format = DateFormat.basic_date_time)
|
||||||
|
@LastModifiedDate
|
||||||
private Instant lastModifiedDate;
|
private Instant lastModifiedDate;
|
||||||
|
@LastModifiedBy
|
||||||
private String lastModifiedBy;
|
private String lastModifiedBy;
|
||||||
|
|
||||||
public Long getId() { // <.>
|
public Long getId() { // <.>
|
||||||
|
@ -54,6 +54,7 @@ import org.springframework.util.Assert;
|
|||||||
* @author Huw Ayling-Miller
|
* @author Huw Ayling-Miller
|
||||||
* @author Henrique Amaral
|
* @author Henrique Amaral
|
||||||
* @author Peter-Josef Meisch
|
* @author Peter-Josef Meisch
|
||||||
|
* @author Nic Hines
|
||||||
* @since 3.2
|
* @since 3.2
|
||||||
*/
|
*/
|
||||||
public final class RestClients {
|
public final class RestClients {
|
||||||
@ -104,15 +105,14 @@ public final class RestClients {
|
|||||||
Duration connectTimeout = clientConfiguration.getConnectTimeout();
|
Duration connectTimeout = clientConfiguration.getConnectTimeout();
|
||||||
|
|
||||||
if (!connectTimeout.isNegative()) {
|
if (!connectTimeout.isNegative()) {
|
||||||
|
|
||||||
requestConfigBuilder.setConnectTimeout(Math.toIntExact(connectTimeout.toMillis()));
|
requestConfigBuilder.setConnectTimeout(Math.toIntExact(connectTimeout.toMillis()));
|
||||||
requestConfigBuilder.setConnectionRequestTimeout(Math.toIntExact(connectTimeout.toMillis()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Duration timeout = clientConfiguration.getSocketTimeout();
|
Duration socketTimeout = clientConfiguration.getSocketTimeout();
|
||||||
|
|
||||||
if (!timeout.isNegative()) {
|
if (!socketTimeout.isNegative()) {
|
||||||
requestConfigBuilder.setSocketTimeout(Math.toIntExact(timeout.toMillis()));
|
requestConfigBuilder.setSocketTimeout(Math.toIntExact(socketTimeout.toMillis()));
|
||||||
|
requestConfigBuilder.setConnectionRequestTimeout(Math.toIntExact(socketTimeout.toMillis()));
|
||||||
}
|
}
|
||||||
|
|
||||||
clientBuilder.setDefaultRequestConfig(requestConfigBuilder.build());
|
clientBuilder.setDefaultRequestConfig(requestConfigBuilder.build());
|
||||||
|
@ -281,15 +281,23 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
|
|||||||
scheme = "https";
|
scheme = "https";
|
||||||
}
|
}
|
||||||
|
|
||||||
ReactorClientHttpConnector connector = new ReactorClientHttpConnector(httpClient);
|
WebClientProvider provider = WebClientProvider.create(scheme, new ReactorClientHttpConnector(httpClient));
|
||||||
WebClientProvider provider = WebClientProvider.create(scheme, connector);
|
|
||||||
|
|
||||||
if (clientConfiguration.getPathPrefix() != null) {
|
if (clientConfiguration.getPathPrefix() != null) {
|
||||||
provider = provider.withPathPrefix(clientConfiguration.getPathPrefix());
|
provider = provider.withPathPrefix(clientConfiguration.getPathPrefix());
|
||||||
}
|
}
|
||||||
|
|
||||||
provider = provider.withDefaultHeaders(clientConfiguration.getDefaultHeaders()) //
|
provider = provider //
|
||||||
.withWebClientConfigurer(clientConfiguration.getWebClientConfigurer());
|
.withDefaultHeaders(clientConfiguration.getDefaultHeaders()) //
|
||||||
|
.withWebClientConfigurer(clientConfiguration.getWebClientConfigurer()) //
|
||||||
|
.withRequestConfigurer(requestHeadersSpec -> requestHeadersSpec.headers(httpHeaders -> {
|
||||||
|
HttpHeaders suppliedHeaders = clientConfiguration.getHeadersSupplier().get();
|
||||||
|
|
||||||
|
if (suppliedHeaders != null && suppliedHeaders != HttpHeaders.EMPTY) {
|
||||||
|
httpHeaders.addAll(suppliedHeaders);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
return provider;
|
return provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -584,12 +592,6 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
|
|||||||
request.getOptions().getHeaders().forEach(it -> theHeaders.add(it.getName(), it.getValue()));
|
request.getOptions().getHeaders().forEach(it -> theHeaders.add(it.getName(), it.getValue()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// plus the ones from the supplier
|
|
||||||
HttpHeaders suppliedHeaders = headersSupplier.get();
|
|
||||||
if (suppliedHeaders != null && suppliedHeaders != HttpHeaders.EMPTY) {
|
|
||||||
theHeaders.addAll(suppliedHeaders);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (request.getEntity() != null) {
|
if (request.getEntity() != null) {
|
||||||
@ -599,8 +601,8 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
|
|||||||
ClientLogger.logRequest(logId, request.getMethod().toUpperCase(), request.getEndpoint(), request.getParameters(),
|
ClientLogger.logRequest(logId, request.getMethod().toUpperCase(), request.getEndpoint(), request.getParameters(),
|
||||||
body::get);
|
body::get);
|
||||||
|
|
||||||
requestBodySpec.contentType(MediaType.valueOf(request.getEntity().getContentType().getValue()));
|
requestBodySpec.contentType(MediaType.valueOf(request.getEntity().getContentType().getValue()))
|
||||||
requestBodySpec.body(Mono.fromSupplier(body), String.class);
|
.body(Mono.fromSupplier(body), String.class);
|
||||||
} else {
|
} else {
|
||||||
ClientLogger.logRequest(logId, request.getMethod().toUpperCase(), request.getEndpoint(), request.getParameters());
|
ClientLogger.logRequest(logId, request.getMethod().toUpperCase(), request.getEndpoint(), request.getParameters());
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,7 @@ class DefaultWebClientProvider implements WebClientProvider {
|
|||||||
private final HttpHeaders headers;
|
private final HttpHeaders headers;
|
||||||
private final @Nullable String pathPrefix;
|
private final @Nullable String pathPrefix;
|
||||||
private final Function<WebClient, WebClient> webClientConfigurer;
|
private final Function<WebClient, WebClient> webClientConfigurer;
|
||||||
|
private final Consumer<WebClient.RequestHeadersSpec<?>> requestConfigurer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create new {@link DefaultWebClientProvider} with empty {@link HttpHeaders} and no-op {@literal error listener}.
|
* Create new {@link DefaultWebClientProvider} with empty {@link HttpHeaders} and no-op {@literal error listener}.
|
||||||
@ -56,7 +57,7 @@ class DefaultWebClientProvider implements WebClientProvider {
|
|||||||
* @param connector can be {@literal null}.
|
* @param connector can be {@literal null}.
|
||||||
*/
|
*/
|
||||||
DefaultWebClientProvider(String scheme, @Nullable ClientHttpConnector connector) {
|
DefaultWebClientProvider(String scheme, @Nullable ClientHttpConnector connector) {
|
||||||
this(scheme, connector, e -> {}, HttpHeaders.EMPTY, null, Function.identity());
|
this(scheme, connector, e -> {}, HttpHeaders.EMPTY, null, Function.identity(), requestHeadersSpec -> {});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -66,18 +67,21 @@ class DefaultWebClientProvider implements WebClientProvider {
|
|||||||
* @param connector can be {@literal null}.
|
* @param connector can be {@literal null}.
|
||||||
* @param errorListener must not be {@literal null}.
|
* @param errorListener must not be {@literal null}.
|
||||||
* @param headers must not be {@literal null}.
|
* @param headers must not be {@literal null}.
|
||||||
* @param pathPrefix can be {@literal null}
|
* @param pathPrefix can be {@literal null}.
|
||||||
* @param webClientConfigurer must not be {@literal null}.
|
* @param webClientConfigurer must not be {@literal null}.
|
||||||
|
* @param requestConfigurer must not be {@literal null}.
|
||||||
*/
|
*/
|
||||||
private DefaultWebClientProvider(String scheme, @Nullable ClientHttpConnector connector,
|
private DefaultWebClientProvider(String scheme, @Nullable ClientHttpConnector connector,
|
||||||
Consumer<Throwable> errorListener, HttpHeaders headers, @Nullable String pathPrefix,
|
Consumer<Throwable> errorListener, HttpHeaders headers, @Nullable String pathPrefix,
|
||||||
Function<WebClient, WebClient> webClientConfigurer) {
|
Function<WebClient, WebClient> webClientConfigurer, Consumer<WebClient.RequestHeadersSpec<?>> requestConfigurer) {
|
||||||
|
|
||||||
Assert.notNull(scheme, "Scheme must not be null! A common scheme would be 'http'.");
|
Assert.notNull(scheme, "Scheme must not be null! A common scheme would be 'http'.");
|
||||||
Assert.notNull(errorListener, "errorListener must not be null! You may want use a no-op one 'e -> {}' instead.");
|
Assert.notNull(errorListener, "errorListener must not be null! You may want use a no-op one 'e -> {}' instead.");
|
||||||
Assert.notNull(headers, "headers must not be null! Think about using 'HttpHeaders.EMPTY' as an alternative.");
|
Assert.notNull(headers, "headers must not be null! Think about using 'HttpHeaders.EMPTY' as an alternative.");
|
||||||
Assert.notNull(webClientConfigurer,
|
Assert.notNull(webClientConfigurer,
|
||||||
"webClientConfigurer must not be null! You may want use a no-op one 'Function.identity()' instead.");
|
"webClientConfigurer must not be null! You may want use a no-op one 'Function.identity()' instead.");
|
||||||
|
Assert.notNull(requestConfigurer,
|
||||||
|
"requestConfigurer must not be null! You may want use a no-op one 'r -> {}' instead.\"");
|
||||||
|
|
||||||
this.cachedClients = new ConcurrentHashMap<>();
|
this.cachedClients = new ConcurrentHashMap<>();
|
||||||
this.scheme = scheme;
|
this.scheme = scheme;
|
||||||
@ -86,6 +90,7 @@ class DefaultWebClientProvider implements WebClientProvider {
|
|||||||
this.headers = headers;
|
this.headers = headers;
|
||||||
this.pathPrefix = pathPrefix;
|
this.pathPrefix = pathPrefix;
|
||||||
this.webClientConfigurer = webClientConfigurer;
|
this.webClientConfigurer = webClientConfigurer;
|
||||||
|
this.requestConfigurer = requestConfigurer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -106,6 +111,7 @@ class DefaultWebClientProvider implements WebClientProvider {
|
|||||||
return this.errorListener;
|
return this.errorListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public String getPathPrefix() {
|
public String getPathPrefix() {
|
||||||
return pathPrefix;
|
return pathPrefix;
|
||||||
@ -120,7 +126,17 @@ class DefaultWebClientProvider implements WebClientProvider {
|
|||||||
merged.addAll(this.headers);
|
merged.addAll(this.headers);
|
||||||
merged.addAll(headers);
|
merged.addAll(headers);
|
||||||
|
|
||||||
return new DefaultWebClientProvider(scheme, connector, errorListener, merged, pathPrefix, webClientConfigurer);
|
return new DefaultWebClientProvider(scheme, connector, errorListener, merged, pathPrefix, webClientConfigurer,
|
||||||
|
requestConfigurer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WebClientProvider withRequestConfigurer(Consumer<WebClient.RequestHeadersSpec<?>> requestConfigurer) {
|
||||||
|
|
||||||
|
Assert.notNull(requestConfigurer, "requestConfigurer must not be null.");
|
||||||
|
|
||||||
|
return new DefaultWebClientProvider(scheme, connector, errorListener, headers, pathPrefix, webClientConfigurer,
|
||||||
|
requestConfigurer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -129,7 +145,8 @@ class DefaultWebClientProvider implements WebClientProvider {
|
|||||||
Assert.notNull(errorListener, "Error listener must not be null.");
|
Assert.notNull(errorListener, "Error listener must not be null.");
|
||||||
|
|
||||||
Consumer<Throwable> listener = this.errorListener.andThen(errorListener);
|
Consumer<Throwable> listener = this.errorListener.andThen(errorListener);
|
||||||
return new DefaultWebClientProvider(scheme, this.connector, listener, headers, pathPrefix, webClientConfigurer);
|
return new DefaultWebClientProvider(scheme, this.connector, listener, headers, pathPrefix, webClientConfigurer,
|
||||||
|
requestConfigurer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -137,18 +154,21 @@ class DefaultWebClientProvider implements WebClientProvider {
|
|||||||
Assert.notNull(pathPrefix, "pathPrefix must not be null.");
|
Assert.notNull(pathPrefix, "pathPrefix must not be null.");
|
||||||
|
|
||||||
return new DefaultWebClientProvider(this.scheme, this.connector, this.errorListener, this.headers, pathPrefix,
|
return new DefaultWebClientProvider(this.scheme, this.connector, this.errorListener, this.headers, pathPrefix,
|
||||||
webClientConfigurer);
|
webClientConfigurer, requestConfigurer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WebClientProvider withWebClientConfigurer(Function<WebClient, WebClient> webClientConfigurer) {
|
public WebClientProvider withWebClientConfigurer(Function<WebClient, WebClient> webClientConfigurer) {
|
||||||
return new DefaultWebClientProvider(scheme, connector, errorListener, headers, pathPrefix, webClientConfigurer);
|
return new DefaultWebClientProvider(scheme, connector, errorListener, headers, pathPrefix, webClientConfigurer,
|
||||||
|
requestConfigurer);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected WebClient createWebClientForSocketAddress(InetSocketAddress socketAddress) {
|
protected WebClient createWebClientForSocketAddress(InetSocketAddress socketAddress) {
|
||||||
|
|
||||||
Builder builder = WebClient.builder().defaultHeaders(it -> it.addAll(getDefaultHeaders()));
|
Builder builder = WebClient.builder() //
|
||||||
|
.defaultHeaders(it -> it.addAll(getDefaultHeaders())) //
|
||||||
|
.defaultRequest(requestConfigurer);
|
||||||
|
|
||||||
if (connector != null) {
|
if (connector != null) {
|
||||||
builder = builder.clientConnector(connector);
|
builder = builder.clientConnector(connector);
|
||||||
|
@ -54,9 +54,9 @@ public interface HostProvider<T extends HostProvider<T>> {
|
|||||||
Assert.notEmpty(endpoints, "Please provide at least one endpoint to connect to.");
|
Assert.notEmpty(endpoints, "Please provide at least one endpoint to connect to.");
|
||||||
|
|
||||||
if (endpoints.length == 1) {
|
if (endpoints.length == 1) {
|
||||||
return new SingleNodeHostProvider(clientProvider, headersSupplier, endpoints[0]);
|
return new SingleNodeHostProvider(clientProvider, endpoints[0]);
|
||||||
} else {
|
} else {
|
||||||
return new MultiNodeHostProvider(clientProvider, headersSupplier, endpoints);
|
return new MultiNodeHostProvider(clientProvider, endpoints);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,14 +28,12 @@ import java.util.LinkedHashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.data.elasticsearch.client.ElasticsearchHost;
|
import org.springframework.data.elasticsearch.client.ElasticsearchHost;
|
||||||
import org.springframework.data.elasticsearch.client.ElasticsearchHost.State;
|
import org.springframework.data.elasticsearch.client.ElasticsearchHost.State;
|
||||||
import org.springframework.data.elasticsearch.client.NoReachableHostException;
|
import org.springframework.data.elasticsearch.client.NoReachableHostException;
|
||||||
import org.springframework.http.HttpHeaders;
|
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.web.reactive.function.client.ClientResponse;
|
import org.springframework.web.reactive.function.client.ClientResponse;
|
||||||
import org.springframework.web.reactive.function.client.WebClient;
|
import org.springframework.web.reactive.function.client.WebClient;
|
||||||
@ -53,14 +51,11 @@ class MultiNodeHostProvider implements HostProvider<MultiNodeHostProvider> {
|
|||||||
private final static Logger LOG = LoggerFactory.getLogger(MultiNodeHostProvider.class);
|
private final static Logger LOG = LoggerFactory.getLogger(MultiNodeHostProvider.class);
|
||||||
|
|
||||||
private final WebClientProvider clientProvider;
|
private final WebClientProvider clientProvider;
|
||||||
private final Supplier<HttpHeaders> headersSupplier;
|
|
||||||
private final Map<InetSocketAddress, ElasticsearchHost> hosts;
|
private final Map<InetSocketAddress, ElasticsearchHost> hosts;
|
||||||
|
|
||||||
MultiNodeHostProvider(WebClientProvider clientProvider, Supplier<HttpHeaders> headersSupplier,
|
MultiNodeHostProvider(WebClientProvider clientProvider, InetSocketAddress... endpoints) {
|
||||||
InetSocketAddress... endpoints) {
|
|
||||||
|
|
||||||
this.clientProvider = clientProvider;
|
this.clientProvider = clientProvider;
|
||||||
this.headersSupplier = headersSupplier;
|
|
||||||
this.hosts = new ConcurrentHashMap<>();
|
this.hosts = new ConcurrentHashMap<>();
|
||||||
for (InetSocketAddress endpoint : endpoints) {
|
for (InetSocketAddress endpoint : endpoints) {
|
||||||
this.hosts.put(endpoint, new ElasticsearchHost(endpoint, State.UNKNOWN));
|
this.hosts.put(endpoint, new ElasticsearchHost(endpoint, State.UNKNOWN));
|
||||||
@ -166,7 +161,6 @@ class MultiNodeHostProvider implements HostProvider<MultiNodeHostProvider> {
|
|||||||
|
|
||||||
Mono<ClientResponse> clientResponseMono = createWebClient(host) //
|
Mono<ClientResponse> clientResponseMono = createWebClient(host) //
|
||||||
.head().uri("/") //
|
.head().uri("/") //
|
||||||
.headers(httpHeaders -> httpHeaders.addAll(headersSupplier.get())) //
|
|
||||||
.exchangeToMono(Mono::just) //
|
.exchangeToMono(Mono::just) //
|
||||||
.timeout(Duration.ofSeconds(1)) //
|
.timeout(Duration.ofSeconds(1)) //
|
||||||
.doOnError(throwable -> {
|
.doOnError(throwable -> {
|
||||||
|
@ -19,12 +19,10 @@ import reactor.core.publisher.Mono;
|
|||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
import org.springframework.data.elasticsearch.client.ElasticsearchHost;
|
import org.springframework.data.elasticsearch.client.ElasticsearchHost;
|
||||||
import org.springframework.data.elasticsearch.client.ElasticsearchHost.State;
|
import org.springframework.data.elasticsearch.client.ElasticsearchHost.State;
|
||||||
import org.springframework.data.elasticsearch.client.NoReachableHostException;
|
import org.springframework.data.elasticsearch.client.NoReachableHostException;
|
||||||
import org.springframework.http.HttpHeaders;
|
|
||||||
import org.springframework.web.reactive.function.client.WebClient;
|
import org.springframework.web.reactive.function.client.WebClient;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,15 +36,12 @@ import org.springframework.web.reactive.function.client.WebClient;
|
|||||||
class SingleNodeHostProvider implements HostProvider<SingleNodeHostProvider> {
|
class SingleNodeHostProvider implements HostProvider<SingleNodeHostProvider> {
|
||||||
|
|
||||||
private final WebClientProvider clientProvider;
|
private final WebClientProvider clientProvider;
|
||||||
private final Supplier<HttpHeaders> headersSupplier;
|
|
||||||
private final InetSocketAddress endpoint;
|
private final InetSocketAddress endpoint;
|
||||||
private volatile ElasticsearchHost state;
|
private volatile ElasticsearchHost state;
|
||||||
|
|
||||||
SingleNodeHostProvider(WebClientProvider clientProvider, Supplier<HttpHeaders> headersSupplier,
|
SingleNodeHostProvider(WebClientProvider clientProvider, InetSocketAddress endpoint) {
|
||||||
InetSocketAddress endpoint) {
|
|
||||||
|
|
||||||
this.clientProvider = clientProvider;
|
this.clientProvider = clientProvider;
|
||||||
this.headersSupplier = headersSupplier;
|
|
||||||
this.endpoint = endpoint;
|
this.endpoint = endpoint;
|
||||||
this.state = new ElasticsearchHost(this.endpoint, State.UNKNOWN);
|
this.state = new ElasticsearchHost(this.endpoint, State.UNKNOWN);
|
||||||
}
|
}
|
||||||
@ -60,7 +55,6 @@ class SingleNodeHostProvider implements HostProvider<SingleNodeHostProvider> {
|
|||||||
|
|
||||||
return createWebClient(endpoint) //
|
return createWebClient(endpoint) //
|
||||||
.head().uri("/") //
|
.head().uri("/") //
|
||||||
.headers(httpHeaders -> httpHeaders.addAll(headersSupplier.get())) //
|
|
||||||
.exchangeToMono(it -> {
|
.exchangeToMono(it -> {
|
||||||
if (it.statusCode().isError()) {
|
if (it.statusCode().isError()) {
|
||||||
state = ElasticsearchHost.offline(endpoint);
|
state = ElasticsearchHost.offline(endpoint);
|
||||||
|
@ -142,4 +142,14 @@ public interface WebClientProvider {
|
|||||||
* @since 4.0
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
WebClientProvider withWebClientConfigurer(Function<WebClient, WebClient> webClientConfigurer);
|
WebClientProvider withWebClientConfigurer(Function<WebClient, WebClient> webClientConfigurer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new instance of {@link WebClientProvider} calling the given {@link Consumer} to configure the requests of
|
||||||
|
* this {@link WebClient}.
|
||||||
|
*
|
||||||
|
* @param requestConfigurer request configuration callback
|
||||||
|
* @return new instance of {@link WebClientProvider}
|
||||||
|
* @since 4.3
|
||||||
|
*/
|
||||||
|
WebClientProvider withRequestConfigurer(Consumer<WebClient.RequestHeadersSpec<?>> requestConfigurer);
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,12 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.elasticsearch.client.analytics.InferencePipelineAggregationBuilder;
|
||||||
|
import org.elasticsearch.client.analytics.ParsedInference;
|
||||||
|
import org.elasticsearch.client.analytics.ParsedStringStats;
|
||||||
|
import org.elasticsearch.client.analytics.ParsedTopMetrics;
|
||||||
|
import org.elasticsearch.client.analytics.StringStatsAggregationBuilder;
|
||||||
|
import org.elasticsearch.client.analytics.TopMetricsAggregationBuilder;
|
||||||
import org.elasticsearch.common.ParseField;
|
import org.elasticsearch.common.ParseField;
|
||||||
import org.elasticsearch.common.xcontent.ContextParser;
|
import org.elasticsearch.common.xcontent.ContextParser;
|
||||||
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
|
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
|
||||||
@ -44,6 +50,8 @@ import org.elasticsearch.search.aggregations.bucket.histogram.HistogramAggregati
|
|||||||
import org.elasticsearch.search.aggregations.bucket.histogram.ParsedAutoDateHistogram;
|
import org.elasticsearch.search.aggregations.bucket.histogram.ParsedAutoDateHistogram;
|
||||||
import org.elasticsearch.search.aggregations.bucket.histogram.ParsedDateHistogram;
|
import org.elasticsearch.search.aggregations.bucket.histogram.ParsedDateHistogram;
|
||||||
import org.elasticsearch.search.aggregations.bucket.histogram.ParsedHistogram;
|
import org.elasticsearch.search.aggregations.bucket.histogram.ParsedHistogram;
|
||||||
|
import org.elasticsearch.search.aggregations.bucket.histogram.ParsedVariableWidthHistogram;
|
||||||
|
import org.elasticsearch.search.aggregations.bucket.histogram.VariableWidthHistogramAggregationBuilder;
|
||||||
import org.elasticsearch.search.aggregations.bucket.missing.MissingAggregationBuilder;
|
import org.elasticsearch.search.aggregations.bucket.missing.MissingAggregationBuilder;
|
||||||
import org.elasticsearch.search.aggregations.bucket.missing.ParsedMissing;
|
import org.elasticsearch.search.aggregations.bucket.missing.ParsedMissing;
|
||||||
import org.elasticsearch.search.aggregations.bucket.nested.NestedAggregationBuilder;
|
import org.elasticsearch.search.aggregations.bucket.nested.NestedAggregationBuilder;
|
||||||
@ -60,12 +68,7 @@ import org.elasticsearch.search.aggregations.bucket.range.ParsedRange;
|
|||||||
import org.elasticsearch.search.aggregations.bucket.range.RangeAggregationBuilder;
|
import org.elasticsearch.search.aggregations.bucket.range.RangeAggregationBuilder;
|
||||||
import org.elasticsearch.search.aggregations.bucket.sampler.InternalSampler;
|
import org.elasticsearch.search.aggregations.bucket.sampler.InternalSampler;
|
||||||
import org.elasticsearch.search.aggregations.bucket.sampler.ParsedSampler;
|
import org.elasticsearch.search.aggregations.bucket.sampler.ParsedSampler;
|
||||||
import org.elasticsearch.search.aggregations.bucket.terms.DoubleTerms;
|
import org.elasticsearch.search.aggregations.bucket.terms.*;
|
||||||
import org.elasticsearch.search.aggregations.bucket.terms.LongTerms;
|
|
||||||
import org.elasticsearch.search.aggregations.bucket.terms.ParsedDoubleTerms;
|
|
||||||
import org.elasticsearch.search.aggregations.bucket.terms.ParsedLongTerms;
|
|
||||||
import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
|
|
||||||
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
|
|
||||||
import org.elasticsearch.search.aggregations.metrics.*;
|
import org.elasticsearch.search.aggregations.metrics.*;
|
||||||
import org.elasticsearch.search.aggregations.pipeline.*;
|
import org.elasticsearch.search.aggregations.pipeline.*;
|
||||||
import org.elasticsearch.search.suggest.Suggest;
|
import org.elasticsearch.search.suggest.Suggest;
|
||||||
@ -81,7 +84,7 @@ import org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsea
|
|||||||
* <p>
|
* <p>
|
||||||
* Original implementation source {@link org.elasticsearch.client.RestHighLevelClient#getDefaultNamedXContents()} by
|
* Original implementation source {@link org.elasticsearch.client.RestHighLevelClient#getDefaultNamedXContents()} by
|
||||||
* {@literal Elasticsearch} (<a href="https://www.elastic.co">https://www.elastic.co</a>) licensed under the Apache
|
* {@literal Elasticsearch} (<a href="https://www.elastic.co">https://www.elastic.co</a>) licensed under the Apache
|
||||||
* License, Version 2.0.
|
* License, Version 2.0. The latest version used from Elasticsearch is 7.10.2.
|
||||||
* </p>
|
* </p>
|
||||||
* Modified for usage with {@link ReactiveElasticsearchClient}.
|
* Modified for usage with {@link ReactiveElasticsearchClient}.
|
||||||
* <p>
|
* <p>
|
||||||
@ -126,9 +129,13 @@ public class NamedXContents {
|
|||||||
map.put(HistogramAggregationBuilder.NAME, (p, c) -> ParsedHistogram.fromXContent(p, (String) c));
|
map.put(HistogramAggregationBuilder.NAME, (p, c) -> ParsedHistogram.fromXContent(p, (String) c));
|
||||||
map.put(DateHistogramAggregationBuilder.NAME, (p, c) -> ParsedDateHistogram.fromXContent(p, (String) c));
|
map.put(DateHistogramAggregationBuilder.NAME, (p, c) -> ParsedDateHistogram.fromXContent(p, (String) c));
|
||||||
map.put(AutoDateHistogramAggregationBuilder.NAME, (p, c) -> ParsedAutoDateHistogram.fromXContent(p, (String) c));
|
map.put(AutoDateHistogramAggregationBuilder.NAME, (p, c) -> ParsedAutoDateHistogram.fromXContent(p, (String) c));
|
||||||
|
map.put(VariableWidthHistogramAggregationBuilder.NAME,
|
||||||
|
(p, c) -> ParsedVariableWidthHistogram.fromXContent(p, (String) c));
|
||||||
map.put(StringTerms.NAME, (p, c) -> ParsedStringTerms.fromXContent(p, (String) c));
|
map.put(StringTerms.NAME, (p, c) -> ParsedStringTerms.fromXContent(p, (String) c));
|
||||||
map.put(LongTerms.NAME, (p, c) -> ParsedLongTerms.fromXContent(p, (String) c));
|
map.put(LongTerms.NAME, (p, c) -> ParsedLongTerms.fromXContent(p, (String) c));
|
||||||
map.put(DoubleTerms.NAME, (p, c) -> ParsedDoubleTerms.fromXContent(p, (String) c));
|
map.put(DoubleTerms.NAME, (p, c) -> ParsedDoubleTerms.fromXContent(p, (String) c));
|
||||||
|
map.put(LongRareTerms.NAME, (p, c) -> ParsedLongRareTerms.fromXContent(p, (String) c));
|
||||||
|
map.put(StringRareTerms.NAME, (p, c) -> ParsedStringRareTerms.fromXContent(p, (String) c));
|
||||||
map.put(MissingAggregationBuilder.NAME, (p, c) -> ParsedMissing.fromXContent(p, (String) c));
|
map.put(MissingAggregationBuilder.NAME, (p, c) -> ParsedMissing.fromXContent(p, (String) c));
|
||||||
map.put(NestedAggregationBuilder.NAME, (p, c) -> ParsedNested.fromXContent(p, (String) c));
|
map.put(NestedAggregationBuilder.NAME, (p, c) -> ParsedNested.fromXContent(p, (String) c));
|
||||||
map.put(ReverseNestedAggregationBuilder.NAME, (p, c) -> ParsedReverseNested.fromXContent(p, (String) c));
|
map.put(ReverseNestedAggregationBuilder.NAME, (p, c) -> ParsedReverseNested.fromXContent(p, (String) c));
|
||||||
@ -142,10 +149,15 @@ public class NamedXContents {
|
|||||||
map.put(GeoDistanceAggregationBuilder.NAME, (p, c) -> ParsedGeoDistance.fromXContent(p, (String) c));
|
map.put(GeoDistanceAggregationBuilder.NAME, (p, c) -> ParsedGeoDistance.fromXContent(p, (String) c));
|
||||||
map.put(FiltersAggregationBuilder.NAME, (p, c) -> ParsedFilters.fromXContent(p, (String) c));
|
map.put(FiltersAggregationBuilder.NAME, (p, c) -> ParsedFilters.fromXContent(p, (String) c));
|
||||||
map.put(AdjacencyMatrixAggregationBuilder.NAME, (p, c) -> ParsedAdjacencyMatrix.fromXContent(p, (String) c));
|
map.put(AdjacencyMatrixAggregationBuilder.NAME, (p, c) -> ParsedAdjacencyMatrix.fromXContent(p, (String) c));
|
||||||
|
map.put(SignificantLongTerms.NAME, (p, c) -> ParsedSignificantLongTerms.fromXContent(p, (String) c));
|
||||||
|
map.put(SignificantStringTerms.NAME, (p, c) -> ParsedSignificantStringTerms.fromXContent(p, (String) c));
|
||||||
map.put(ScriptedMetricAggregationBuilder.NAME, (p, c) -> ParsedScriptedMetric.fromXContent(p, (String) c));
|
map.put(ScriptedMetricAggregationBuilder.NAME, (p, c) -> ParsedScriptedMetric.fromXContent(p, (String) c));
|
||||||
map.put(IpRangeAggregationBuilder.NAME, (p, c) -> ParsedBinaryRange.fromXContent(p, (String) c));
|
map.put(IpRangeAggregationBuilder.NAME, (p, c) -> ParsedBinaryRange.fromXContent(p, (String) c));
|
||||||
map.put(TopHitsAggregationBuilder.NAME, (p, c) -> ParsedTopHits.fromXContent(p, (String) c));
|
map.put(TopHitsAggregationBuilder.NAME, (p, c) -> ParsedTopHits.fromXContent(p, (String) c));
|
||||||
map.put(CompositeAggregationBuilder.NAME, (p, c) -> ParsedComposite.fromXContent(p, (String) c));
|
map.put(CompositeAggregationBuilder.NAME, (p, c) -> ParsedComposite.fromXContent(p, (String) c));
|
||||||
|
map.put(StringStatsAggregationBuilder.NAME, (p, c) -> ParsedStringStats.PARSER.parse(p, (String) c));
|
||||||
|
map.put(TopMetricsAggregationBuilder.NAME, (p, c) -> ParsedTopMetrics.PARSER.parse(p, (String) c));
|
||||||
|
map.put(InferencePipelineAggregationBuilder.NAME, (p, c) -> ParsedInference.fromXContent(p, (String) (c)));
|
||||||
List<NamedXContentRegistry.Entry> entries = map.entrySet().stream().map(
|
List<NamedXContentRegistry.Entry> entries = map.entrySet().stream().map(
|
||||||
entry -> new NamedXContentRegistry.Entry(Aggregation.class, new ParseField(entry.getKey()), entry.getValue()))
|
entry -> new NamedXContentRegistry.Entry(Aggregation.class, new ParseField(entry.getKey()), entry.getValue()))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
@ -1452,7 +1452,8 @@ public class RequestConverters {
|
|||||||
// encode each part (e.g. index, type and id) separately before merging them into the path
|
// encode each part (e.g. index, type and id) separately before merging them into the path
|
||||||
// we prepend "/" to the path part to make this path absolute, otherwise there can be issues with
|
// we prepend "/" to the path part to make this path absolute, otherwise there can be issues with
|
||||||
// paths that start with `-` or contain `:`
|
// paths that start with `-` or contain `:`
|
||||||
URI uri = new URI(null, null, null, -1, '/' + pathPart, null, null);
|
// the authority must be an empty string and not null, else paths that being with slashes could have them
|
||||||
|
URI uri = new URI((String) null, "", "/" + pathPart, (String) null, (String) null);
|
||||||
// manually encode any slash that each part may contain
|
// manually encode any slash that each part may contain
|
||||||
return uri.getRawPath().substring(1).replaceAll("/", "%2F");
|
return uri.getRawPath().substring(1).replaceAll("/", "%2F");
|
||||||
} catch (URISyntaxException e) {
|
} catch (URISyntaxException e) {
|
||||||
|
@ -29,7 +29,7 @@ import org.springframework.data.mapping.context.PersistentEntities;
|
|||||||
* @author Peter-Josef Meisch
|
* @author Peter-Josef Meisch
|
||||||
* @since 4.1
|
* @since 4.1
|
||||||
*/
|
*/
|
||||||
class PersistentEntitiesFactoryBean implements FactoryBean<PersistentEntities> {
|
public class PersistentEntitiesFactoryBean implements FactoryBean<PersistentEntities> {
|
||||||
|
|
||||||
private final MappingElasticsearchConverter converter;
|
private final MappingElasticsearchConverter converter;
|
||||||
|
|
||||||
|
@ -419,7 +419,7 @@ public abstract class AbstractElasticsearchTemplate implements ElasticsearchOper
|
|||||||
Assert.notNull(query.getId(), "No document id defined for MoreLikeThisQuery");
|
Assert.notNull(query.getId(), "No document id defined for MoreLikeThisQuery");
|
||||||
|
|
||||||
MoreLikeThisQueryBuilder moreLikeThisQueryBuilder = requestFactory.moreLikeThisQueryBuilder(query, index);
|
MoreLikeThisQueryBuilder moreLikeThisQueryBuilder = requestFactory.moreLikeThisQueryBuilder(query, index);
|
||||||
return search(new NativeSearchQueryBuilder().withQuery(moreLikeThisQueryBuilder).build(), clazz, index);
|
return search(new NativeSearchQueryBuilder().withQuery(moreLikeThisQueryBuilder).withPageable(query.getPageable()).build(), clazz, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -760,15 +760,17 @@ class RequestFactory {
|
|||||||
String indexName = index.getIndexName();
|
String indexName = index.getIndexName();
|
||||||
IndexRequest indexRequest;
|
IndexRequest indexRequest;
|
||||||
|
|
||||||
if (query.getObject() != null) {
|
Object queryObject = query.getObject();
|
||||||
String id = StringUtils.isEmpty(query.getId()) ? getPersistentEntityId(query.getObject()) : query.getId();
|
|
||||||
|
if (queryObject != null) {
|
||||||
|
String id = StringUtils.isEmpty(query.getId()) ? getPersistentEntityId(queryObject) : query.getId();
|
||||||
// If we have a query id and a document id, do not ask ES to generate one.
|
// If we have a query id and a document id, do not ask ES to generate one.
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
indexRequest = new IndexRequest(indexName).id(id);
|
indexRequest = new IndexRequest(indexName).id(id);
|
||||||
} else {
|
} else {
|
||||||
indexRequest = new IndexRequest(indexName);
|
indexRequest = new IndexRequest(indexName);
|
||||||
}
|
}
|
||||||
indexRequest.source(elasticsearchConverter.mapObject(query.getObject()).toJson(), Requests.INDEX_CONTENT_TYPE);
|
indexRequest.source(elasticsearchConverter.mapObject(queryObject).toJson(), Requests.INDEX_CONTENT_TYPE);
|
||||||
} else if (query.getSource() != null) {
|
} else if (query.getSource() != null) {
|
||||||
indexRequest = new IndexRequest(indexName).id(query.getId()).source(query.getSource(),
|
indexRequest = new IndexRequest(indexName).id(query.getId()).source(query.getSource(),
|
||||||
Requests.INDEX_CONTENT_TYPE);
|
Requests.INDEX_CONTENT_TYPE);
|
||||||
@ -779,7 +781,8 @@ class RequestFactory {
|
|||||||
|
|
||||||
if (query.getVersion() != null) {
|
if (query.getVersion() != null) {
|
||||||
indexRequest.version(query.getVersion());
|
indexRequest.version(query.getVersion());
|
||||||
VersionType versionType = retrieveVersionTypeFromPersistentEntity(query.getObject().getClass());
|
VersionType versionType = retrieveVersionTypeFromPersistentEntity(
|
||||||
|
queryObject != null ? queryObject.getClass() : null);
|
||||||
indexRequest.versionType(versionType);
|
indexRequest.versionType(versionType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -814,15 +817,16 @@ class RequestFactory {
|
|||||||
|
|
||||||
IndexRequestBuilder indexRequestBuilder;
|
IndexRequestBuilder indexRequestBuilder;
|
||||||
|
|
||||||
if (query.getObject() != null) {
|
Object queryObject = query.getObject();
|
||||||
String id = StringUtils.isEmpty(query.getId()) ? getPersistentEntityId(query.getObject()) : query.getId();
|
if (queryObject != null) {
|
||||||
|
String id = StringUtils.isEmpty(query.getId()) ? getPersistentEntityId(queryObject) : query.getId();
|
||||||
// If we have a query id and a document id, do not ask ES to generate one.
|
// If we have a query id and a document id, do not ask ES to generate one.
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
indexRequestBuilder = client.prepareIndex(indexName, type, id);
|
indexRequestBuilder = client.prepareIndex(indexName, type, id);
|
||||||
} else {
|
} else {
|
||||||
indexRequestBuilder = client.prepareIndex(indexName, type);
|
indexRequestBuilder = client.prepareIndex(indexName, type);
|
||||||
}
|
}
|
||||||
indexRequestBuilder.setSource(elasticsearchConverter.mapObject(query.getObject()).toJson(),
|
indexRequestBuilder.setSource(elasticsearchConverter.mapObject(queryObject).toJson(),
|
||||||
Requests.INDEX_CONTENT_TYPE);
|
Requests.INDEX_CONTENT_TYPE);
|
||||||
} else if (query.getSource() != null) {
|
} else if (query.getSource() != null) {
|
||||||
indexRequestBuilder = client.prepareIndex(indexName, type, query.getId()).setSource(query.getSource(),
|
indexRequestBuilder = client.prepareIndex(indexName, type, query.getId()).setSource(query.getSource(),
|
||||||
@ -834,7 +838,8 @@ class RequestFactory {
|
|||||||
|
|
||||||
if (query.getVersion() != null) {
|
if (query.getVersion() != null) {
|
||||||
indexRequestBuilder.setVersion(query.getVersion());
|
indexRequestBuilder.setVersion(query.getVersion());
|
||||||
VersionType versionType = retrieveVersionTypeFromPersistentEntity(query.getObject().getClass());
|
VersionType versionType = retrieveVersionTypeFromPersistentEntity(
|
||||||
|
queryObject != null ? queryObject.getClass() : null);
|
||||||
indexRequestBuilder.setVersionType(versionType);
|
indexRequestBuilder.setVersionType(versionType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1695,12 +1700,13 @@ class RequestFactory {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private VersionType retrieveVersionTypeFromPersistentEntity(Class<?> clazz) {
|
private VersionType retrieveVersionTypeFromPersistentEntity(@Nullable Class<?> clazz) {
|
||||||
|
|
||||||
MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext = elasticsearchConverter
|
MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext = elasticsearchConverter
|
||||||
.getMappingContext();
|
.getMappingContext();
|
||||||
|
|
||||||
ElasticsearchPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(clazz);
|
ElasticsearchPersistentEntity<?> persistentEntity = clazz != null ? mappingContext.getPersistentEntity(clazz)
|
||||||
|
: null;
|
||||||
|
|
||||||
VersionType versionType = null;
|
VersionType versionType = null;
|
||||||
|
|
||||||
|
@ -19,7 +19,6 @@ import org.springframework.data.convert.EntityConverter;
|
|||||||
import org.springframework.data.elasticsearch.core.document.Document;
|
import org.springframework.data.elasticsearch.core.document.Document;
|
||||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
|
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
|
||||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
|
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
|
||||||
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
|
|
||||||
import org.springframework.data.elasticsearch.core.query.Query;
|
import org.springframework.data.elasticsearch.core.query.Query;
|
||||||
import org.springframework.data.projection.ProjectionFactory;
|
import org.springframework.data.projection.ProjectionFactory;
|
||||||
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
||||||
@ -64,7 +63,13 @@ public interface ElasticsearchConverter
|
|||||||
return idValue.toString();
|
return idValue.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
return getConversionService().convert(idValue, String.class);
|
String converted = getConversionService().convert(idValue, String.class);
|
||||||
|
|
||||||
|
if (converted == null) {
|
||||||
|
return idValue.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return converted;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -86,29 +91,15 @@ public interface ElasticsearchConverter
|
|||||||
|
|
||||||
// region query
|
// region query
|
||||||
/**
|
/**
|
||||||
* Updates a {@link CriteriaQuery} by renaming the property names in the query to the correct mapped field names and
|
* Updates a {@link Query} by renaming the property names in the query to the correct mapped field names and the
|
||||||
* the values to the converted values if the {@link ElasticsearchPersistentProperty} for a property has a
|
* values to the converted values if the {@link ElasticsearchPersistentProperty} for a property has a
|
||||||
* {@link org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentPropertyConverter}. If
|
* {@link org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentPropertyConverter}. If
|
||||||
* domainClass is null or query is not a {@link CriteriaQuery}, it's a noop.
|
* domainClass is null it's a noop.
|
||||||
*
|
*
|
||||||
* @param query the query that is internally updated
|
* @param query the query that is internally updated, must not be {@literal null}
|
||||||
* @param domainClass the class of the object that is searched with the query
|
* @param domainClass the class of the object that is searched with the query
|
||||||
*/
|
*/
|
||||||
default void updateQuery(Query query, @Nullable Class<?> domainClass) {
|
void updateQuery(Query query, @Nullable Class<?> domainClass);
|
||||||
|
|
||||||
if (domainClass != null && query instanceof CriteriaQuery) {
|
|
||||||
updateCriteriaQuery((CriteriaQuery) query, domainClass);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates a {@link CriteriaQuery} by renaming the property names in the query to the correct mapped field names and
|
|
||||||
* the values to the converted values if the {@link ElasticsearchPersistentProperty} for a property has a
|
|
||||||
* {@link org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentPropertyConverter}.
|
|
||||||
*
|
|
||||||
* @param criteriaQuery the query that is internally updated, must not be {@literal null}
|
|
||||||
* @param domainClass the class of the object that is searched with the query, must not be {@literal null}
|
|
||||||
*/
|
|
||||||
void updateCriteriaQuery(CriteriaQuery criteriaQuery, Class<?> domainClass);
|
|
||||||
// endregion
|
// endregion
|
||||||
}
|
}
|
||||||
|
@ -42,8 +42,11 @@ import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersiste
|
|||||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentPropertyConverter;
|
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentPropertyConverter;
|
||||||
import org.springframework.data.elasticsearch.core.query.Criteria;
|
import org.springframework.data.elasticsearch.core.query.Criteria;
|
||||||
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
|
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
|
||||||
|
import org.springframework.data.elasticsearch.core.query.FetchSourceFilter;
|
||||||
import org.springframework.data.elasticsearch.core.query.Field;
|
import org.springframework.data.elasticsearch.core.query.Field;
|
||||||
|
import org.springframework.data.elasticsearch.core.query.Query;
|
||||||
import org.springframework.data.elasticsearch.core.query.SeqNoPrimaryTerm;
|
import org.springframework.data.elasticsearch.core.query.SeqNoPrimaryTerm;
|
||||||
|
import org.springframework.data.elasticsearch.core.query.SourceFilter;
|
||||||
import org.springframework.data.mapping.MappingException;
|
import org.springframework.data.mapping.MappingException;
|
||||||
import org.springframework.data.mapping.PersistentPropertyAccessor;
|
import org.springframework.data.mapping.PersistentPropertyAccessor;
|
||||||
import org.springframework.data.mapping.PreferredConstructor;
|
import org.springframework.data.mapping.PreferredConstructor;
|
||||||
@ -1024,7 +1027,61 @@ public class MappingElasticsearchConverter
|
|||||||
|
|
||||||
// region queries
|
// region queries
|
||||||
@Override
|
@Override
|
||||||
public void updateCriteriaQuery(CriteriaQuery criteriaQuery, Class<?> domainClass) {
|
public void updateQuery(Query query, @Nullable Class<?> domainClass) {
|
||||||
|
|
||||||
|
Assert.notNull(query, "query must not be null");
|
||||||
|
|
||||||
|
if (domainClass != null) {
|
||||||
|
|
||||||
|
updateFieldsAndSourceFilter(query, domainClass);
|
||||||
|
|
||||||
|
if (query instanceof CriteriaQuery) {
|
||||||
|
updateCriteriaQuery((CriteriaQuery) query, domainClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateFieldsAndSourceFilter(Query query, Class<?> domainClass) {
|
||||||
|
|
||||||
|
ElasticsearchPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(domainClass);
|
||||||
|
|
||||||
|
if (persistentEntity != null) {
|
||||||
|
List<String> fields = query.getFields();
|
||||||
|
|
||||||
|
if (!fields.isEmpty()) {
|
||||||
|
query.setFields(updateFieldNames(fields, persistentEntity));
|
||||||
|
}
|
||||||
|
|
||||||
|
SourceFilter sourceFilter = query.getSourceFilter();
|
||||||
|
|
||||||
|
if (sourceFilter != null) {
|
||||||
|
|
||||||
|
String[] includes = null;
|
||||||
|
String[] excludes = null;
|
||||||
|
|
||||||
|
if (sourceFilter.getIncludes() != null) {
|
||||||
|
includes = updateFieldNames(Arrays.asList(sourceFilter.getIncludes()), persistentEntity)
|
||||||
|
.toArray(new String[] {});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sourceFilter.getExcludes() != null) {
|
||||||
|
excludes = updateFieldNames(Arrays.asList(sourceFilter.getExcludes()), persistentEntity)
|
||||||
|
.toArray(new String[] {});
|
||||||
|
}
|
||||||
|
|
||||||
|
query.addSourceFilter(new FetchSourceFilter(includes, excludes));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> updateFieldNames(List<String> fields, ElasticsearchPersistentEntity<?> persistentEntity) {
|
||||||
|
return fields.stream().map(fieldName -> {
|
||||||
|
ElasticsearchPersistentProperty persistentProperty = persistentEntity.getPersistentProperty(fieldName);
|
||||||
|
return persistentProperty != null ? persistentProperty.getFieldName() : fieldName;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateCriteriaQuery(CriteriaQuery criteriaQuery, Class<?> domainClass) {
|
||||||
|
|
||||||
Assert.notNull(criteriaQuery, "criteriaQuery must not be null");
|
Assert.notNull(criteriaQuery, "criteriaQuery must not be null");
|
||||||
Assert.notNull(domainClass, "domainClass must not be null");
|
Assert.notNull(domainClass, "domainClass must not be null");
|
||||||
|
@ -245,6 +245,7 @@ public class MappingBuilder {
|
|||||||
Field fieldAnnotation = property.findAnnotation(Field.class);
|
Field fieldAnnotation = property.findAnnotation(Field.class);
|
||||||
boolean isCompletionProperty = property.isCompletionProperty();
|
boolean isCompletionProperty = property.isCompletionProperty();
|
||||||
boolean isNestedOrObjectProperty = isNestedOrObjectProperty(property);
|
boolean isNestedOrObjectProperty = isNestedOrObjectProperty(property);
|
||||||
|
DynamicMapping dynamicMapping = property.findAnnotation(DynamicMapping.class);
|
||||||
|
|
||||||
if (!isCompletionProperty && property.isEntity() && hasRelevantAnnotation(property)) {
|
if (!isCompletionProperty && property.isEntity() && hasRelevantAnnotation(property)) {
|
||||||
|
|
||||||
@ -259,7 +260,7 @@ public class MappingBuilder {
|
|||||||
: null;
|
: null;
|
||||||
|
|
||||||
mapEntity(builder, persistentEntity, false, property.getFieldName(), true, fieldAnnotation.type(),
|
mapEntity(builder, persistentEntity, false, property.getFieldName(), true, fieldAnnotation.type(),
|
||||||
fieldAnnotation, property.findAnnotation(DynamicMapping.class));
|
fieldAnnotation, dynamicMapping);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -274,9 +275,9 @@ public class MappingBuilder {
|
|||||||
if (isRootObject && fieldAnnotation != null && property.isIdProperty()) {
|
if (isRootObject && fieldAnnotation != null && property.isIdProperty()) {
|
||||||
applyDefaultIdFieldMapping(builder, property);
|
applyDefaultIdFieldMapping(builder, property);
|
||||||
} else if (multiField != null) {
|
} else if (multiField != null) {
|
||||||
addMultiFieldMapping(builder, property, multiField, isNestedOrObjectProperty);
|
addMultiFieldMapping(builder, property, multiField, isNestedOrObjectProperty, dynamicMapping);
|
||||||
} else if (fieldAnnotation != null) {
|
} else if (fieldAnnotation != null) {
|
||||||
addSingleFieldMapping(builder, property, fieldAnnotation, isNestedOrObjectProperty);
|
addSingleFieldMapping(builder, property, fieldAnnotation, isNestedOrObjectProperty, dynamicMapping);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -377,7 +378,7 @@ public class MappingBuilder {
|
|||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
private void addSingleFieldMapping(XContentBuilder builder, ElasticsearchPersistentProperty property,
|
private void addSingleFieldMapping(XContentBuilder builder, ElasticsearchPersistentProperty property,
|
||||||
Field annotation, boolean nestedOrObjectField) throws IOException {
|
Field annotation, boolean nestedOrObjectField, @Nullable DynamicMapping dynamicMapping) throws IOException {
|
||||||
|
|
||||||
// build the property json, if empty skip it as this is no valid mapping
|
// build the property json, if empty skip it as this is no valid mapping
|
||||||
XContentBuilder propertyBuilder = jsonBuilder().startObject();
|
XContentBuilder propertyBuilder = jsonBuilder().startObject();
|
||||||
@ -389,6 +390,11 @@ public class MappingBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
builder.startObject(property.getFieldName());
|
builder.startObject(property.getFieldName());
|
||||||
|
|
||||||
|
if (nestedOrObjectField && dynamicMapping != null) {
|
||||||
|
builder.field(TYPE_DYNAMIC, dynamicMapping.value().name().toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
addFieldMappingParameters(builder, annotation, nestedOrObjectField);
|
addFieldMappingParameters(builder, annotation, nestedOrObjectField);
|
||||||
builder.endObject();
|
builder.endObject();
|
||||||
}
|
}
|
||||||
@ -429,10 +435,15 @@ public class MappingBuilder {
|
|||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
private void addMultiFieldMapping(XContentBuilder builder, ElasticsearchPersistentProperty property,
|
private void addMultiFieldMapping(XContentBuilder builder, ElasticsearchPersistentProperty property,
|
||||||
MultiField annotation, boolean nestedOrObjectField) throws IOException {
|
MultiField annotation, boolean nestedOrObjectField, @Nullable DynamicMapping dynamicMapping) throws IOException {
|
||||||
|
|
||||||
// main field
|
// main field
|
||||||
builder.startObject(property.getFieldName());
|
builder.startObject(property.getFieldName());
|
||||||
|
|
||||||
|
if (nestedOrObjectField && dynamicMapping != null) {
|
||||||
|
builder.field(TYPE_DYNAMIC, dynamicMapping.value().name().toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
addFieldMappingParameters(builder, annotation.mainField(), nestedOrObjectField);
|
addFieldMappingParameters(builder, annotation.mainField(), nestedOrObjectField);
|
||||||
|
|
||||||
// inner fields
|
// inner fields
|
||||||
|
@ -15,10 +15,14 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.elasticsearch.core.join;
|
package org.springframework.data.elasticsearch.core.join;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import org.springframework.data.annotation.PersistenceConstructor;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Subhobrata Dey
|
* @author Subhobrata Dey
|
||||||
|
* @author Sascha Woo
|
||||||
* @since 4.1
|
* @since 4.1
|
||||||
*/
|
*/
|
||||||
public class JoinField<ID> {
|
public class JoinField<ID> {
|
||||||
@ -35,6 +39,7 @@ public class JoinField<ID> {
|
|||||||
this(name, null);
|
this(name, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PersistenceConstructor
|
||||||
public JoinField(String name, @Nullable ID parent) {
|
public JoinField(String name, @Nullable ID parent) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
@ -52,4 +57,21 @@ public class JoinField<ID> {
|
|||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(name, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!(obj instanceof JoinField)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
JoinField other = (JoinField) obj;
|
||||||
|
return Objects.equals(name, other.name) && Objects.equals(parent, other.parent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,6 +96,15 @@ abstract class AbstractQuery implements Query {
|
|||||||
return fields;
|
return fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFields(List<String> fields) {
|
||||||
|
|
||||||
|
Assert.notNull(fields, "fields must not be null");
|
||||||
|
|
||||||
|
this.fields.clear();
|
||||||
|
this.fields.addAll(fields);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addSourceFilter(SourceFilter sourceFilter) {
|
public void addSourceFilter(SourceFilter sourceFilter) {
|
||||||
this.sourceFilter = sourceFilter;
|
this.sourceFilter = sourceFilter;
|
||||||
|
@ -23,6 +23,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MoreLikeThisQuery
|
* MoreLikeThisQuery
|
||||||
@ -176,6 +177,9 @@ public class MoreLikeThisQuery {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setPageable(Pageable pageable) {
|
public void setPageable(Pageable pageable) {
|
||||||
|
|
||||||
|
Assert.notNull(pageable, "pageable must not be null");
|
||||||
|
|
||||||
this.pageable = pageable;
|
this.pageable = pageable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,6 +103,13 @@ public interface Query {
|
|||||||
*/
|
*/
|
||||||
List<String> getFields();
|
List<String> getFields();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set fields to be returned as part of search request
|
||||||
|
* @param fields must not be {@literal null}
|
||||||
|
* @since 4.2.1
|
||||||
|
*/
|
||||||
|
void setFields(List<String> fields);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add source filter to be added as part of search request
|
* Add source filter to be added as part of search request
|
||||||
*
|
*
|
||||||
|
@ -15,22 +15,20 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.elasticsearch.repository.query;
|
package org.springframework.data.elasticsearch.repository.query;
|
||||||
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import org.springframework.core.convert.support.GenericConversionService;
|
import org.springframework.core.convert.support.GenericConversionService;
|
||||||
import org.springframework.data.domain.PageRequest;
|
import org.springframework.data.domain.PageRequest;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
||||||
import org.springframework.data.elasticsearch.core.SearchHitSupport;
|
import org.springframework.data.elasticsearch.core.SearchHitSupport;
|
||||||
import org.springframework.data.elasticsearch.core.SearchHits;
|
import org.springframework.data.elasticsearch.core.SearchHits;
|
||||||
import org.springframework.data.elasticsearch.core.convert.DateTimeConverters;
|
import org.springframework.data.elasticsearch.core.convert.DateTimeConverters;
|
||||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||||
import org.springframework.data.elasticsearch.core.query.StringQuery;
|
import org.springframework.data.elasticsearch.core.query.StringQuery;
|
||||||
|
import org.springframework.data.elasticsearch.repository.support.StringQueryUtil;
|
||||||
import org.springframework.data.repository.query.ParametersParameterAccessor;
|
import org.springframework.data.repository.query.ParametersParameterAccessor;
|
||||||
import org.springframework.data.util.StreamUtils;
|
import org.springframework.data.util.StreamUtils;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.util.ClassUtils;
|
||||||
import org.springframework.util.NumberUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ElasticsearchStringQuery
|
* ElasticsearchStringQuery
|
||||||
@ -43,25 +41,8 @@ import org.springframework.util.NumberUtils;
|
|||||||
*/
|
*/
|
||||||
public class ElasticsearchStringQuery extends AbstractElasticsearchRepositoryQuery {
|
public class ElasticsearchStringQuery extends AbstractElasticsearchRepositoryQuery {
|
||||||
|
|
||||||
private static final Pattern PARAMETER_PLACEHOLDER = Pattern.compile("\\?(\\d+)");
|
|
||||||
private String query;
|
private String query;
|
||||||
|
|
||||||
private final GenericConversionService conversionService = new GenericConversionService();
|
|
||||||
|
|
||||||
{
|
|
||||||
if (!conversionService.canConvert(java.util.Date.class, String.class)) {
|
|
||||||
conversionService.addConverter(DateTimeConverters.JavaDateConverter.INSTANCE);
|
|
||||||
}
|
|
||||||
if (ClassUtils.isPresent("org.joda.time.DateTimeZone", ElasticsearchStringQuery.class.getClassLoader())) {
|
|
||||||
if (!conversionService.canConvert(org.joda.time.ReadableInstant.class, String.class)) {
|
|
||||||
conversionService.addConverter(DateTimeConverters.JodaDateTimeConverter.INSTANCE);
|
|
||||||
}
|
|
||||||
if (!conversionService.canConvert(org.joda.time.LocalDateTime.class, String.class)) {
|
|
||||||
conversionService.addConverter(DateTimeConverters.JodaLocalDateTimeConverter.INSTANCE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ElasticsearchStringQuery(ElasticsearchQueryMethod queryMethod, ElasticsearchOperations elasticsearchOperations,
|
public ElasticsearchStringQuery(ElasticsearchQueryMethod queryMethod, ElasticsearchOperations elasticsearchOperations,
|
||||||
String query) {
|
String query) {
|
||||||
super(queryMethod, elasticsearchOperations);
|
super(queryMethod, elasticsearchOperations);
|
||||||
@ -97,52 +78,32 @@ public class ElasticsearchStringQuery extends AbstractElasticsearchRepositoryQue
|
|||||||
} else if (queryMethod.isPageQuery()) {
|
} else if (queryMethod.isPageQuery()) {
|
||||||
stringQuery.setPageable(accessor.getPageable());
|
stringQuery.setPageable(accessor.getPageable());
|
||||||
SearchHits<?> searchHits = elasticsearchOperations.search(stringQuery, clazz, index);
|
SearchHits<?> searchHits = elasticsearchOperations.search(stringQuery, clazz, index);
|
||||||
|
if (queryMethod.isSearchPageMethod()) {
|
||||||
result = SearchHitSupport.searchPageFor(searchHits, stringQuery.getPageable());
|
result = SearchHitSupport.searchPageFor(searchHits, stringQuery.getPageable());
|
||||||
} else if (queryMethod.isStreamQuery()) {
|
|
||||||
if (accessor.getPageable().isUnpaged()) {
|
|
||||||
stringQuery.setPageable(PageRequest.of(0, DEFAULT_STREAM_BATCH_SIZE));
|
|
||||||
} else {
|
} else {
|
||||||
stringQuery.setPageable(accessor.getPageable());
|
result = SearchHitSupport
|
||||||
|
.unwrapSearchHits(SearchHitSupport.searchPageFor(searchHits, stringQuery.getPageable()));
|
||||||
}
|
}
|
||||||
|
} else if (queryMethod.isStreamQuery()) {
|
||||||
|
stringQuery.setPageable(
|
||||||
|
accessor.getPageable().isPaged() ? accessor.getPageable() : PageRequest.of(0, DEFAULT_STREAM_BATCH_SIZE));
|
||||||
result = StreamUtils.createStreamFromIterator(elasticsearchOperations.searchForStream(stringQuery, clazz, index));
|
result = StreamUtils.createStreamFromIterator(elasticsearchOperations.searchForStream(stringQuery, clazz, index));
|
||||||
} else if (queryMethod.isCollectionQuery()) {
|
} else if (queryMethod.isCollectionQuery()) {
|
||||||
if (accessor.getPageable().isPaged()) {
|
stringQuery.setPageable(accessor.getPageable().isPaged() ? accessor.getPageable() : Pageable.unpaged());
|
||||||
stringQuery.setPageable(accessor.getPageable());
|
|
||||||
}
|
|
||||||
result = elasticsearchOperations.search(stringQuery, clazz, index);
|
result = elasticsearchOperations.search(stringQuery, clazz, index);
|
||||||
} else {
|
} else {
|
||||||
result = elasticsearchOperations.searchOne(stringQuery, clazz, index);
|
result = elasticsearchOperations.searchOne(stringQuery, clazz, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
return queryMethod.isNotSearchHitMethod() ? SearchHitSupport.unwrapSearchHits(result) : result;
|
return (queryMethod.isNotSearchHitMethod() && queryMethod.isNotSearchPageMethod())
|
||||||
|
? SearchHitSupport.unwrapSearchHits(result)
|
||||||
|
: result;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected StringQuery createQuery(ParametersParameterAccessor parameterAccessor) {
|
protected StringQuery createQuery(ParametersParameterAccessor parameterAccessor) {
|
||||||
String queryString = replacePlaceholders(this.query, parameterAccessor);
|
String queryString = new StringQueryUtil(elasticsearchOperations.getElasticsearchConverter().getConversionService())
|
||||||
|
.replacePlaceholders(this.query, parameterAccessor);
|
||||||
return new StringQuery(queryString);
|
return new StringQuery(queryString);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String replacePlaceholders(String input, ParametersParameterAccessor accessor) {
|
|
||||||
|
|
||||||
Matcher matcher = PARAMETER_PLACEHOLDER.matcher(input);
|
|
||||||
String result = input;
|
|
||||||
while (matcher.find()) {
|
|
||||||
|
|
||||||
String placeholder = Pattern.quote(matcher.group()) + "(?!\\d+)";
|
|
||||||
int index = NumberUtils.parseNumber(matcher.group(1), Integer.class);
|
|
||||||
result = result.replaceAll(placeholder, getParameterWithIndex(accessor, index));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getParameterWithIndex(ParametersParameterAccessor accessor, int index) {
|
|
||||||
Object parameter = accessor.getBindableValue(index);
|
|
||||||
if (parameter == null) {
|
|
||||||
return "null";
|
|
||||||
}
|
|
||||||
if (conversionService.canConvert(parameter.getClass(), String.class)) {
|
|
||||||
return conversionService.convert(parameter, String.class);
|
|
||||||
}
|
|
||||||
return parameter.toString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -15,15 +15,11 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.elasticsearch.repository.query;
|
package org.springframework.data.elasticsearch.repository.query;
|
||||||
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations;
|
import org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations;
|
||||||
import org.springframework.data.elasticsearch.core.query.StringQuery;
|
import org.springframework.data.elasticsearch.core.query.StringQuery;
|
||||||
|
import org.springframework.data.elasticsearch.repository.support.StringQueryUtil;
|
||||||
import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider;
|
import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider;
|
||||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||||
import org.springframework.util.NumberUtils;
|
|
||||||
import org.springframework.util.ObjectUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Christoph Strobl
|
* @author Christoph Strobl
|
||||||
@ -32,7 +28,6 @@ import org.springframework.util.ObjectUtils;
|
|||||||
*/
|
*/
|
||||||
public class ReactiveElasticsearchStringQuery extends AbstractReactiveElasticsearchRepositoryQuery {
|
public class ReactiveElasticsearchStringQuery extends AbstractReactiveElasticsearchRepositoryQuery {
|
||||||
|
|
||||||
private static final Pattern PARAMETER_PLACEHOLDER = Pattern.compile("\\?(\\d+)");
|
|
||||||
private final String query;
|
private final String query;
|
||||||
|
|
||||||
public ReactiveElasticsearchStringQuery(ReactiveElasticsearchQueryMethod queryMethod,
|
public ReactiveElasticsearchStringQuery(ReactiveElasticsearchQueryMethod queryMethod,
|
||||||
@ -52,27 +47,12 @@ public class ReactiveElasticsearchStringQuery extends AbstractReactiveElasticsea
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected StringQuery createQuery(ElasticsearchParameterAccessor parameterAccessor) {
|
protected StringQuery createQuery(ElasticsearchParameterAccessor parameterAccessor) {
|
||||||
String queryString = replacePlaceholders(this.query, parameterAccessor);
|
String queryString = new StringQueryUtil(
|
||||||
|
getElasticsearchOperations().getElasticsearchConverter().getConversionService()).replacePlaceholders(this.query,
|
||||||
|
parameterAccessor);
|
||||||
return new StringQuery(queryString);
|
return new StringQuery(queryString);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String replacePlaceholders(String input, ElasticsearchParameterAccessor accessor) {
|
|
||||||
|
|
||||||
Matcher matcher = PARAMETER_PLACEHOLDER.matcher(input);
|
|
||||||
String result = input;
|
|
||||||
while (matcher.find()) {
|
|
||||||
|
|
||||||
String placeholder = Pattern.quote(matcher.group()) + "(?!\\d+)";
|
|
||||||
int index = NumberUtils.parseNumber(matcher.group(1), Integer.class);
|
|
||||||
result = result.replaceAll(placeholder, getParameterWithIndex(accessor, index));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getParameterWithIndex(ElasticsearchParameterAccessor accessor, int index) {
|
|
||||||
return ObjectUtils.nullSafeToString(accessor.getBindableValue(index));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
boolean isCountQuery() {
|
boolean isCountQuery() {
|
||||||
return queryMethod.hasCountQueryAnnotation();
|
return queryMethod.hasCountQueryAnnotation();
|
||||||
|
@ -0,0 +1,135 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 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.repository.support;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.springframework.core.convert.ConversionService;
|
||||||
|
import org.springframework.core.convert.support.GenericConversionService;
|
||||||
|
import org.springframework.data.elasticsearch.core.convert.DateTimeConverters;
|
||||||
|
import org.springframework.data.elasticsearch.repository.query.ElasticsearchStringQuery;
|
||||||
|
import org.springframework.data.repository.query.ParameterAccessor;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.ClassUtils;
|
||||||
|
import org.springframework.util.NumberUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Peter-Josef Meisch
|
||||||
|
* @author Niklas Herder
|
||||||
|
*/
|
||||||
|
final public class StringQueryUtil {
|
||||||
|
|
||||||
|
private static final Pattern PARAMETER_PLACEHOLDER = Pattern.compile("\\?(\\d+)");
|
||||||
|
|
||||||
|
private final ConversionService conversionService;
|
||||||
|
private final GenericConversionService genericConversionService;
|
||||||
|
|
||||||
|
public StringQueryUtil(ConversionService conversionService) {
|
||||||
|
|
||||||
|
Assert.notNull(conversionService, "conversionService must not be null");
|
||||||
|
|
||||||
|
this.conversionService = conversionService;
|
||||||
|
genericConversionService = setupGenericConversionService();
|
||||||
|
}
|
||||||
|
|
||||||
|
private GenericConversionService setupGenericConversionService() {
|
||||||
|
|
||||||
|
GenericConversionService genericConversionService = new GenericConversionService();
|
||||||
|
|
||||||
|
if (!genericConversionService.canConvert(java.util.Date.class, String.class)) {
|
||||||
|
genericConversionService.addConverter(DateTimeConverters.JavaDateConverter.INSTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ClassUtils.isPresent("org.joda.time.DateTimeZone", ElasticsearchStringQuery.class.getClassLoader())) {
|
||||||
|
if (!genericConversionService.canConvert(org.joda.time.ReadableInstant.class, String.class)) {
|
||||||
|
genericConversionService.addConverter(DateTimeConverters.JodaDateTimeConverter.INSTANCE);
|
||||||
|
}
|
||||||
|
if (!genericConversionService.canConvert(org.joda.time.LocalDateTime.class, String.class)) {
|
||||||
|
genericConversionService.addConverter(DateTimeConverters.JodaLocalDateTimeConverter.INSTANCE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return genericConversionService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String replacePlaceholders(String input, ParameterAccessor accessor) {
|
||||||
|
|
||||||
|
Matcher matcher = PARAMETER_PLACEHOLDER.matcher(input);
|
||||||
|
String result = input;
|
||||||
|
while (matcher.find()) {
|
||||||
|
|
||||||
|
String placeholder = Pattern.quote(matcher.group()) + "(?!\\d+)";
|
||||||
|
int index = NumberUtils.parseNumber(matcher.group(1), Integer.class);
|
||||||
|
result = result.replaceAll(placeholder, Matcher.quoteReplacement(getParameterWithIndex(accessor, index)));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getParameterWithIndex(ParameterAccessor accessor, int index) {
|
||||||
|
|
||||||
|
Object parameter = accessor.getBindableValue(index);
|
||||||
|
String parameterValue = "null";
|
||||||
|
|
||||||
|
// noinspection ConstantConditions
|
||||||
|
if (parameter != null) {
|
||||||
|
|
||||||
|
parameterValue = convert(parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return parameterValue;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private String convert(Object parameter) {
|
||||||
|
if (Collection.class.isAssignableFrom(parameter.getClass())) {
|
||||||
|
Collection<?> collectionParam = (Collection<?>) parameter;
|
||||||
|
StringBuilder sb = new StringBuilder("[");
|
||||||
|
sb.append(collectionParam.stream().map(o -> {
|
||||||
|
if (o instanceof String) {
|
||||||
|
return "\"" + convert(o) + "\"";
|
||||||
|
} else {
|
||||||
|
return convert(o);
|
||||||
|
}
|
||||||
|
}).collect(Collectors.joining(",")));
|
||||||
|
sb.append("]");
|
||||||
|
return sb.toString();
|
||||||
|
} else {
|
||||||
|
String parameterValue = "null";
|
||||||
|
if (conversionService.canConvert(parameter.getClass(), String.class)) {
|
||||||
|
String converted = conversionService.convert(parameter, String.class);
|
||||||
|
|
||||||
|
if (converted != null) {
|
||||||
|
parameterValue = converted;
|
||||||
|
}
|
||||||
|
} else if (genericConversionService.canConvert(parameter.getClass(), String.class)) {
|
||||||
|
String converted = genericConversionService.convert(parameter, String.class);
|
||||||
|
|
||||||
|
if (converted != null) {
|
||||||
|
parameterValue = converted;
|
||||||
|
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
parameterValue = parameter.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
parameterValue = parameterValue.replaceAll("\"", Matcher.quoteReplacement("\\\""));
|
||||||
|
return parameterValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,6 +1,45 @@
|
|||||||
Spring Data Elasticsearch Changelog
|
Spring Data Elasticsearch Changelog
|
||||||
===================================
|
===================================
|
||||||
|
|
||||||
|
Changes in version 4.2.3 (2021-07-16)
|
||||||
|
-------------------------------------
|
||||||
|
* #1866 - Queries defined with `@Query` are not using registered converters for parameter conversion.
|
||||||
|
* #1858 - Collection parameters for @Query-annotated methods get escaped wrongly.
|
||||||
|
* #1846 - Missing hashCode and equals methods in JoinField.
|
||||||
|
|
||||||
|
|
||||||
|
Changes in version 4.2.2 (2021-06-22)
|
||||||
|
-------------------------------------
|
||||||
|
* #1834 - TopMetricsAggregation NamedObjectNotFoundException: unknown field [top_metrics].
|
||||||
|
|
||||||
|
|
||||||
|
Changes in version 4.1.10 (2021-06-22)
|
||||||
|
--------------------------------------
|
||||||
|
* #1843 - Pageable results and @Query annotation.
|
||||||
|
* #1834 - TopMetricsAggregation NamedObjectNotFoundException: unknown field [top_metrics].
|
||||||
|
|
||||||
|
|
||||||
|
Changes in version 4.2.1 (2021-05-14)
|
||||||
|
-------------------------------------
|
||||||
|
* #1811 - StringQuery execution crashes on return type `SearchPage<T>`.
|
||||||
|
* #1805 - Upgrade to Elasticsearch 7.12.1.
|
||||||
|
* #1794 - Refactor `DefaultReactiveElasticsearchClient` to do request customization with the `WebClient`.
|
||||||
|
* #1790 - Custom Query with string parameter which contains double quotes.
|
||||||
|
* #1787 - Search with MoreLikeThisQuery should use Pageable.
|
||||||
|
* #1785 - Fix documentation about auditing.
|
||||||
|
* #1778 - Custom property names must be used in SourceFilter and source fields.
|
||||||
|
* #1767 - DynamicMapping annotation should be applicable to any object field.
|
||||||
|
|
||||||
|
|
||||||
|
Changes in version 4.1.9 (2021-05-14)
|
||||||
|
-------------------------------------
|
||||||
|
* #1811 - StringQuery execution crashes on return type `SearchPage<T>`.
|
||||||
|
* #1790 - Custom Query with string parameter which contains double quotes.
|
||||||
|
* #1787 - Search with MoreLikeThisQuery should use Pageable.
|
||||||
|
* #1785 - Fix documentation about auditing.
|
||||||
|
* #1767 - DynamicMapping annotation should be applicable to any object field.
|
||||||
|
|
||||||
|
|
||||||
Changes in version 4.2.0 (2021-04-14)
|
Changes in version 4.2.0 (2021-04-14)
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
* #1771 - Remove `@Persistent` from entity-scan include filters.
|
* #1771 - Remove `@Persistent` from entity-scan include filters.
|
||||||
@ -1597,6 +1636,11 @@ Release Notes - Spring Data Elasticsearch - Version 1.0 M1 (2014-02-07)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Spring Data Elasticsearch 4.2 GA (2021.0.0)
|
Spring Data Elasticsearch 4.2.5 (2021.0.5)
|
||||||
Copyright (c) [2013-2021] Pivotal Software, Inc.
|
Copyright (c) [2013-2021] Pivotal Software, Inc.
|
||||||
|
|
||||||
This product is licensed to you under the Apache License, Version 2.0 (the "License").
|
This product is licensed to you under the Apache License, Version 2.0 (the "License").
|
||||||
@ -23,6 +23,11 @@ conditions of the subcomponent's license, as noted in the LICENSE file.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -83,10 +83,10 @@ public class ReactiveMockClientTestsUtils {
|
|||||||
|
|
||||||
if (hosts.length == 1) {
|
if (hosts.length == 1) {
|
||||||
// noinspection unchecked
|
// noinspection unchecked
|
||||||
delegate = (T) new SingleNodeHostProvider(clientProvider, HttpHeaders::new, getInetSocketAddress(hosts[0])) {};
|
delegate = (T) new SingleNodeHostProvider(clientProvider, getInetSocketAddress(hosts[0])) {};
|
||||||
} else {
|
} else {
|
||||||
// noinspection unchecked
|
// noinspection unchecked
|
||||||
delegate = (T) new MultiNodeHostProvider(clientProvider, HttpHeaders::new, Arrays.stream(hosts)
|
delegate = (T) new MultiNodeHostProvider(clientProvider, Arrays.stream(hosts)
|
||||||
.map(ReactiveMockClientTestsUtils::getInetSocketAddress).toArray(InetSocketAddress[]::new)) {};
|
.map(ReactiveMockClientTestsUtils::getInetSocketAddress).toArray(InetSocketAddress[]::new)) {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,6 +297,11 @@ public class ReactiveMockClientTestsUtils {
|
|||||||
throw new UnsupportedOperationException("not implemented");
|
throw new UnsupportedOperationException("not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WebClientProvider withRequestConfigurer(Consumer<WebClient.RequestHeadersSpec<?>> requestConfigurer) {
|
||||||
|
throw new UnsupportedOperationException("not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
public Send when(String host) {
|
public Send when(String host) {
|
||||||
InetSocketAddress inetSocketAddress = getInetSocketAddress(host);
|
InetSocketAddress inetSocketAddress = getInetSocketAddress(host);
|
||||||
return new CallbackImpl(get(host), headersUriSpecMap.get(inetSocketAddress),
|
return new CallbackImpl(get(host), headersUriSpecMap.get(inetSocketAddress),
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.elasticsearch.core;
|
package org.springframework.data.elasticsearch.core;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.*;
|
|
||||||
import static org.skyscreamer.jsonassert.JSONAssert.*;
|
import static org.skyscreamer.jsonassert.JSONAssert.*;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
@ -25,6 +24,7 @@ import java.util.Date;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import org.assertj.core.api.SoftAssertions;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.DisplayName;
|
import org.junit.jupiter.api.DisplayName;
|
||||||
@ -44,6 +44,9 @@ import org.springframework.data.elasticsearch.core.geo.GeoJsonPoint;
|
|||||||
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
|
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
|
||||||
import org.springframework.data.elasticsearch.core.query.Criteria;
|
import org.springframework.data.elasticsearch.core.query.Criteria;
|
||||||
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
|
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
|
||||||
|
import org.springframework.data.elasticsearch.core.query.FetchSourceFilter;
|
||||||
|
import org.springframework.data.elasticsearch.core.query.Query;
|
||||||
|
import org.springframework.data.elasticsearch.core.query.SourceFilter;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -356,9 +359,7 @@ public class CriteriaQueryMappingUnitTests {
|
|||||||
" }\n" + //
|
" }\n" + //
|
||||||
"}\n"; //
|
"}\n"; //
|
||||||
|
|
||||||
CriteriaQuery criteriaQuery = new CriteriaQuery(
|
CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("persons.birthDate").is(LocalDate.of(1999, 10, 3)));
|
||||||
new Criteria("persons.birthDate").is(LocalDate.of(1999, 10, 3))
|
|
||||||
);
|
|
||||||
mappingElasticsearchConverter.updateQuery(criteriaQuery, House.class);
|
mappingElasticsearchConverter.updateQuery(criteriaQuery, House.class);
|
||||||
String queryString = new CriteriaQueryProcessor().createQuery(criteriaQuery.getCriteria()).toString();
|
String queryString = new CriteriaQueryProcessor().createQuery(criteriaQuery.getCriteria()).toString();
|
||||||
|
|
||||||
@ -389,9 +390,7 @@ public class CriteriaQueryMappingUnitTests {
|
|||||||
" }\n" + //
|
" }\n" + //
|
||||||
"}\n"; //
|
"}\n"; //
|
||||||
|
|
||||||
CriteriaQuery criteriaQuery = new CriteriaQuery(
|
CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("persons.nickName.keyword").is("Foobar"));
|
||||||
new Criteria("persons.nickName.keyword").is("Foobar")
|
|
||||||
);
|
|
||||||
mappingElasticsearchConverter.updateQuery(criteriaQuery, House.class);
|
mappingElasticsearchConverter.updateQuery(criteriaQuery, House.class);
|
||||||
String queryString = new CriteriaQueryProcessor().createQuery(criteriaQuery.getCriteria()).toString();
|
String queryString = new CriteriaQueryProcessor().createQuery(criteriaQuery.getCriteria()).toString();
|
||||||
|
|
||||||
@ -417,14 +416,33 @@ public class CriteriaQueryMappingUnitTests {
|
|||||||
" }\n" + //
|
" }\n" + //
|
||||||
"}\n"; //
|
"}\n"; //
|
||||||
|
|
||||||
CriteriaQuery criteriaQuery = new CriteriaQuery(
|
CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("persons.birthDate").is(LocalDate.of(1999, 10, 3)));
|
||||||
new Criteria("persons.birthDate").is(LocalDate.of(1999, 10, 3))
|
|
||||||
);
|
|
||||||
mappingElasticsearchConverter.updateQuery(criteriaQuery, ObjectWithPerson.class);
|
mappingElasticsearchConverter.updateQuery(criteriaQuery, ObjectWithPerson.class);
|
||||||
String queryString = new CriteriaQueryProcessor().createQuery(criteriaQuery.getCriteria()).toString();
|
String queryString = new CriteriaQueryProcessor().createQuery(criteriaQuery.getCriteria()).toString();
|
||||||
|
|
||||||
assertEquals(expected, queryString, false);
|
assertEquals(expected, queryString, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test // #1778
|
||||||
|
@DisplayName("should map names in source fields and SourceFilters")
|
||||||
|
void shouldMapNamesInSourceFieldsAndSourceFilters() {
|
||||||
|
|
||||||
|
Query query = Query.findAll();
|
||||||
|
// Note: we don't care if these filters make sense here, this test is only about name mapping
|
||||||
|
query.addFields("firstName", "lastName");
|
||||||
|
query.addSourceFilter(new FetchSourceFilter(new String[] { "firstName" }, new String[] { "lastName" }));
|
||||||
|
|
||||||
|
mappingElasticsearchConverter.updateQuery(query, Person.class);
|
||||||
|
|
||||||
|
SoftAssertions softly = new SoftAssertions();
|
||||||
|
softly.assertThat(query.getFields()).containsExactly("first-name", "last-name");
|
||||||
|
SourceFilter sourceFilter = query.getSourceFilter();
|
||||||
|
softly.assertThat(sourceFilter).isNotNull();
|
||||||
|
softly.assertThat(sourceFilter.getIncludes()).containsExactly("first-name");
|
||||||
|
softly.assertThat(sourceFilter.getExcludes()).containsExactly("last-name");
|
||||||
|
softly.assertAll();
|
||||||
|
}
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region helper functions
|
// region helper functions
|
||||||
@ -442,7 +460,8 @@ public class CriteriaQueryMappingUnitTests {
|
|||||||
@Nullable @Id String id;
|
@Nullable @Id String id;
|
||||||
@Nullable @Field(name = "first-name") String firstName;
|
@Nullable @Field(name = "first-name") String firstName;
|
||||||
@Nullable @Field(name = "last-name") String lastName;
|
@Nullable @Field(name = "last-name") String lastName;
|
||||||
@Nullable @MultiField(mainField = @Field(name="nick-name"), otherFields = {@InnerField(suffix = "keyword", type = FieldType.Keyword)}) String nickName;
|
@Nullable @MultiField(mainField = @Field(name = "nick-name"),
|
||||||
|
otherFields = { @InnerField(suffix = "keyword", type = FieldType.Keyword) }) String nickName;
|
||||||
@Nullable @Field(name = "created-date", type = FieldType.Date, format = DateFormat.epoch_millis) Date createdDate;
|
@Nullable @Field(name = "created-date", type = FieldType.Date, format = DateFormat.epoch_millis) Date createdDate;
|
||||||
@Nullable @Field(name = "birth-date", type = FieldType.Date, format = {},
|
@Nullable @Field(name = "birth-date", type = FieldType.Date, format = {},
|
||||||
pattern = "dd.MM.uuuu") LocalDate birthDate;
|
pattern = "dd.MM.uuuu") LocalDate birthDate;
|
||||||
@ -450,16 +469,12 @@ public class CriteriaQueryMappingUnitTests {
|
|||||||
|
|
||||||
static class House {
|
static class House {
|
||||||
@Nullable @Id String id;
|
@Nullable @Id String id;
|
||||||
@Nullable
|
@Nullable @Field(name = "per-sons", type = FieldType.Nested) List<Person> persons;
|
||||||
@Field(name = "per-sons", type = FieldType.Nested)
|
|
||||||
List<Person> persons;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static class ObjectWithPerson {
|
static class ObjectWithPerson {
|
||||||
@Nullable @Id String id;
|
@Nullable @Id String id;
|
||||||
@Nullable
|
@Nullable @Field(name = "per-sons", type = FieldType.Object) List<Person> persons;
|
||||||
@Field(name = "per-sons", type = FieldType.Object)
|
|
||||||
List<Person> persons;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static class GeoShapeEntity {
|
static class GeoShapeEntity {
|
||||||
|
@ -1116,6 +1116,51 @@ public abstract class ElasticsearchTemplateTests {
|
|||||||
assertThat(content).contains(sampleEntity);
|
assertThat(content).contains(sampleEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test // #1787
|
||||||
|
@DisplayName("should use Pageable on MoreLikeThis queries")
|
||||||
|
void shouldUsePageableOnMoreLikeThisQueries() {
|
||||||
|
|
||||||
|
String sampleMessage = "So we build a web site or an application and want to add search to it, "
|
||||||
|
+ "and then it hits us: getting search working is hard. We want our search solution to be fast,"
|
||||||
|
+ " we want a painless setup and a completely free search schema, we want to be able to index data simply using JSON over HTTP, "
|
||||||
|
+ "we want our search server to be always available, we want to be able to start with one machine and scale to hundreds, "
|
||||||
|
+ "we want real-time search, we want simple multi-tenancy, and we want a solution that is built for the cloud.";
|
||||||
|
String referenceId = nextIdAsString();
|
||||||
|
Collection<String> ids = IntStream.rangeClosed(1, 10).mapToObj(i -> nextIdAsString()).collect(Collectors.toList());
|
||||||
|
ids.add(referenceId);
|
||||||
|
ids.stream()
|
||||||
|
.map(id -> getIndexQuery(
|
||||||
|
SampleEntity.builder().id(id).message(sampleMessage).version(System.currentTimeMillis()).build()))
|
||||||
|
.forEach(indexQuery -> operations.index(indexQuery, index));
|
||||||
|
indexOperations.refresh();
|
||||||
|
|
||||||
|
MoreLikeThisQuery moreLikeThisQuery = new MoreLikeThisQuery();
|
||||||
|
moreLikeThisQuery.setId(referenceId);
|
||||||
|
moreLikeThisQuery.addFields("message");
|
||||||
|
moreLikeThisQuery.setMinDocFreq(1);
|
||||||
|
moreLikeThisQuery.setPageable(PageRequest.of(0, 5));
|
||||||
|
|
||||||
|
SearchHits<SampleEntity> searchHits = operations.search(moreLikeThisQuery, SampleEntity.class, index);
|
||||||
|
|
||||||
|
assertThat(searchHits.getTotalHits()).isEqualTo(10);
|
||||||
|
assertThat(searchHits.getSearchHits()).hasSize(5);
|
||||||
|
|
||||||
|
Collection<String> returnedIds = searchHits.getSearchHits().stream().map(SearchHit::getId)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
moreLikeThisQuery.setPageable(PageRequest.of(1, 5));
|
||||||
|
|
||||||
|
searchHits = operations.search(moreLikeThisQuery, SampleEntity.class, index);
|
||||||
|
|
||||||
|
assertThat(searchHits.getTotalHits()).isEqualTo(10);
|
||||||
|
assertThat(searchHits.getSearchHits()).hasSize(5);
|
||||||
|
|
||||||
|
searchHits.getSearchHits().stream().map(SearchHit::getId).forEach(returnedIds::add);
|
||||||
|
|
||||||
|
assertThat(returnedIds).hasSize(10);
|
||||||
|
assertThat(ids).containsAll(returnedIds);
|
||||||
|
}
|
||||||
|
|
||||||
@Test // DATAES-167
|
@Test // DATAES-167
|
||||||
public void shouldReturnResultsWithScanAndScrollForGivenCriteriaQuery() {
|
public void shouldReturnResultsWithScanAndScrollForGivenCriteriaQuery() {
|
||||||
|
|
||||||
@ -3751,6 +3796,23 @@ public abstract class ElasticsearchTemplateTests {
|
|||||||
assertThat(explanation).isNotNull();
|
assertThat(explanation).isNotNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test // #1893
|
||||||
|
@DisplayName("should index document from source with version")
|
||||||
|
void shouldIndexDocumentFromSourceWithVersion() {
|
||||||
|
|
||||||
|
String source = "{\n" + //
|
||||||
|
" \"answer\": 42\n" + //
|
||||||
|
"}";
|
||||||
|
IndexQuery query = new IndexQueryBuilder() //
|
||||||
|
.withId("42") //
|
||||||
|
.withSource(source) //
|
||||||
|
.withVersion(42L) //
|
||||||
|
.build();
|
||||||
|
|
||||||
|
operations.index(query, IndexCoordinates.of(INDEX_NAME_SAMPLE_ENTITY));
|
||||||
|
}
|
||||||
|
|
||||||
|
// region entities
|
||||||
@Document(indexName = INDEX_NAME_SAMPLE_ENTITY)
|
@Document(indexName = INDEX_NAME_SAMPLE_ENTITY)
|
||||||
@Setting(shards = 1, replicas = 0, refreshInterval = "-1")
|
@Setting(shards = 1, replicas = 0, refreshInterval = "-1")
|
||||||
static class SampleEntity {
|
static class SampleEntity {
|
||||||
@ -4528,4 +4590,5 @@ public abstract class ElasticsearchTemplateTests {
|
|||||||
this.text = text;
|
this.text = text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// endregion
|
||||||
}
|
}
|
||||||
|
@ -296,6 +296,16 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
|
|||||||
indexOps.delete();
|
indexOps.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test // #1767
|
||||||
|
@DisplayName("should write dynamic mapping entries")
|
||||||
|
void shouldWriteDynamicMappingEntries() {
|
||||||
|
|
||||||
|
IndexOperations indexOps = operations.indexOps(DynamicMappingEntity.class);
|
||||||
|
indexOps.create();
|
||||||
|
indexOps.putMapping();
|
||||||
|
indexOps.delete();
|
||||||
|
}
|
||||||
|
|
||||||
@Document(indexName = "ignore-above-index")
|
@Document(indexName = "ignore-above-index")
|
||||||
static class IgnoreAboveEntity {
|
static class IgnoreAboveEntity {
|
||||||
@Nullable @Id private String id;
|
@Nullable @Id private String id;
|
||||||
@ -1082,4 +1092,25 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
|
|||||||
this.dense_vector = dense_vector;
|
this.dense_vector = dense_vector;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Document(indexName = "dynamic-mapping")
|
||||||
|
@DynamicMapping(DynamicMappingValue.False)
|
||||||
|
static class DynamicMappingEntity {
|
||||||
|
|
||||||
|
@Nullable @DynamicMapping(DynamicMappingValue.Strict) @Field(type = FieldType.Object) private Author author;
|
||||||
|
@Nullable @DynamicMapping(DynamicMappingValue.False) @Field(
|
||||||
|
type = FieldType.Object) private Map<String, Object> objectMap;
|
||||||
|
@Nullable @DynamicMapping(DynamicMappingValue.False) @Field(
|
||||||
|
type = FieldType.Nested) private List<Map<String, Object>> nestedObjectMap;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Author getAuthor() {
|
||||||
|
return author;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthor(Author author) {
|
||||||
|
this.author = author;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@ import java.time.LocalDateTime;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.elasticsearch.search.suggest.completion.context.ContextMapping;
|
import org.elasticsearch.search.suggest.completion.context.ContextMapping;
|
||||||
@ -415,23 +416,42 @@ public class MappingBuilderUnitTests extends MappingContextBaseTests {
|
|||||||
assertEquals(expected, mapping, false);
|
assertEquals(expected, mapping, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test // DATAES-148, #1767
|
||||||
void shouldWriteDynamicMappingSettings() throws JSONException {
|
void shouldWriteDynamicMappingSettings() throws JSONException {
|
||||||
|
|
||||||
String expected = "{\n" + //
|
String expected = "{\n" + //
|
||||||
" \"dynamic\": \"false\",\n" + //
|
" \"dynamic\": \"false\",\n" + //
|
||||||
" \"properties\": {\n" + //
|
" \"properties\": {\n" + //
|
||||||
|
" \"_class\": {\n" + //
|
||||||
|
" \"type\": \"keyword\",\n" + //
|
||||||
|
" \"index\": false,\n" + //
|
||||||
|
" \"doc_values\": false\n" + //
|
||||||
|
" },\n" + //
|
||||||
" \"author\": {\n" + //
|
" \"author\": {\n" + //
|
||||||
" \"dynamic\": \"strict\",\n" + //
|
|
||||||
" \"type\": \"object\",\n" + //
|
" \"type\": \"object\",\n" + //
|
||||||
" \"properties\": {}\n" + //
|
" \"dynamic\": \"strict\",\n" + //
|
||||||
|
" \"properties\": {\n" + //
|
||||||
|
" \"_class\": {\n" + //
|
||||||
|
" \"type\": \"keyword\",\n" + //
|
||||||
|
" \"index\": false,\n" + //
|
||||||
|
" \"doc_values\": false\n" + //
|
||||||
" }\n" + //
|
" }\n" + //
|
||||||
" }\n" + //
|
" }\n" + //
|
||||||
"}\n";
|
" },\n" + //
|
||||||
|
" \"objectMap\": {\n" + //
|
||||||
|
" \"type\": \"object\",\n" + //
|
||||||
|
" \"dynamic\": \"false\"\n" + //
|
||||||
|
" },\n" + //
|
||||||
|
" \"nestedObjectMap\": {\n" + //
|
||||||
|
" \"type\": \"nested\",\n" + //
|
||||||
|
" \"dynamic\": \"false\"\n" + //
|
||||||
|
" }\n" + //
|
||||||
|
" }\n" + //
|
||||||
|
"}"; //
|
||||||
|
|
||||||
String mapping = getMappingBuilder().buildPropertyMapping(ConfigureDynamicMappingEntity.class);
|
String mapping = getMappingBuilder().buildPropertyMapping(ConfigureDynamicMappingEntity.class);
|
||||||
|
|
||||||
assertEquals(expected, mapping, false);
|
assertEquals(expected, mapping, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test // DATAES-784
|
@Test // DATAES-784
|
||||||
@ -612,8 +632,7 @@ public class MappingBuilderUnitTests extends MappingContextBaseTests {
|
|||||||
@DisplayName("should map according to the annotated properties")
|
@DisplayName("should map according to the annotated properties")
|
||||||
void shouldMapAccordingToTheAnnotatedProperties() throws JSONException {
|
void shouldMapAccordingToTheAnnotatedProperties() throws JSONException {
|
||||||
|
|
||||||
String expected = "{\n" +
|
String expected = "{\n" + " \"properties\": {\n" + //
|
||||||
" \"properties\": {\n" + //
|
|
||||||
" \"field1\": {\n" + //
|
" \"field1\": {\n" + //
|
||||||
" \"type\": \"date\",\n" + //
|
" \"type\": \"date\",\n" + //
|
||||||
" \"format\": \"date_optional_time||epoch_millis\"\n" + //
|
" \"format\": \"date_optional_time||epoch_millis\"\n" + //
|
||||||
@ -666,7 +685,6 @@ public class MappingBuilderUnitTests extends MappingContextBaseTests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static class FieldNameEntity {
|
static class FieldNameEntity {
|
||||||
|
|
||||||
@Document(indexName = "fieldname-index")
|
@Document(indexName = "fieldname-index")
|
||||||
@ -1199,6 +1217,10 @@ public class MappingBuilderUnitTests extends MappingContextBaseTests {
|
|||||||
static class ConfigureDynamicMappingEntity {
|
static class ConfigureDynamicMappingEntity {
|
||||||
|
|
||||||
@Nullable @DynamicMapping(DynamicMappingValue.Strict) @Field(type = FieldType.Object) private Author author;
|
@Nullable @DynamicMapping(DynamicMappingValue.Strict) @Field(type = FieldType.Object) private Author author;
|
||||||
|
@Nullable @DynamicMapping(DynamicMappingValue.False) @Field(
|
||||||
|
type = FieldType.Object) private Map<String, Object> objectMap;
|
||||||
|
@Nullable @DynamicMapping(DynamicMappingValue.False) @Field(
|
||||||
|
type = FieldType.Nested) private List<Map<String, Object>> nestedObjectMap;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public Author getAuthor() {
|
public Author getAuthor() {
|
||||||
@ -1474,7 +1496,8 @@ public class MappingBuilderUnitTests extends MappingContextBaseTests {
|
|||||||
@Nullable @Id private String id;
|
@Nullable @Id private String id;
|
||||||
@Nullable @Field(type = FieldType.Date) private LocalDateTime field1;
|
@Nullable @Field(type = FieldType.Date) private LocalDateTime field1;
|
||||||
@Nullable @Field(type = FieldType.Date, format = DateFormat.basic_date) private LocalDateTime field2;
|
@Nullable @Field(type = FieldType.Date, format = DateFormat.basic_date) private LocalDateTime field2;
|
||||||
@Nullable @Field(type = FieldType.Date, format = { DateFormat.basic_date, DateFormat.basic_time }) private LocalDateTime field3;
|
@Nullable @Field(type = FieldType.Date,
|
||||||
|
format = { DateFormat.basic_date, DateFormat.basic_time }) private LocalDateTime field3;
|
||||||
@Nullable @Field(type = FieldType.Date, pattern = "dd.MM.uuuu") private LocalDateTime field4;
|
@Nullable @Field(type = FieldType.Date, pattern = "dd.MM.uuuu") private LocalDateTime field4;
|
||||||
@Nullable @Field(type = FieldType.Date, format = {}, pattern = "dd.MM.uuuu") private LocalDateTime field5;
|
@Nullable @Field(type = FieldType.Date, format = {}, pattern = "dd.MM.uuuu") private LocalDateTime field5;
|
||||||
|
|
||||||
|
@ -1593,20 +1593,35 @@ public abstract class CustomMethodRepositoryBaseTests {
|
|||||||
assertThat((nextPageable.getPageNumber())).isEqualTo(1);
|
assertThat((nextPageable.getPageNumber())).isEqualTo(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<SampleEntity> createSampleEntities(String type, int numberOfEntities) {
|
@Test // #1811
|
||||||
|
@DisplayName("should return SearchPage with query")
|
||||||
|
void shouldReturnSearchPageWithQuery() {
|
||||||
|
List<SampleEntity> entities = createSampleEntities("abc", 20);
|
||||||
|
repository.saveAll(entities);
|
||||||
|
|
||||||
List<SampleEntity> entities = new ArrayList<>();
|
SearchPage<SampleEntity> searchPage = repository.searchWithQueryByMessage("Message", PageRequest.of(0, 10));
|
||||||
for (int i = 0; i < numberOfEntities; i++) {
|
|
||||||
|
|
||||||
SampleEntity entity = new SampleEntity();
|
assertThat(searchPage).isNotNull();
|
||||||
entity.setId(UUID.randomUUID().toString());
|
SearchHits<SampleEntity> searchHits = searchPage.getSearchHits();
|
||||||
entity.setAvailable(true);
|
assertThat(searchHits).isNotNull();
|
||||||
entity.setMessage("Message");
|
assertThat((searchHits.getTotalHits())).isEqualTo(20);
|
||||||
entity.setType(type);
|
assertThat(searchHits.getSearchHits()).hasSize(10);
|
||||||
entities.add(entity);
|
Pageable nextPageable = searchPage.nextPageable();
|
||||||
|
assertThat((nextPageable.getPageNumber())).isEqualTo(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return entities;
|
@Test // #1917
|
||||||
|
@DisplayName("shouldReturnAllDocumentsWithUnpagedQuery")
|
||||||
|
void shouldReturnAllDocumentsWithUnpagedQuery() {
|
||||||
|
|
||||||
|
List<SampleEntity> entities = createSampleEntities("abc", 20);
|
||||||
|
repository.saveAll(entities);
|
||||||
|
|
||||||
|
SearchHits<SampleEntity> searchHits = repository.searchWithQueryByMessageUnpaged("Message");
|
||||||
|
|
||||||
|
assertThat(searchHits).isNotNull();
|
||||||
|
assertThat((searchHits.getTotalHits())).isEqualTo(20);
|
||||||
|
assertThat(searchHits.getSearchHits()).hasSize(20);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test // DATAES-891
|
@Test // DATAES-891
|
||||||
@ -1631,10 +1646,24 @@ public abstract class CustomMethodRepositoryBaseTests {
|
|||||||
assertThat(count).isEqualTo(20);
|
assertThat(count).isEqualTo(20);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<SampleEntity> createSampleEntities(String type, int numberOfEntities) {
|
||||||
|
|
||||||
|
List<SampleEntity> entities = new ArrayList<>();
|
||||||
|
for (int i = 0; i < numberOfEntities; i++) {
|
||||||
|
SampleEntity entity = new SampleEntity();
|
||||||
|
entity.setId(UUID.randomUUID().toString());
|
||||||
|
entity.setAvailable(true);
|
||||||
|
entity.setMessage("Message");
|
||||||
|
entity.setType(type);
|
||||||
|
entities.add(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
return entities;
|
||||||
|
}
|
||||||
|
|
||||||
@Document(indexName = "test-index-sample-repositories-custom-method")
|
@Document(indexName = "test-index-sample-repositories-custom-method")
|
||||||
static class SampleEntity {
|
static class SampleEntity {
|
||||||
@Nullable
|
@Nullable @Id private String id;
|
||||||
@Id private String id;
|
|
||||||
@Nullable @Field(type = Text, store = true, fielddata = true) private String type;
|
@Nullable @Field(type = Text, store = true, fielddata = true) private String type;
|
||||||
@Nullable @Field(type = Text, store = true, fielddata = true) private String message;
|
@Nullable @Field(type = Text, store = true, fielddata = true) private String message;
|
||||||
@Nullable @Field(type = Keyword) private String keyword;
|
@Nullable @Field(type = Keyword) private String keyword;
|
||||||
@ -1836,6 +1865,12 @@ public abstract class CustomMethodRepositoryBaseTests {
|
|||||||
|
|
||||||
SearchPage<SampleEntity> searchByMessage(String message, Pageable pageable);
|
SearchPage<SampleEntity> searchByMessage(String message, Pageable pageable);
|
||||||
|
|
||||||
|
@Query("{\"match\": {\"message\": \"?0\"}}")
|
||||||
|
SearchPage<SampleEntity> searchWithQueryByMessage(String message, Pageable pageable);
|
||||||
|
|
||||||
|
@Query("{\"match\": {\"message\": \"?0\"}}")
|
||||||
|
SearchHits<SampleEntity> searchWithQueryByMessageUnpaged(String message);
|
||||||
|
|
||||||
@CountQuery("{\"bool\" : {\"must\" : {\"term\" : {\"type\" : \"?0\"}}}}")
|
@CountQuery("{\"bool\" : {\"must\" : {\"term\" : {\"type\" : \"?0\"}}}}")
|
||||||
long countWithQueryByType(String type);
|
long countWithQueryByType(String type);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 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.repository.query;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import org.springframework.core.convert.converter.Converter;
|
||||||
|
import org.springframework.data.convert.CustomConversions;
|
||||||
|
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
||||||
|
import org.springframework.data.elasticsearch.core.convert.ElasticsearchCustomConversions;
|
||||||
|
import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter;
|
||||||
|
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Peter-Josef Meisch
|
||||||
|
*/
|
||||||
|
public class ElasticsearchStringQueryUnitTestBase {
|
||||||
|
|
||||||
|
protected ElasticsearchConverter setupConverter() {
|
||||||
|
MappingElasticsearchConverter converter = new MappingElasticsearchConverter(
|
||||||
|
new SimpleElasticsearchMappingContext());
|
||||||
|
Collection<Converter<?, ?>> converters = new ArrayList<>();
|
||||||
|
converters.add(ElasticsearchStringQueryUnitTests.CarConverter.INSTANCE);
|
||||||
|
CustomConversions customConversions = new ElasticsearchCustomConversions(converters);
|
||||||
|
converter.setConversions(customConversions);
|
||||||
|
converter.afterPropertiesSet();
|
||||||
|
return converter;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Car {
|
||||||
|
@Nullable private String name;
|
||||||
|
@Nullable private String model;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(@Nullable String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getModel() {
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setModel(@Nullable String model) {
|
||||||
|
this.model = model;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum CarConverter implements Converter<Car, String> {
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String convert(ElasticsearchStringQueryUnitTests.Car car) {
|
||||||
|
return (car.getName() != null ? car.getName() : "null") + '-'
|
||||||
|
+ (car.getModel() != null ? car.getModel() : "null");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -16,8 +16,10 @@
|
|||||||
package org.springframework.data.elasticsearch.repository.query;
|
package org.springframework.data.elasticsearch.repository.query;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.*;
|
import static org.assertj.core.api.Assertions.*;
|
||||||
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -25,6 +27,7 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
@ -37,9 +40,7 @@ import org.springframework.data.elasticsearch.annotations.InnerField;
|
|||||||
import org.springframework.data.elasticsearch.annotations.MultiField;
|
import org.springframework.data.elasticsearch.annotations.MultiField;
|
||||||
import org.springframework.data.elasticsearch.annotations.Query;
|
import org.springframework.data.elasticsearch.annotations.Query;
|
||||||
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
||||||
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
import org.springframework.data.elasticsearch.core.SearchHits;
|
||||||
import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter;
|
|
||||||
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
|
|
||||||
import org.springframework.data.elasticsearch.core.query.StringQuery;
|
import org.springframework.data.elasticsearch.core.query.StringQuery;
|
||||||
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
||||||
import org.springframework.data.repository.Repository;
|
import org.springframework.data.repository.Repository;
|
||||||
@ -49,16 +50,16 @@ import org.springframework.lang.Nullable;
|
|||||||
/**
|
/**
|
||||||
* @author Christoph Strobl
|
* @author Christoph Strobl
|
||||||
* @author Peter-Josef Meisch
|
* @author Peter-Josef Meisch
|
||||||
|
* @author Niklas Herder
|
||||||
*/
|
*/
|
||||||
@ExtendWith(MockitoExtension.class)
|
@ExtendWith(MockitoExtension.class)
|
||||||
public class ElasticsearchStringQueryUnitTests {
|
public class ElasticsearchStringQueryUnitTests extends ElasticsearchStringQueryUnitTestBase {
|
||||||
|
|
||||||
@Mock ElasticsearchOperations operations;
|
@Mock ElasticsearchOperations operations;
|
||||||
ElasticsearchConverter converter;
|
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
converter = new MappingElasticsearchConverter(new SimpleElasticsearchMappingContext());
|
when(operations.getElasticsearchConverter()).thenReturn(setupConverter());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test // DATAES-552
|
@Test // DATAES-552
|
||||||
@ -82,7 +83,53 @@ public class ElasticsearchStringQueryUnitTests {
|
|||||||
.isEqualTo("name:(zero, eleven, one, two, three, four, five, six, seven, eight, nine, ten, eleven, zero, one)");
|
.isEqualTo("name:(zero, eleven, one, two, three, four, five, six, seven, eight, nine, ten, eleven, zero, one)");
|
||||||
}
|
}
|
||||||
|
|
||||||
private org.springframework.data.elasticsearch.core.query.Query createQuery(String methodName, String... args)
|
@Test // #1790
|
||||||
|
@DisplayName("should escape Strings in query parameters")
|
||||||
|
void shouldEscapeStringsInQueryParameters() throws Exception {
|
||||||
|
|
||||||
|
org.springframework.data.elasticsearch.core.query.Query query = createQuery("findByPrefix", "hello \"Stranger\"");
|
||||||
|
|
||||||
|
assertThat(query).isInstanceOf(StringQuery.class);
|
||||||
|
assertThat(((StringQuery) query).getSource())
|
||||||
|
.isEqualTo("{\"bool\":{\"must\": [{\"match\": {\"prefix\": {\"name\" : \"hello \\\"Stranger\\\"\"}}]}}");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test // #1858
|
||||||
|
@DisplayName("should only quote String query parameters")
|
||||||
|
void shouldOnlyEscapeStringQueryParameters() throws Exception {
|
||||||
|
org.springframework.data.elasticsearch.core.query.Query query = createQuery("findByAge", Integer.valueOf(30));
|
||||||
|
|
||||||
|
assertThat(query).isInstanceOf(StringQuery.class);
|
||||||
|
assertThat(((StringQuery) query).getSource()).isEqualTo("{ 'bool' : { 'must' : { 'term' : { 'age' : 30 } } } }");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test // #1858
|
||||||
|
@DisplayName("should only quote String collection query parameters")
|
||||||
|
void shouldOnlyEscapeStringCollectionQueryParameters() throws Exception {
|
||||||
|
org.springframework.data.elasticsearch.core.query.Query query = createQuery("findByAgeIn",
|
||||||
|
new ArrayList<>(Arrays.asList(30, 35, 40)));
|
||||||
|
|
||||||
|
assertThat(query).isInstanceOf(StringQuery.class);
|
||||||
|
assertThat(((StringQuery) query).getSource())
|
||||||
|
.isEqualTo("{ 'bool' : { 'must' : { 'term' : { 'age' : [30,35,40] } } } }");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test // #1858
|
||||||
|
@DisplayName("should escape Strings in collection query parameters")
|
||||||
|
void shouldEscapeStringsInCollectionsQueryParameters() throws Exception {
|
||||||
|
|
||||||
|
final List<String> another_string = Arrays.asList("hello \"Stranger\"", "Another string");
|
||||||
|
List<String> params = new ArrayList<>(another_string);
|
||||||
|
org.springframework.data.elasticsearch.core.query.Query query = createQuery("findByNameIn", params);
|
||||||
|
|
||||||
|
assertThat(query).isInstanceOf(StringQuery.class);
|
||||||
|
assertThat(((StringQuery) query).getSource()).isEqualTo(
|
||||||
|
"{ 'bool' : { 'must' : { 'terms' : { 'name' : [\"hello \\\"Stranger\\\"\",\"Another string\"] } } } }");
|
||||||
|
}
|
||||||
|
|
||||||
|
private org.springframework.data.elasticsearch.core.query.Query createQuery(String methodName, Object... args)
|
||||||
throws NoSuchMethodException {
|
throws NoSuchMethodException {
|
||||||
|
|
||||||
Class<?>[] argTypes = Arrays.stream(args).map(Object::getClass).toArray(Class[]::new);
|
Class<?>[] argTypes = Arrays.stream(args).map(Object::getClass).toArray(Class[]::new);
|
||||||
@ -91,6 +138,21 @@ public class ElasticsearchStringQueryUnitTests {
|
|||||||
return elasticsearchStringQuery.createQuery(new ElasticsearchParametersParameterAccessor(queryMethod, args));
|
return elasticsearchStringQuery.createQuery(new ElasticsearchParametersParameterAccessor(queryMethod, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test // #1866
|
||||||
|
@DisplayName("should use converter on parameters")
|
||||||
|
void shouldUseConverterOnParameters() throws NoSuchMethodException {
|
||||||
|
|
||||||
|
Car car = new Car();
|
||||||
|
car.setName("Toyota");
|
||||||
|
car.setModel("Prius");
|
||||||
|
|
||||||
|
org.springframework.data.elasticsearch.core.query.Query query = createQuery("findByCar", car);
|
||||||
|
|
||||||
|
assertThat(query).isInstanceOf(StringQuery.class);
|
||||||
|
assertThat(((StringQuery) query).getSource())
|
||||||
|
.isEqualTo("{ 'bool' : { 'must' : { 'term' : { 'car' : 'Toyota-Prius' } } } }");
|
||||||
|
}
|
||||||
|
|
||||||
private ElasticsearchStringQuery queryForMethod(ElasticsearchQueryMethod queryMethod) {
|
private ElasticsearchStringQuery queryForMethod(ElasticsearchQueryMethod queryMethod) {
|
||||||
return new ElasticsearchStringQuery(queryMethod, operations, queryMethod.getAnnotatedQuery());
|
return new ElasticsearchStringQuery(queryMethod, operations, queryMethod.getAnnotatedQuery());
|
||||||
}
|
}
|
||||||
@ -99,33 +161,59 @@ public class ElasticsearchStringQueryUnitTests {
|
|||||||
|
|
||||||
Method method = SampleRepository.class.getMethod(name, parameters);
|
Method method = SampleRepository.class.getMethod(name, parameters);
|
||||||
return new ElasticsearchQueryMethod(method, new DefaultRepositoryMetadata(SampleRepository.class),
|
return new ElasticsearchQueryMethod(method, new DefaultRepositoryMetadata(SampleRepository.class),
|
||||||
new SpelAwareProxyProjectionFactory(), converter.getMappingContext());
|
new SpelAwareProxyProjectionFactory(), operations.getElasticsearchConverter().getMappingContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
private interface SampleRepository extends Repository<Person, String> {
|
private interface SampleRepository extends Repository<Person, String> {
|
||||||
|
|
||||||
|
@Query("{ 'bool' : { 'must' : { 'term' : { 'age' : ?0 } } } }")
|
||||||
|
List<Person> findByAge(Integer age);
|
||||||
|
|
||||||
|
@Query("{ 'bool' : { 'must' : { 'term' : { 'age' : ?0 } } } }")
|
||||||
|
List<Person> findByAgeIn(ArrayList<Integer> age);
|
||||||
|
|
||||||
@Query("{ 'bool' : { 'must' : { 'term' : { 'name' : '?0' } } } }")
|
@Query("{ 'bool' : { 'must' : { 'term' : { 'name' : '?0' } } } }")
|
||||||
Person findByName(String name);
|
Person findByName(String name);
|
||||||
|
|
||||||
|
@Query("{ 'bool' : { 'must' : { 'terms' : { 'name' : ?0 } } } }")
|
||||||
|
Person findByNameIn(ArrayList<String> names);
|
||||||
|
|
||||||
@Query(value = "name:(?0, ?11, ?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?0, ?1)")
|
@Query(value = "name:(?0, ?11, ?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?0, ?1)")
|
||||||
Person findWithRepeatedPlaceholder(String arg0, String arg1, String arg2, String arg3, String arg4, String arg5,
|
Person findWithRepeatedPlaceholder(String arg0, String arg1, String arg2, String arg3, String arg4, String arg5,
|
||||||
String arg6, String arg7, String arg8, String arg9, String arg10, String arg11);
|
String arg6, String arg7, String arg8, String arg9, String arg10, String arg11);
|
||||||
|
|
||||||
|
@Query("{\"bool\":{\"must\": [{\"match\": {\"prefix\": {\"name\" : \"?0\"}}]}}")
|
||||||
|
SearchHits<Book> findByPrefix(String prefix);
|
||||||
|
|
||||||
|
@Query("{ 'bool' : { 'must' : { 'term' : { 'car' : '?0' } } } }")
|
||||||
|
Person findByCar(Car car);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Rizwan Idrees
|
* @author Rizwan Idrees
|
||||||
* @author Mohsin Husen
|
* @author Mohsin Husen
|
||||||
* @author Artur Konczak
|
* @author Artur Konczak
|
||||||
|
* @author Niklas Herder
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Document(indexName = "test-index-person-query-unittest")
|
@Document(indexName = "test-index-person-query-unittest")
|
||||||
static class Person {
|
static class Person {
|
||||||
|
|
||||||
|
@Nullable public int age;
|
||||||
@Nullable @Id private String id;
|
@Nullable @Id private String id;
|
||||||
@Nullable private String name;
|
@Nullable private String name;
|
||||||
@Nullable @Field(type = FieldType.Nested) private List<Car> car;
|
@Nullable @Field(type = FieldType.Nested) private List<Car> car;
|
||||||
@Nullable @Field(type = FieldType.Nested, includeInParent = true) private List<Book> books;
|
@Nullable @Field(type = FieldType.Nested, includeInParent = true) private List<Book> books;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public int getAge() {
|
||||||
|
return age;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAge(int age) {
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
@ -219,29 +307,6 @@ public class ElasticsearchStringQueryUnitTests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class Car {
|
|
||||||
@Nullable private String name;
|
|
||||||
@Nullable private String model;
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setName(@Nullable String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public String getModel() {
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setModel(@Nullable String model) {
|
|
||||||
this.model = model;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class Author {
|
static class Author {
|
||||||
|
|
||||||
@Nullable private String id;
|
@Nullable private String id;
|
||||||
@ -265,5 +330,4 @@ public class ElasticsearchStringQueryUnitTests {
|
|||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
package org.springframework.data.elasticsearch.repository.query;
|
package org.springframework.data.elasticsearch.repository.query;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.*;
|
import static org.assertj.core.api.Assertions.*;
|
||||||
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
@ -29,6 +30,7 @@ import java.util.Map;
|
|||||||
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Disabled;
|
import org.junit.jupiter.api.Disabled;
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
@ -41,9 +43,7 @@ import org.springframework.data.elasticsearch.annotations.InnerField;
|
|||||||
import org.springframework.data.elasticsearch.annotations.MultiField;
|
import org.springframework.data.elasticsearch.annotations.MultiField;
|
||||||
import org.springframework.data.elasticsearch.annotations.Query;
|
import org.springframework.data.elasticsearch.annotations.Query;
|
||||||
import org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations;
|
import org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations;
|
||||||
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
import org.springframework.data.elasticsearch.core.SearchHit;
|
||||||
import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter;
|
|
||||||
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
|
|
||||||
import org.springframework.data.elasticsearch.core.query.StringQuery;
|
import org.springframework.data.elasticsearch.core.query.StringQuery;
|
||||||
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
||||||
import org.springframework.data.repository.Repository;
|
import org.springframework.data.repository.Repository;
|
||||||
@ -57,16 +57,15 @@ import org.springframework.lang.Nullable;
|
|||||||
* @author Peter-Josef Meisch
|
* @author Peter-Josef Meisch
|
||||||
*/
|
*/
|
||||||
@ExtendWith(MockitoExtension.class)
|
@ExtendWith(MockitoExtension.class)
|
||||||
public class ReactiveElasticsearchStringQueryUnitTests {
|
public class ReactiveElasticsearchStringQueryUnitTests extends ElasticsearchStringQueryUnitTestBase {
|
||||||
|
|
||||||
SpelExpressionParser PARSER = new SpelExpressionParser();
|
SpelExpressionParser PARSER = new SpelExpressionParser();
|
||||||
ElasticsearchConverter converter;
|
|
||||||
|
|
||||||
@Mock ReactiveElasticsearchOperations operations;
|
@Mock ReactiveElasticsearchOperations operations;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
converter = new MappingElasticsearchConverter(new SimpleElasticsearchMappingContext());
|
when(operations.getElasticsearchConverter()).thenReturn(setupConverter());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test // DATAES-519
|
@Test // DATAES-519
|
||||||
@ -119,7 +118,33 @@ public class ReactiveElasticsearchStringQueryUnitTests {
|
|||||||
.isEqualTo("name:(zero, eleven, one, two, three, four, five, six, seven, eight, nine, ten, eleven, zero, one)");
|
.isEqualTo("name:(zero, eleven, one, two, three, four, five, six, seven, eight, nine, ten, eleven, zero, one)");
|
||||||
}
|
}
|
||||||
|
|
||||||
private org.springframework.data.elasticsearch.core.query.Query createQuery(String methodName, String... args)
|
@Test // #1790
|
||||||
|
@DisplayName("should escape Strings in query parameters")
|
||||||
|
void shouldEscapeStringsInQueryParameters() throws Exception {
|
||||||
|
|
||||||
|
org.springframework.data.elasticsearch.core.query.Query query = createQuery("findByPrefix", "hello \"Stranger\"");
|
||||||
|
|
||||||
|
assertThat(query).isInstanceOf(StringQuery.class);
|
||||||
|
assertThat(((StringQuery) query).getSource())
|
||||||
|
.isEqualTo("{\"bool\":{\"must\": [{\"match\": {\"prefix\": {\"name\" : \"hello \\\"Stranger\\\"\"}}]}}");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test // #1866
|
||||||
|
@DisplayName("should use converter on parameters")
|
||||||
|
void shouldUseConverterOnParameters() throws Exception {
|
||||||
|
|
||||||
|
Car car = new Car();
|
||||||
|
car.setName("Toyota");
|
||||||
|
car.setModel("Prius");
|
||||||
|
|
||||||
|
org.springframework.data.elasticsearch.core.query.Query query = createQuery("findByCar", car);
|
||||||
|
|
||||||
|
assertThat(query).isInstanceOf(StringQuery.class);
|
||||||
|
assertThat(((StringQuery) query).getSource())
|
||||||
|
.isEqualTo("{ 'bool' : { 'must' : { 'term' : { 'car' : 'Toyota-Prius' } } } }");
|
||||||
|
}
|
||||||
|
|
||||||
|
private org.springframework.data.elasticsearch.core.query.Query createQuery(String methodName, Object... args)
|
||||||
throws NoSuchMethodException {
|
throws NoSuchMethodException {
|
||||||
|
|
||||||
Class<?>[] argTypes = Arrays.stream(args).map(Object::getClass).toArray(Class[]::new);
|
Class<?>[] argTypes = Arrays.stream(args).map(Object::getClass).toArray(Class[]::new);
|
||||||
@ -139,7 +164,7 @@ public class ReactiveElasticsearchStringQueryUnitTests {
|
|||||||
|
|
||||||
Method method = SampleRepository.class.getMethod(name, parameters);
|
Method method = SampleRepository.class.getMethod(name, parameters);
|
||||||
return new ReactiveElasticsearchQueryMethod(method, new DefaultRepositoryMetadata(SampleRepository.class),
|
return new ReactiveElasticsearchQueryMethod(method, new DefaultRepositoryMetadata(SampleRepository.class),
|
||||||
new SpelAwareProxyProjectionFactory(), converter.getMappingContext());
|
new SpelAwareProxyProjectionFactory(), operations.getElasticsearchConverter().getMappingContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
private ReactiveElasticsearchStringQuery createQueryForMethod(String name, Class<?>... parameters) throws Exception {
|
private ReactiveElasticsearchStringQuery createQueryForMethod(String name, Class<?>... parameters) throws Exception {
|
||||||
@ -163,6 +188,13 @@ public class ReactiveElasticsearchStringQueryUnitTests {
|
|||||||
@Query(value = "name:(?0, ?11, ?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?0, ?1)")
|
@Query(value = "name:(?0, ?11, ?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?0, ?1)")
|
||||||
Person findWithRepeatedPlaceholder(String arg0, String arg1, String arg2, String arg3, String arg4, String arg5,
|
Person findWithRepeatedPlaceholder(String arg0, String arg1, String arg2, String arg3, String arg4, String arg5,
|
||||||
String arg6, String arg7, String arg8, String arg9, String arg10, String arg11);
|
String arg6, String arg7, String arg8, String arg9, String arg10, String arg11);
|
||||||
|
|
||||||
|
@Query("{\"bool\":{\"must\": [{\"match\": {\"prefix\": {\"name\" : \"?0\"}}]}}")
|
||||||
|
Flux<SearchHit<Book>> findByPrefix(String prefix);
|
||||||
|
|
||||||
|
@Query("{ 'bool' : { 'must' : { 'term' : { 'car' : '?0' } } } }")
|
||||||
|
Mono<Person> findByCar(Car car);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -275,29 +307,6 @@ public class ReactiveElasticsearchStringQueryUnitTests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class Car {
|
|
||||||
@Nullable private String name;
|
|
||||||
@Nullable private String model;
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setName(@Nullable String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public String getModel() {
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setModel(@Nullable String model) {
|
|
||||||
this.model = model;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class Author {
|
static class Author {
|
||||||
|
|
||||||
@Nullable private String id;
|
@Nullable private String id;
|
||||||
|
@ -28,6 +28,7 @@ import java.lang.Long;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.IntStream;
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
import org.elasticsearch.ElasticsearchStatusException;
|
import org.elasticsearch.ElasticsearchStatusException;
|
||||||
@ -541,14 +542,36 @@ class SimpleReactiveElasticsearchRepositoryTests {
|
|||||||
@Test // DATAES-519
|
@Test // DATAES-519
|
||||||
void annotatedFinderMethodShouldBeExecutedCorrectly() {
|
void annotatedFinderMethodShouldBeExecutedCorrectly() {
|
||||||
|
|
||||||
bulkIndex(new SampleEntity("id-one", "message"), //
|
int count = 30;
|
||||||
new SampleEntity("id-two", "test message"), //
|
SampleEntity[] sampleEntities = IntStream.range(1, count + 1)
|
||||||
new SampleEntity("id-three", "test test")) //
|
.mapToObj(i -> new SampleEntity("id-" + i, "test " + i)).collect(Collectors.toList())
|
||||||
.block();
|
.toArray(new SampleEntity[count]);
|
||||||
|
|
||||||
|
bulkIndex(sampleEntities).block();
|
||||||
|
|
||||||
repository.findAllViaAnnotatedQueryByMessageLike("test") //
|
repository.findAllViaAnnotatedQueryByMessageLike("test") //
|
||||||
.as(StepVerifier::create) //
|
.as(StepVerifier::create) //
|
||||||
.expectNextCount(2) //
|
.expectNextCount(count) //
|
||||||
|
.verifyComplete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test // #1917
|
||||||
|
void annotatedFinderMethodPagedShouldBeExecutedCorrectly() {
|
||||||
|
|
||||||
|
int count = 30;
|
||||||
|
SampleEntity[] sampleEntities = IntStream.range(1, count + 1)
|
||||||
|
.mapToObj(i -> new SampleEntity("id-" + i, "test " + i)).collect(Collectors.toList())
|
||||||
|
.toArray(new SampleEntity[count]);
|
||||||
|
|
||||||
|
bulkIndex(sampleEntities).block();
|
||||||
|
|
||||||
|
repository.findAllViaAnnotatedQueryByMessageLikePaged("test", PageRequest.of(0, 20)) //
|
||||||
|
.as(StepVerifier::create) //
|
||||||
|
.expectNextCount(20) //
|
||||||
|
.verifyComplete();
|
||||||
|
repository.findAllViaAnnotatedQueryByMessageLikePaged("test", PageRequest.of(1, 20)) //
|
||||||
|
.as(StepVerifier::create) //
|
||||||
|
.expectNextCount(10) //
|
||||||
.verifyComplete();
|
.verifyComplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -596,6 +619,9 @@ class SimpleReactiveElasticsearchRepositoryTests {
|
|||||||
@Query("{ \"bool\" : { \"must\" : { \"term\" : { \"message\" : \"?0\" } } } }")
|
@Query("{ \"bool\" : { \"must\" : { \"term\" : { \"message\" : \"?0\" } } } }")
|
||||||
Flux<SampleEntity> findAllViaAnnotatedQueryByMessageLike(String message);
|
Flux<SampleEntity> findAllViaAnnotatedQueryByMessageLike(String message);
|
||||||
|
|
||||||
|
@Query("{ \"bool\" : { \"must\" : { \"term\" : { \"message\" : \"?0\" } } } }")
|
||||||
|
Flux<SampleEntity> findAllViaAnnotatedQueryByMessageLikePaged(String message, Pageable pageable);
|
||||||
|
|
||||||
Mono<SampleEntity> findFirstByMessageLike(String message);
|
Mono<SampleEntity> findFirstByMessageLike(String message);
|
||||||
|
|
||||||
Mono<Long> countAllByMessage(String message);
|
Mono<Long> countAllByMessage(String message);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user