Compare commits
76 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| be32581511 | |||
| 589924e87e | |||
| f4505c4778 | |||
| 9edae2725e | |||
| d4052c4951 | |||
| ce00928454 | |||
| 0f19400efe | |||
| c441503a56 | |||
| 7c364551db | |||
| 53a66c3f7c | |||
| 6cde9f9e78 | |||
| c03c790d46 | |||
| 41d91237d7 | |||
| fbcaeb10fd | |||
| 457a6e778e | |||
| 16f66e4c17 | |||
| bca4ba3fab | |||
| 88924903e8 | |||
| 7192d29095 | |||
| e0ca73b9b1 | |||
| 8285dd0cd0 | |||
| 6f73ac952b | |||
| 336b290e18 | |||
| e0286aa59a | |||
| 247be2b002 | |||
| e2ac3194b0 | |||
| 0c81b4b368 | |||
| 5fd35cb4c7 | |||
| af31cce875 | |||
| 23126ff3da | |||
| 0b3ecf6b23 | |||
| b96b5c2322 | |||
| 2a646e583d | |||
| 09c76b4694 | |||
| 1b59b31a72 | |||
| 2aba7a57fb | |||
| 15ca49a92e | |||
| b7088f8002 | |||
| 76f7ed5196 | |||
| e5445cf56f | |||
| 09a4e59e8d | |||
| 1e33e0f498 | |||
| e4df537382 | |||
| c1ab4d66e0 | |||
| 42cbab7ef6 | |||
| 9eed498fab | |||
| f16f70ff0f | |||
| 7494d344c5 | |||
| ca61901c1c | |||
| 323ccc9729 | |||
| 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 |
+117
@@ -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
Binary file not shown.
+3
-1
@@ -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
|
||||
#Tue Feb 22 13:55:13 CET 2022
|
||||
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.4/apache-maven-3.8.4-bin.zip
|
||||
|
||||
Vendored
+26
-48
@@ -1,3 +1,9 @@
|
||||
def p = [:]
|
||||
node {
|
||||
checkout scm
|
||||
p = readProperties interpolate: true, file: 'ci/pipeline.properties'
|
||||
}
|
||||
|
||||
pipeline {
|
||||
agent none
|
||||
|
||||
@@ -12,7 +18,7 @@ pipeline {
|
||||
}
|
||||
|
||||
stages {
|
||||
stage("test: baseline (jdk8)") {
|
||||
stage("test: baseline (main)") {
|
||||
when {
|
||||
anyOf {
|
||||
branch '4.2.x'
|
||||
@@ -25,14 +31,14 @@ pipeline {
|
||||
options { timeout(time: 30, unit: 'MINUTES') }
|
||||
|
||||
environment {
|
||||
DOCKER_HUB = credentials('hub.docker.com-springbuildmaster')
|
||||
ARTIFACTORY = credentials('02bd1690-b54f-4c9f-819d-a77cb7a9822c')
|
||||
DOCKER_HUB = credentials("${p['docker.credentials']}")
|
||||
ARTIFACTORY = credentials("${p['artifactory.credentials']}")
|
||||
}
|
||||
|
||||
steps {
|
||||
script {
|
||||
docker.withRegistry('', 'hub.docker.com-springbuildmaster') {
|
||||
docker.image('adoptopenjdk/openjdk8:latest').inside('-u root -v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker -v $HOME:/tmp/jenkins-home') {
|
||||
docker.withRegistry(p['docker.registry'], p['docker.credentials']) {
|
||||
docker.image(p['docker.java.main.image']).inside(p['docker.java.inside.docker']) {
|
||||
sh "docker login --username ${DOCKER_HUB_USR} --password ${DOCKER_HUB_PSW}"
|
||||
sh 'PROFILE=none ci/verify.sh'
|
||||
sh "ci/clean.sh"
|
||||
@@ -50,23 +56,23 @@ pipeline {
|
||||
}
|
||||
}
|
||||
parallel {
|
||||
stage("test: baseline (jdk11)") {
|
||||
stage("test: baseline (next)") {
|
||||
agent {
|
||||
label 'data'
|
||||
}
|
||||
options { timeout(time: 30, unit: 'MINUTES') }
|
||||
|
||||
environment {
|
||||
DOCKER_HUB = credentials('hub.docker.com-springbuildmaster')
|
||||
ARTIFACTORY = credentials('02bd1690-b54f-4c9f-819d-a77cb7a9822c')
|
||||
DOCKER_HUB = credentials("${p['docker.credentials']}")
|
||||
ARTIFACTORY = credentials("${p['artifactory.credentials']}")
|
||||
}
|
||||
|
||||
steps {
|
||||
script {
|
||||
docker.withRegistry('', 'hub.docker.com-springbuildmaster') {
|
||||
docker.image('adoptopenjdk/openjdk11:latest').inside('-u root -v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker -v $HOME:/tmp/jenkins-home') {
|
||||
docker.withRegistry(p['docker.registry'], p['docker.credentials']) {
|
||||
docker.image(p['docker.java.11.image']).inside(p['docker.java.inside.docker']) {
|
||||
sh "docker login --username ${DOCKER_HUB_USR} --password ${DOCKER_HUB_PSW}"
|
||||
sh 'PROFILE=java11 ci/verify.sh'
|
||||
sh 'PROFILE=none ci/verify.sh'
|
||||
sh "ci/clean.sh"
|
||||
}
|
||||
}
|
||||
@@ -74,23 +80,23 @@ pipeline {
|
||||
}
|
||||
}
|
||||
|
||||
stage("test: baseline (jdk16)") {
|
||||
stage("test: baseline (LTS)") {
|
||||
agent {
|
||||
label 'data'
|
||||
}
|
||||
options { timeout(time: 30, unit: 'MINUTES') }
|
||||
|
||||
environment {
|
||||
DOCKER_HUB = credentials('hub.docker.com-springbuildmaster')
|
||||
ARTIFACTORY = credentials('02bd1690-b54f-4c9f-819d-a77cb7a9822c')
|
||||
DOCKER_HUB = credentials("${p['docker.credentials']}")
|
||||
ARTIFACTORY = credentials("${p['artifactory.credentials']}")
|
||||
}
|
||||
|
||||
steps {
|
||||
script {
|
||||
docker.withRegistry('', 'hub.docker.com-springbuildmaster') {
|
||||
docker.image('adoptopenjdk/openjdk16:latest').inside('-u root -v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker -v $HOME:/tmp/jenkins-home') {
|
||||
docker.withRegistry(p['docker.registry'], p['docker.credentials']) {
|
||||
docker.image(p['docker.java.lts.image']).inside(p['docker.java.inside.docker']) {
|
||||
sh "docker login --username ${DOCKER_HUB_USR} --password ${DOCKER_HUB_PSW}"
|
||||
sh 'PROFILE=java11 ci/verify.sh'
|
||||
sh 'PROFILE=none ci/verify.sh'
|
||||
sh "ci/clean.sh"
|
||||
}
|
||||
}
|
||||
@@ -113,13 +119,13 @@ pipeline {
|
||||
options { timeout(time: 20, unit: 'MINUTES') }
|
||||
|
||||
environment {
|
||||
ARTIFACTORY = credentials('02bd1690-b54f-4c9f-819d-a77cb7a9822c')
|
||||
ARTIFACTORY = credentials("${p['artifactory.credentials']}")
|
||||
}
|
||||
|
||||
steps {
|
||||
script {
|
||||
docker.withRegistry('', 'hub.docker.com-springbuildmaster') {
|
||||
docker.image('adoptopenjdk/openjdk8:latest').inside('-v $HOME:/tmp/jenkins-home') {
|
||||
docker.withRegistry(p['docker.registry'], p['docker.credentials']) {
|
||||
docker.image(p['docker.java.main.image']).inside(p['docker.java.inside.basic']) {
|
||||
sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -s settings.xml -Pci,artifactory -Dmaven.repo.local=/tmp/jenkins-home/.m2/spring-data-elasticsearch-non-root ' +
|
||||
'-Dartifactory.server=https://repo.spring.io ' +
|
||||
"-Dartifactory.username=${ARTIFACTORY_USR} " +
|
||||
@@ -133,34 +139,6 @@ pipeline {
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Publish documentation') {
|
||||
when {
|
||||
branch '4.2.x'
|
||||
}
|
||||
agent {
|
||||
label 'data'
|
||||
}
|
||||
options { timeout(time: 20, unit: 'MINUTES') }
|
||||
|
||||
environment {
|
||||
ARTIFACTORY = credentials('02bd1690-b54f-4c9f-819d-a77cb7a9822c')
|
||||
}
|
||||
|
||||
steps {
|
||||
script {
|
||||
docker.withRegistry('', 'hub.docker.com-springbuildmaster') {
|
||||
docker.image('adoptopenjdk/openjdk8:latest').inside('-v $HOME:/tmp/jenkins-home') {
|
||||
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.username=${ARTIFACTORY_USR} " +
|
||||
"-Dartifactory.password=${ARTIFACTORY_PSW} " +
|
||||
"-Dartifactory.distribution-repository=temp-private-local " +
|
||||
'-Dmaven.test.skip=true clean deploy -U -B'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
post {
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
# Java versions
|
||||
java.main.tag=8u332-b09-jdk
|
||||
java.11.tag=11.0.15_10-jdk
|
||||
java.15.tag=15.0.2_7-jdk-hotspot
|
||||
java.lts.tag=17.0.3_7-jdk
|
||||
|
||||
# Docker container images - standard
|
||||
docker.java.main.image=harbor-repo.vmware.com/dockerhub-proxy-cache/library/eclipse-temurin:${java.main.tag}
|
||||
docker.java.11.image=harbor-repo.vmware.com/dockerhub-proxy-cache/library/eclipse-temurin:${java.11.tag}
|
||||
docker.java.15.image=harbor-repo.vmware.com/dockerhub-proxy-cache/library/adoptopenjdk:${java.15.tag}
|
||||
docker.java.lts.image=harbor-repo.vmware.com/dockerhub-proxy-cache/library/eclipse-temurin:${java.lts.tag}
|
||||
|
||||
# Supported versions of MongoDB
|
||||
docker.mongodb.4.0.version=4.0.28
|
||||
docker.mongodb.4.4.version=4.4.12
|
||||
docker.mongodb.5.0.version=5.0.6
|
||||
|
||||
# Supported versions of Redis
|
||||
docker.redis.6.version=6.2.6
|
||||
|
||||
# Supported versions of Cassandra
|
||||
docker.cassandra.3.version=3.11.12
|
||||
|
||||
# Docker environment settings
|
||||
docker.java.inside.basic=-v $HOME:/tmp/jenkins-home
|
||||
docker.java.inside.docker=-u root -v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker -v $HOME:/tmp/jenkins-home
|
||||
|
||||
# Credentials
|
||||
docker.registry=
|
||||
docker.credentials=hub.docker.com-springbuildmaster
|
||||
artifactory.credentials=02bd1690-b54f-4c9f-819d-a77cb7a9822c
|
||||
@@ -8,7 +8,7 @@
|
||||
# "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
|
||||
# http://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
|
||||
@@ -19,7 +19,7 @@
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Maven2 Start Up Batch script
|
||||
# Maven Start Up Batch script
|
||||
#
|
||||
# Required ENV vars:
|
||||
# ------------------
|
||||
@@ -114,7 +114,6 @@ if $mingw ; then
|
||||
M2_HOME="`(cd "$M2_HOME"; pwd)`"
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
|
||||
# TODO classpath?
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
@@ -212,7 +211,11 @@ else
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
|
||||
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
|
||||
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
|
||||
esac
|
||||
@@ -221,22 +224,38 @@ else
|
||||
echo "Downloading from: $jarUrl"
|
||||
fi
|
||||
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 [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Found wget ... using wget"
|
||||
fi
|
||||
wget "$jarUrl" -O "$wrapperJarPath"
|
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||
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
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Found curl ... using curl"
|
||||
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
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Falling back to using Java to download"
|
||||
fi
|
||||
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 "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
@@ -277,6 +296,11 @@ if $cygwin; then
|
||||
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
|
||||
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
|
||||
|
||||
exec "$JAVACMD" \
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
@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
|
||||
@REM https://www.apache.org/licenses/LICENSE-2.0
|
||||
@REM http://www.apache.org/licenses/LICENSE-2.0
|
||||
@REM
|
||||
@REM Unless required by applicable law or agreed to in writing,
|
||||
@REM software distributed under the License is distributed on an
|
||||
@@ -18,7 +18,7 @@
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Maven2 Start Up Batch script
|
||||
@REM Maven Start Up Batch script
|
||||
@REM
|
||||
@REM Required ENV vars:
|
||||
@REM JAVA_HOME - location of a JDK home dir
|
||||
@@ -26,7 +26,7 @@
|
||||
@REM Optional ENV vars
|
||||
@REM M2_HOME - location of maven2's installed home dir
|
||||
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
|
||||
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
|
||||
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
|
||||
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
@REM e.g. to debug Maven itself, use
|
||||
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
@@ -37,7 +37,7 @@
|
||||
@echo off
|
||||
@REM set title of command window
|
||||
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%
|
||||
|
||||
@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_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"
|
||||
FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO (
|
||||
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
|
||||
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 (
|
||||
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
|
||||
)
|
||||
|
||||
@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.
|
||||
if exist %WRAPPER_JAR% (
|
||||
echo Found %WRAPPER_JAR%
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Found %WRAPPER_JAR%
|
||||
)
|
||||
) else (
|
||||
echo Couldn't find %WRAPPER_JAR%, downloading it ...
|
||||
echo Downloading from: %DOWNLOAD_URL%
|
||||
powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"
|
||||
echo Finished downloading %WRAPPER_JAR%
|
||||
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 Downloading from: %DOWNLOAD_URL%
|
||||
)
|
||||
|
||||
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%
|
||||
)
|
||||
)
|
||||
@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% %*
|
||||
if ERRORLEVEL 1 goto error
|
||||
goto end
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-elasticsearch</artifactId>
|
||||
<version>4.2.2</version>
|
||||
<version>4.2.13-SNAPSHOT</version>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.data.build</groupId>
|
||||
<artifactId>spring-data-parent</artifactId>
|
||||
<version>2.5.2</version>
|
||||
<version>2.5.13-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<name>Spring Data Elasticsearch</name>
|
||||
@@ -20,9 +20,9 @@
|
||||
<properties>
|
||||
<commonslang>2.6</commonslang>
|
||||
<elasticsearch>7.12.1</elasticsearch>
|
||||
<log4j>2.13.3</log4j>
|
||||
<log4j>2.17.0</log4j>
|
||||
<netty>4.1.52.Final</netty>
|
||||
<springdata.commons>2.5.2</springdata.commons>
|
||||
<springdata.commons>2.5.13-SNAPSHOT</springdata.commons>
|
||||
<testcontainers>1.15.1</testcontainers>
|
||||
<java-module-name>spring.data.elasticsearch</java-module-name>
|
||||
</properties>
|
||||
@@ -152,6 +152,12 @@
|
||||
<groupId>org.elasticsearch.client</groupId>
|
||||
<artifactId>transport</artifactId>
|
||||
<version>${elasticsearch}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -159,6 +165,12 @@
|
||||
<groupId>org.elasticsearch.plugin</groupId>
|
||||
<artifactId>transport-netty4-client</artifactId>
|
||||
<version>${elasticsearch}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -272,24 +284,24 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!--
|
||||
<dependency>
|
||||
<groupId>org.apache.openwebbeans.test</groupId>
|
||||
<artifactId>cditest-owb</artifactId>
|
||||
<version>1.2.8</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.apache.geronimo.specs</groupId>
|
||||
<artifactId>geronimo-jcdi_1.0_spec</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.apache.geronimo.specs</groupId>
|
||||
<artifactId>geronimo-atinject_1.0_spec</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
-->
|
||||
<!--
|
||||
<dependency>
|
||||
<groupId>org.apache.openwebbeans.test</groupId>
|
||||
<artifactId>cditest-owb</artifactId>
|
||||
<version>1.2.8</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.apache.geronimo.specs</groupId>
|
||||
<artifactId>geronimo-jcdi_1.0_spec</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.apache.geronimo.specs</groupId>
|
||||
<artifactId>geronimo-atinject_1.0_spec</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
-->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.skyscreamer</groupId>
|
||||
@@ -467,7 +479,9 @@
|
||||
</module>
|
||||
</checkstyleRules>
|
||||
<includes>**/*</includes>
|
||||
<excludes>.git/**/*,target/**/*,**/target/**/*,.idea/**/*,**/spring.schemas,**/*.svg,mvnw,mvnw.cmd,**/*.policy</excludes>
|
||||
<excludes>
|
||||
.git/**/*,target/**/*,**/target/**/*,.idea/**/*,**/spring.schemas,**/*.svg,mvnw,mvnw.cmd,**/*.policy
|
||||
</excludes>
|
||||
<sourceDirectories>./</sourceDirectories>
|
||||
</configuration>
|
||||
</plugin>
|
||||
@@ -480,8 +494,8 @@
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-libs-release</id>
|
||||
<url>https://repo.spring.io/libs-release</url>
|
||||
<id>spring-libs-snapshot</id>
|
||||
<url>https://repo.spring.io/libs-snapshot</url>
|
||||
</repository>
|
||||
|
||||
<repository>
|
||||
|
||||
@@ -190,6 +190,29 @@ ClientConfiguration clientConfiguration = ClientConfiguration.builder()
|
||||
|
||||
IMPORTANT: Adding a Header supplier as shown in above example allows to inject headers that may change over the time, like authentication JWT tokens. If this is used in the reactive setup, the supplier function *must not* block!
|
||||
|
||||
=== Elasticsearch 7 compatibility headers
|
||||
|
||||
When using Spring Data Elasticsearch 4 - which uses the Elasticsearch 7 client libraries - and accessing an Elasticsearch cluster that is running on version 8, it is necessary to set the compatibility headers
|
||||
https://www.elastic.co/guide/en/elasticsearch/reference/8.0/rest-api-compatibility.html[see Elasticserach documentation].
|
||||
This should be done using a header supplier like shown above:
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
ClientConfigurationBuilder configurationBuilder = new ClientConfigurationBuilder();
|
||||
configurationBuilder //
|
||||
// ...
|
||||
.withHeaders(() -> {
|
||||
HttpHeaders defaultCompatibilityHeaders = new HttpHeaders();
|
||||
defaultCompatibilityHeaders.add("Accept",
|
||||
"application/vnd.elasticsearch+json;compatible-with=7");
|
||||
defaultCompatibilityHeaders.add("Content-Type",
|
||||
"application/vnd.elasticsearch+json;compatible-with=7");
|
||||
return defaultCompatibilityHeaders;
|
||||
});
|
||||
----
|
||||
====
|
||||
|
||||
[[elasticsearch.clients.logging]]
|
||||
== Client Logging
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ public @interface Document {
|
||||
* Name of the Elasticsearch index.
|
||||
* <ul>
|
||||
* <li>Lowercase only</li>
|
||||
* <li><Cannot include \, /, *, ?, ", <, >, |, ` ` (space character), ,, #/li>
|
||||
* <li>Cannot include \, /, *, ?, ", >, <, |, ` ` (space character), ,, #</li>
|
||||
* <li>Cannot start with -, _, +</li>
|
||||
* <li>Cannot be . or ..</li>
|
||||
* <li>Cannot be longer than 255 bytes (note it is bytes, so multi-byte characters will count towards the 255 limit
|
||||
|
||||
+12
-2
@@ -17,10 +17,20 @@ package org.springframework.data.elasticsearch.annotations;
|
||||
|
||||
/**
|
||||
* values for the {@link DynamicMapping annotation}
|
||||
*
|
||||
*
|
||||
* @author Peter-Josef Meisch
|
||||
* @since 4.0
|
||||
*/
|
||||
public enum DynamicMappingValue {
|
||||
True, False, Strict
|
||||
True("true"), False("false"), Strict("strict");
|
||||
|
||||
private final String mappedName;
|
||||
|
||||
DynamicMappingValue(String mappedName) {
|
||||
this.mappedName = mappedName;
|
||||
}
|
||||
|
||||
public String getMappedName() {
|
||||
return mappedName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,40 +26,51 @@ package org.springframework.data.elasticsearch.annotations;
|
||||
* @author Morgan Lutz
|
||||
*/
|
||||
public enum FieldType {
|
||||
Auto, //
|
||||
Text, //
|
||||
Keyword, //
|
||||
Long, //
|
||||
Integer, //
|
||||
Short, //
|
||||
Byte, //
|
||||
Double, //
|
||||
Float, //
|
||||
Half_Float, //
|
||||
Scaled_Float, //
|
||||
Date, //
|
||||
Date_Nanos, //
|
||||
Boolean, //
|
||||
Binary, //
|
||||
Integer_Range, //
|
||||
Float_Range, //
|
||||
Long_Range, //
|
||||
Double_Range, //
|
||||
Date_Range, //
|
||||
Ip_Range, //
|
||||
Object, //
|
||||
Nested, //
|
||||
Ip, //
|
||||
TokenCount, //
|
||||
Percolator, //
|
||||
Flattened, //
|
||||
Search_As_You_Type, //
|
||||
Auto("auto"), //
|
||||
Text("text"), //
|
||||
Keyword("keyword"), //
|
||||
Long("long"), //
|
||||
Integer("integer"), //
|
||||
Short("short"), //
|
||||
Byte("byte"), //
|
||||
Double("double"), //
|
||||
Float("float"), //
|
||||
Half_Float("half_float"), //
|
||||
Scaled_Float("scaled_float"), //
|
||||
Date("date"), //
|
||||
Date_Nanos("date_nanos"), //
|
||||
Boolean("boolean"), //
|
||||
Binary("binary"), //
|
||||
Integer_Range("integer_range"), //
|
||||
Float_Range("float_range"), //
|
||||
Long_Range("long_range"), //
|
||||
Double_Range("double_range"), //
|
||||
Date_Range("date_range"), //
|
||||
Ip_Range("ip_range"), //
|
||||
Object("object"), //
|
||||
Nested("nested"), //
|
||||
Ip("ip"), //
|
||||
TokenCount("token_count"), //
|
||||
Percolator("percolator"), //
|
||||
Flattened("flattened"), //
|
||||
Search_As_You_Type("search_as_you_type"), //
|
||||
/** @since 4.1 */
|
||||
Rank_Feature, //
|
||||
Rank_Feature("rank_feature"), //
|
||||
/** @since 4.1 */
|
||||
Rank_Features, //
|
||||
Rank_Features("rank_features"), //
|
||||
/** since 4.2 */
|
||||
Wildcard, //
|
||||
Wildcard("wildcard"), //
|
||||
/** @since 4.2 */
|
||||
Dense_Vector //
|
||||
Dense_Vector("dense_vector") //
|
||||
;
|
||||
|
||||
private final String mappedName;
|
||||
|
||||
FieldType(String mappedName) {
|
||||
this.mappedName = mappedName;
|
||||
}
|
||||
|
||||
public String getMappedName() {
|
||||
return mappedName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ import org.springframework.util.Assert;
|
||||
* @author Huw Ayling-Miller
|
||||
* @author Henrique Amaral
|
||||
* @author Peter-Josef Meisch
|
||||
* @author Nic Hines
|
||||
* @since 3.2
|
||||
*/
|
||||
public final class RestClients {
|
||||
@@ -104,15 +105,14 @@ public final class RestClients {
|
||||
Duration connectTimeout = clientConfiguration.getConnectTimeout();
|
||||
|
||||
if (!connectTimeout.isNegative()) {
|
||||
|
||||
requestConfigBuilder.setConnectTimeout(Math.toIntExact(connectTimeout.toMillis()));
|
||||
requestConfigBuilder.setConnectionRequestTimeout(Math.toIntExact(connectTimeout.toMillis()));
|
||||
}
|
||||
|
||||
Duration timeout = clientConfiguration.getSocketTimeout();
|
||||
Duration socketTimeout = clientConfiguration.getSocketTimeout();
|
||||
|
||||
if (!timeout.isNegative()) {
|
||||
requestConfigBuilder.setSocketTimeout(Math.toIntExact(timeout.toMillis()));
|
||||
if (!socketTimeout.isNegative()) {
|
||||
requestConfigBuilder.setSocketTimeout(Math.toIntExact(socketTimeout.toMillis()));
|
||||
requestConfigBuilder.setConnectionRequestTimeout(Math.toIntExact(socketTimeout.toMillis()));
|
||||
}
|
||||
|
||||
clientBuilder.setDefaultRequestConfig(requestConfigBuilder.build());
|
||||
|
||||
+2
-1
@@ -1452,7 +1452,8 @@ public class RequestConverters {
|
||||
// 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
|
||||
// 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
|
||||
return uri.getRawPath().substring(1).replaceAll("/", "%2F");
|
||||
} catch (URISyntaxException e) {
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ import org.springframework.data.mapping.context.PersistentEntities;
|
||||
* @author Peter-Josef Meisch
|
||||
* @since 4.1
|
||||
*/
|
||||
class PersistentEntitiesFactoryBean implements FactoryBean<PersistentEntities> {
|
||||
public class PersistentEntitiesFactoryBean implements FactoryBean<PersistentEntities> {
|
||||
|
||||
private final MappingElasticsearchConverter converter;
|
||||
|
||||
|
||||
+3
@@ -79,6 +79,8 @@ import org.springframework.util.Assert;
|
||||
* @author Peter-Josef Meisch
|
||||
* @author Roman Puchkovskiy
|
||||
* @author Subhobrata Dey
|
||||
* @author Steven Pearce
|
||||
* @author Anton Naydenov
|
||||
*/
|
||||
public abstract class AbstractElasticsearchTemplate implements ElasticsearchOperations, ApplicationContextAware {
|
||||
|
||||
@@ -116,6 +118,7 @@ public abstract class AbstractElasticsearchTemplate implements ElasticsearchOper
|
||||
}
|
||||
|
||||
copy.setRoutingResolver(routingResolver);
|
||||
copy.setRefreshPolicy(refreshPolicy);
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
-4
@@ -124,7 +124,6 @@ public interface ReactiveSearchOperations {
|
||||
/**
|
||||
* Search the index for entities matching the given {@link Query query}.
|
||||
*
|
||||
* @param <T>
|
||||
* @param query must not be {@literal null}.
|
||||
* @param entityType must not be {@literal null}.
|
||||
* @param <T>
|
||||
@@ -138,7 +137,6 @@ public interface ReactiveSearchOperations {
|
||||
/**
|
||||
* Search the index for entities matching the given {@link Query query}.
|
||||
*
|
||||
* @param <T>
|
||||
* @param query must not be {@literal null}.
|
||||
* @param entityType must not be {@literal null}.
|
||||
* @param resultType the projection result type.
|
||||
@@ -151,7 +149,6 @@ public interface ReactiveSearchOperations {
|
||||
/**
|
||||
* Search the index for entities matching the given {@link Query query}.
|
||||
*
|
||||
* @param <T>
|
||||
* @param query must not be {@literal null}.
|
||||
* @param entityType must not be {@literal null}.
|
||||
* @param index the target index, must not be {@literal null}
|
||||
@@ -166,7 +163,6 @@ public interface ReactiveSearchOperations {
|
||||
/**
|
||||
* Search the index for entities matching the given {@link Query query}.
|
||||
*
|
||||
* @param <T>
|
||||
* @param query must not be {@literal null}.
|
||||
* @param entityType must not be {@literal null}.
|
||||
* @param resultType the projection result type.
|
||||
|
||||
@@ -760,15 +760,17 @@ class RequestFactory {
|
||||
String indexName = index.getIndexName();
|
||||
IndexRequest indexRequest;
|
||||
|
||||
if (query.getObject() != null) {
|
||||
String id = StringUtils.isEmpty(query.getId()) ? getPersistentEntityId(query.getObject()) : query.getId();
|
||||
Object queryObject = query.getObject();
|
||||
|
||||
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 (id != null) {
|
||||
indexRequest = new IndexRequest(indexName).id(id);
|
||||
} else {
|
||||
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) {
|
||||
indexRequest = new IndexRequest(indexName).id(query.getId()).source(query.getSource(),
|
||||
Requests.INDEX_CONTENT_TYPE);
|
||||
@@ -779,7 +781,8 @@ class RequestFactory {
|
||||
|
||||
if (query.getVersion() != null) {
|
||||
indexRequest.version(query.getVersion());
|
||||
VersionType versionType = retrieveVersionTypeFromPersistentEntity(query.getObject().getClass());
|
||||
VersionType versionType = retrieveVersionTypeFromPersistentEntity(
|
||||
queryObject != null ? queryObject.getClass() : null);
|
||||
indexRequest.versionType(versionType);
|
||||
}
|
||||
|
||||
@@ -814,15 +817,16 @@ class RequestFactory {
|
||||
|
||||
IndexRequestBuilder indexRequestBuilder;
|
||||
|
||||
if (query.getObject() != null) {
|
||||
String id = StringUtils.isEmpty(query.getId()) ? getPersistentEntityId(query.getObject()) : query.getId();
|
||||
Object queryObject = query.getObject();
|
||||
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 (id != null) {
|
||||
indexRequestBuilder = client.prepareIndex(indexName, type, id);
|
||||
} else {
|
||||
indexRequestBuilder = client.prepareIndex(indexName, type);
|
||||
}
|
||||
indexRequestBuilder.setSource(elasticsearchConverter.mapObject(query.getObject()).toJson(),
|
||||
indexRequestBuilder.setSource(elasticsearchConverter.mapObject(queryObject).toJson(),
|
||||
Requests.INDEX_CONTENT_TYPE);
|
||||
} else if (query.getSource() != null) {
|
||||
indexRequestBuilder = client.prepareIndex(indexName, type, query.getId()).setSource(query.getSource(),
|
||||
@@ -834,7 +838,8 @@ class RequestFactory {
|
||||
|
||||
if (query.getVersion() != null) {
|
||||
indexRequestBuilder.setVersion(query.getVersion());
|
||||
VersionType versionType = retrieveVersionTypeFromPersistentEntity(query.getObject().getClass());
|
||||
VersionType versionType = retrieveVersionTypeFromPersistentEntity(
|
||||
queryObject != null ? queryObject.getClass() : null);
|
||||
indexRequestBuilder.setVersionType(versionType);
|
||||
}
|
||||
|
||||
@@ -1061,6 +1066,10 @@ class RequestFactory {
|
||||
|
||||
query.getRescorerQueries().forEach(rescorer -> sourceBuilder.addRescorer(getQueryRescorerBuilder(rescorer)));
|
||||
|
||||
if (query.getScrollTime() != null) {
|
||||
request.scroll(TimeValue.timeValueMillis(query.getScrollTime().toMillis()));
|
||||
}
|
||||
|
||||
request.source(sourceBuilder);
|
||||
return request;
|
||||
}
|
||||
@@ -1149,6 +1158,10 @@ class RequestFactory {
|
||||
|
||||
query.getRescorerQueries().forEach(rescorer -> searchRequestBuilder.addRescorer(getQueryRescorerBuilder(rescorer)));
|
||||
|
||||
if (query.getScrollTime() != null) {
|
||||
searchRequestBuilder.setScroll(TimeValue.timeValueMillis(query.getScrollTime().toMillis()));
|
||||
}
|
||||
|
||||
return searchRequestBuilder;
|
||||
}
|
||||
|
||||
@@ -1695,12 +1708,13 @@ class RequestFactory {
|
||||
return null;
|
||||
}
|
||||
|
||||
private VersionType retrieveVersionTypeFromPersistentEntity(Class<?> clazz) {
|
||||
private VersionType retrieveVersionTypeFromPersistentEntity(@Nullable Class<?> clazz) {
|
||||
|
||||
MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext = elasticsearchConverter
|
||||
.getMappingContext();
|
||||
|
||||
ElasticsearchPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(clazz);
|
||||
ElasticsearchPersistentEntity<?> persistentEntity = clazz != null ? mappingContext.getPersistentEntity(clazz)
|
||||
: null;
|
||||
|
||||
VersionType versionType = null;
|
||||
|
||||
|
||||
@@ -23,8 +23,7 @@ import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.elasticsearch.search.aggregations.Aggregations;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.elasticsearch.UncategorizedElasticsearchException;
|
||||
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
||||
import org.springframework.data.elasticsearch.core.document.Document;
|
||||
import org.springframework.data.elasticsearch.core.document.NestedMetaData;
|
||||
@@ -44,12 +43,11 @@ import org.springframework.util.Assert;
|
||||
* @author Mark Paluch
|
||||
* @author Roman Puchkovskiy
|
||||
* @author Matt Gilene
|
||||
* @author Sascha Woo
|
||||
* @since 4.0
|
||||
*/
|
||||
class SearchHitMapping<T> {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(SearchHitMapping.class);
|
||||
|
||||
private final Class<T> type;
|
||||
private final ElasticsearchConverter converter;
|
||||
private final MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext;
|
||||
@@ -173,7 +171,7 @@ class SearchHitMapping<T> {
|
||||
*/
|
||||
private SearchHits<?> mapInnerDocuments(SearchHits<SearchDocument> searchHits, Class<T> type) {
|
||||
|
||||
if (searchHits.getTotalHits() == 0) {
|
||||
if (searchHits.isEmpty()) {
|
||||
return searchHits;
|
||||
}
|
||||
|
||||
@@ -217,7 +215,7 @@ class SearchHitMapping<T> {
|
||||
searchHits.getAggregations());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn("Could not map inner_hits", e);
|
||||
throw new UncategorizedElasticsearchException("Unable to convert inner hits.", e);
|
||||
}
|
||||
|
||||
return searchHits;
|
||||
|
||||
@@ -20,7 +20,7 @@ import org.springframework.data.elasticsearch.core.convert.GeoConverters;
|
||||
import org.springframework.data.elasticsearch.core.document.Document;
|
||||
|
||||
/**
|
||||
* Interface definition for structures defined in <a href="https://geojson.org/>GeoJSON</a> format. copied from Spring
|
||||
* Interface definition for structures defined in <a href="https://geojson.org/">GeoJSON</a> format. copied from Spring
|
||||
* Data Mongodb
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
|
||||
@@ -156,10 +156,9 @@ public class MappingBuilder {
|
||||
boolean writeNestedProperties = !isRootObject && (isAnyPropertyAnnotatedWithField(entity) || nestedOrObjectField);
|
||||
if (writeNestedProperties) {
|
||||
|
||||
String type = nestedOrObjectField ? fieldType.toString().toLowerCase()
|
||||
: FieldType.Object.toString().toLowerCase();
|
||||
builder.startObject(nestedObjectFieldName).field(FIELD_PARAM_TYPE, type);
|
||||
String type = nestedOrObjectField ? fieldType.getMappedName() : FieldType.Object.getMappedName();
|
||||
|
||||
builder.startObject(nestedObjectFieldName).field(FIELD_PARAM_TYPE, type);
|
||||
if (nestedOrObjectField && FieldType.Nested == fieldType && parentFieldAnnotation != null
|
||||
&& parentFieldAnnotation.includeInParent()) {
|
||||
builder.field("include_in_parent", true);
|
||||
@@ -364,7 +363,7 @@ public class MappingBuilder {
|
||||
}
|
||||
|
||||
builder.startObject(property.getFieldName()) //
|
||||
.field(FIELD_PARAM_TYPE, field.type().name().toLowerCase()) //
|
||||
.field(FIELD_PARAM_TYPE, field.type().getMappedName()) //
|
||||
.field(MAPPING_ENABLED, false) //
|
||||
.endObject(); //
|
||||
} catch (Exception e) {
|
||||
@@ -392,7 +391,7 @@ public class MappingBuilder {
|
||||
builder.startObject(property.getFieldName());
|
||||
|
||||
if (nestedOrObjectField && dynamicMapping != null) {
|
||||
builder.field(TYPE_DYNAMIC, dynamicMapping.value().name().toLowerCase());
|
||||
builder.field(TYPE_DYNAMIC, dynamicMapping.value().getMappedName());
|
||||
}
|
||||
|
||||
addFieldMappingParameters(builder, annotation, nestedOrObjectField);
|
||||
@@ -441,7 +440,7 @@ public class MappingBuilder {
|
||||
builder.startObject(property.getFieldName());
|
||||
|
||||
if (nestedOrObjectField && dynamicMapping != null) {
|
||||
builder.field(TYPE_DYNAMIC, dynamicMapping.value().name().toLowerCase());
|
||||
builder.field(TYPE_DYNAMIC, dynamicMapping.value().getMappedName());
|
||||
}
|
||||
|
||||
addFieldMappingParameters(builder, annotation.mainField(), nestedOrObjectField);
|
||||
|
||||
+7
-5
@@ -71,7 +71,7 @@ public final class MappingParameters {
|
||||
static final String FIELD_PARAM_NULL_VALUE = "null_value";
|
||||
static final String FIELD_PARAM_POSITION_INCREMENT_GAP = "position_increment_gap";
|
||||
static final String FIELD_PARAM_POSITIVE_SCORE_IMPACT = "positive_score_impact";
|
||||
static final String FIELD_PARAM_DIMS = "dims";
|
||||
static final String FIELD_PARAM_DIMS = "dims";
|
||||
static final String FIELD_PARAM_SCALING_FACTOR = "scaling_factor";
|
||||
static final String FIELD_PARAM_SEARCH_ANALYZER = "search_analyzer";
|
||||
static final String FIELD_PARAM_STORE = "store";
|
||||
@@ -101,7 +101,7 @@ public final class MappingParameters {
|
||||
private final NullValueType nullValueType;
|
||||
private final Integer positionIncrementGap;
|
||||
private final boolean positiveScoreImpact;
|
||||
private final Integer dims;
|
||||
private final Integer dims;
|
||||
private final String searchAnalyzer;
|
||||
private final double scalingFactor;
|
||||
private final Similarity similarity;
|
||||
@@ -163,7 +163,8 @@ public final class MappingParameters {
|
||||
positiveScoreImpact = field.positiveScoreImpact();
|
||||
dims = field.dims();
|
||||
if (type == FieldType.Dense_Vector) {
|
||||
Assert.isTrue(dims >= 1 && dims <= 2048, "Invalid required parameter! Dense_Vector value \"dims\" must be between 1 and 2048.");
|
||||
Assert.isTrue(dims >= 1 && dims <= 2048,
|
||||
"Invalid required parameter! Dense_Vector value \"dims\" must be between 1 and 2048.");
|
||||
}
|
||||
Assert.isTrue(field.enabled() || type == FieldType.Object, "enabled false is only allowed for field type object");
|
||||
enabled = field.enabled();
|
||||
@@ -205,7 +206,8 @@ public final class MappingParameters {
|
||||
positiveScoreImpact = field.positiveScoreImpact();
|
||||
dims = field.dims();
|
||||
if (type == FieldType.Dense_Vector) {
|
||||
Assert.isTrue(dims >= 1 && dims <= 2048, "Invalid required parameter! Dense_Vector value \"dims\" must be between 1 and 2048.");
|
||||
Assert.isTrue(dims >= 1 && dims <= 2048,
|
||||
"Invalid required parameter! Dense_Vector value \"dims\" must be between 1 and 2048.");
|
||||
}
|
||||
enabled = true;
|
||||
eagerGlobalOrdinals = field.eagerGlobalOrdinals();
|
||||
@@ -229,7 +231,7 @@ public final class MappingParameters {
|
||||
}
|
||||
|
||||
if (type != FieldType.Auto) {
|
||||
builder.field(FIELD_PARAM_TYPE, type.name().toLowerCase());
|
||||
builder.field(FIELD_PARAM_TYPE, type.getMappedName());
|
||||
|
||||
if (type == FieldType.Date) {
|
||||
List<String> formats = new ArrayList<>();
|
||||
|
||||
@@ -15,10 +15,14 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.core.join;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.springframework.data.annotation.PersistenceConstructor;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* @author Subhobrata Dey
|
||||
* @author Sascha Woo
|
||||
* @since 4.1
|
||||
*/
|
||||
public class JoinField<ID> {
|
||||
@@ -35,6 +39,7 @@ public class JoinField<ID> {
|
||||
this(name, null);
|
||||
}
|
||||
|
||||
@PersistenceConstructor
|
||||
public JoinField(String name, @Nullable ID parent) {
|
||||
this.name = name;
|
||||
this.parent = parent;
|
||||
@@ -52,4 +57,21 @@ public class JoinField<ID> {
|
||||
public String getName() {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ import org.springframework.lang.Nullable;
|
||||
* @author Mohsin Husen
|
||||
* @author Peter-Josef Meisch
|
||||
* @author Farid Faoudi
|
||||
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update.html>docs</a>
|
||||
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update.html">docs</a>
|
||||
*/
|
||||
public class UpdateQuery {
|
||||
|
||||
|
||||
+6
-9
@@ -17,6 +17,7 @@ package org.springframework.data.elasticsearch.repository.query;
|
||||
|
||||
import org.springframework.core.convert.support.GenericConversionService;
|
||||
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.SearchHitSupport;
|
||||
import org.springframework.data.elasticsearch.core.SearchHits;
|
||||
@@ -84,16 +85,11 @@ public class ElasticsearchStringQuery extends AbstractElasticsearchRepositoryQue
|
||||
.unwrapSearchHits(SearchHitSupport.searchPageFor(searchHits, stringQuery.getPageable()));
|
||||
}
|
||||
} else if (queryMethod.isStreamQuery()) {
|
||||
if (accessor.getPageable().isUnpaged()) {
|
||||
stringQuery.setPageable(PageRequest.of(0, DEFAULT_STREAM_BATCH_SIZE));
|
||||
} else {
|
||||
stringQuery.setPageable(accessor.getPageable());
|
||||
}
|
||||
stringQuery.setPageable(
|
||||
accessor.getPageable().isPaged() ? accessor.getPageable() : PageRequest.of(0, DEFAULT_STREAM_BATCH_SIZE));
|
||||
result = StreamUtils.createStreamFromIterator(elasticsearchOperations.searchForStream(stringQuery, clazz, index));
|
||||
} else if (queryMethod.isCollectionQuery()) {
|
||||
if (accessor.getPageable().isPaged()) {
|
||||
stringQuery.setPageable(accessor.getPageable());
|
||||
}
|
||||
stringQuery.setPageable(accessor.getPageable().isPaged() ? accessor.getPageable() : Pageable.unpaged());
|
||||
result = elasticsearchOperations.search(stringQuery, clazz, index);
|
||||
} else {
|
||||
result = elasticsearchOperations.searchOne(stringQuery, clazz, index);
|
||||
@@ -105,7 +101,8 @@ public class ElasticsearchStringQuery extends AbstractElasticsearchRepositoryQue
|
||||
}
|
||||
|
||||
protected StringQuery createQuery(ParametersParameterAccessor parameterAccessor) {
|
||||
String queryString = StringQueryUtil.replacePlaceholders(this.query, parameterAccessor);
|
||||
String queryString = new StringQueryUtil(elasticsearchOperations.getElasticsearchConverter().getConversionService())
|
||||
.replacePlaceholders(this.query, parameterAccessor);
|
||||
return new StringQuery(queryString);
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -47,7 +47,9 @@ public class ReactiveElasticsearchStringQuery extends AbstractReactiveElasticsea
|
||||
|
||||
@Override
|
||||
protected StringQuery createQuery(ElasticsearchParameterAccessor parameterAccessor) {
|
||||
String queryString = StringQueryUtil.replacePlaceholders(this.query, parameterAccessor);
|
||||
String queryString = new StringQueryUtil(
|
||||
getElasticsearchOperations().getElasticsearchConverter().getConversionService()).replacePlaceholders(this.query,
|
||||
parameterAccessor);
|
||||
return new StringQuery(queryString);
|
||||
}
|
||||
|
||||
|
||||
+67
-21
@@ -15,41 +15,59 @@
|
||||
*/
|
||||
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 static 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
private final ConversionService conversionService;
|
||||
private final GenericConversionService genericConversionService;
|
||||
|
||||
private StringQueryUtil() {}
|
||||
public StringQueryUtil(ConversionService conversionService) {
|
||||
|
||||
public static String replacePlaceholders(String input, ParameterAccessor accessor) {
|
||||
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;
|
||||
@@ -62,7 +80,7 @@ final public class StringQueryUtil {
|
||||
return result;
|
||||
}
|
||||
|
||||
private static String getParameterWithIndex(ParameterAccessor accessor, int index) {
|
||||
private String getParameterWithIndex(ParameterAccessor accessor, int index) {
|
||||
|
||||
Object parameter = accessor.getBindableValue(index);
|
||||
String parameterValue = "null";
|
||||
@@ -70,20 +88,48 @@ final public class StringQueryUtil {
|
||||
// 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;
|
||||
}
|
||||
|
||||
parameterValue = parameterValue.replaceAll("\"", Matcher.quoteReplacement("\\\""));
|
||||
return parameterValue;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
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].
|
||||
@@ -1637,5 +1644,6 @@ Release Notes - Spring Data Elasticsearch - Version 1.0 M1 (2014-02-07)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Spring Data Elasticsearch 4.2.2 (2021.0.2)
|
||||
Spring Data Elasticsearch 4.2.12 (2021.0.12)
|
||||
Copyright (c) [2013-2021] Pivotal Software, Inc.
|
||||
|
||||
This product is licensed to you under the Apache License, Version 2.0 (the "License").
|
||||
@@ -19,6 +19,16 @@ conditions of the subcomponent's license, as noted in the LICENSE file.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+64
-3
@@ -50,10 +50,13 @@ import org.elasticsearch.cluster.metadata.AliasMetadata;
|
||||
import org.elasticsearch.common.lucene.search.function.CombineFunction;
|
||||
import org.elasticsearch.common.lucene.search.function.FunctionScoreQuery;
|
||||
import org.elasticsearch.index.VersionType;
|
||||
import org.elasticsearch.index.query.InnerHitBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilders;
|
||||
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
|
||||
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder.FilterFunctionBuilder;
|
||||
import org.elasticsearch.index.query.functionscore.GaussDecayFunctionBuilder;
|
||||
import org.elasticsearch.join.query.HasChildQueryBuilder;
|
||||
import org.elasticsearch.join.query.JoinQueryBuilders;
|
||||
import org.elasticsearch.join.query.ParentIdQueryBuilder;
|
||||
import org.elasticsearch.script.Script;
|
||||
import org.elasticsearch.script.ScriptType;
|
||||
@@ -1129,7 +1132,8 @@ public abstract class ElasticsearchTemplateTests {
|
||||
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()))
|
||||
.map(id -> getIndexQuery(
|
||||
SampleEntity.builder().id(id).message(sampleMessage).version(System.currentTimeMillis()).build()))
|
||||
.forEach(indexQuery -> operations.index(indexQuery, index));
|
||||
indexOperations.refresh();
|
||||
|
||||
@@ -1144,7 +1148,8 @@ public abstract class ElasticsearchTemplateTests {
|
||||
assertThat(searchHits.getTotalHits()).isEqualTo(10);
|
||||
assertThat(searchHits.getSearchHits()).hasSize(5);
|
||||
|
||||
Collection<String> returnedIds = searchHits.getSearchHits().stream().map(SearchHit::getId).collect(Collectors.toList());
|
||||
Collection<String> returnedIds = searchHits.getSearchHits().stream().map(SearchHit::getId)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
moreLikeThisQuery.setPageable(PageRequest.of(1, 5));
|
||||
|
||||
@@ -3027,6 +3032,46 @@ public abstract class ElasticsearchTemplateTests {
|
||||
indexOperations.removeAlias(aliasQuery);
|
||||
}
|
||||
|
||||
@Test // #1997
|
||||
@DisplayName("should return document with inner hits size zero")
|
||||
void shouldReturnDocumentWithInnerHitsSizeZero() {
|
||||
|
||||
// given
|
||||
SampleJoinEntity sampleQuestionEntity1 = new SampleJoinEntity();
|
||||
sampleQuestionEntity1.setUuid("q1");
|
||||
sampleQuestionEntity1.setText("This is a question");
|
||||
sampleQuestionEntity1.setMyJoinField(new JoinField<>("question"));
|
||||
|
||||
SampleJoinEntity sampleAnswerEntity1 = new SampleJoinEntity();
|
||||
sampleAnswerEntity1.setUuid("a1");
|
||||
sampleAnswerEntity1.setText("This is an answer");
|
||||
sampleAnswerEntity1.setMyJoinField(new JoinField<>("answer", sampleQuestionEntity1.getUuid()));
|
||||
|
||||
SampleJoinEntity sampleAnswerEntity2 = new SampleJoinEntity();
|
||||
sampleAnswerEntity1.setUuid("a2");
|
||||
sampleAnswerEntity1.setText("This is an answer");
|
||||
sampleAnswerEntity1.setMyJoinField(new JoinField<>("answer", sampleQuestionEntity1.getUuid()));
|
||||
|
||||
IndexOperations indexOps = operations.indexOps(SampleJoinEntity.class);
|
||||
operations.save(Arrays.asList(sampleQuestionEntity1, sampleAnswerEntity1, sampleAnswerEntity2));
|
||||
indexOps.refresh();
|
||||
|
||||
// when
|
||||
Query query = new NativeSearchQueryBuilder().withQuery(
|
||||
JoinQueryBuilders.hasChildQuery("answer", matchAllQuery(), org.apache.lucene.search.join.ScoreMode.Avg)
|
||||
.innerHit(new InnerHitBuilder("innerHits").setSize(0)))
|
||||
.build();
|
||||
|
||||
SearchHits<SampleJoinEntity> searchHits = operations.search(query, SampleJoinEntity.class);
|
||||
|
||||
// then
|
||||
assertThat(searchHits).isNotNull();
|
||||
assertThat(searchHits.getTotalHits()).isEqualTo(1);
|
||||
assertThat(searchHits.getSearchHits()).hasSize(1);
|
||||
assertThat(searchHits.getSearchHit(0).getInnerHits().size()).isEqualTo(1);
|
||||
assertThat(searchHits.getSearchHit(0).getInnerHits("innerHits").getTotalHits()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test // DATAES-541
|
||||
public void shouldRemoveAlias() {
|
||||
|
||||
@@ -3794,6 +3839,22 @@ public abstract class ElasticsearchTemplateTests {
|
||||
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)
|
||||
@Setting(shards = 1, replicas = 0, refreshInterval = "-1")
|
||||
@@ -4572,5 +4633,5 @@ public abstract class ElasticsearchTemplateTests {
|
||||
this.text = text;
|
||||
}
|
||||
}
|
||||
//endregion
|
||||
// endregion
|
||||
}
|
||||
|
||||
+211
-70
@@ -308,8 +308,10 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
|
||||
|
||||
@Document(indexName = "ignore-above-index")
|
||||
static class IgnoreAboveEntity {
|
||||
@Nullable @Id private String id;
|
||||
@Nullable @Field(type = FieldType.Keyword, ignoreAbove = 10) private String message;
|
||||
@Nullable
|
||||
@Id private String id;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Keyword, ignoreAbove = 10) private String message;
|
||||
|
||||
@Nullable
|
||||
public String getId() {
|
||||
@@ -334,13 +336,17 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
|
||||
|
||||
@Document(indexName = "fieldname-index")
|
||||
static class IdEntity {
|
||||
@Nullable @Id @Field("id-property") private String id;
|
||||
@Nullable
|
||||
@Id
|
||||
@Field("id-property") private String id;
|
||||
}
|
||||
|
||||
@Document(indexName = "fieldname-index")
|
||||
static class TextEntity {
|
||||
|
||||
@Nullable @Id @Field("id-property") private String id;
|
||||
@Nullable
|
||||
@Id
|
||||
@Field("id-property") private String id;
|
||||
|
||||
@Field(name = "text-property", type = FieldType.Text) //
|
||||
@Nullable private String textProperty;
|
||||
@@ -349,42 +355,57 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
|
||||
@Document(indexName = "fieldname-index")
|
||||
static class MappingEntity {
|
||||
|
||||
@Nullable @Id @Field("id-property") private String id;
|
||||
@Nullable
|
||||
@Id
|
||||
@Field("id-property") private String id;
|
||||
|
||||
@Field("mapping-property") @Mapping(mappingPath = "/mappings/test-field-analyzed-mappings.json") //
|
||||
@Field("mapping-property")
|
||||
@Mapping(mappingPath = "/mappings/test-field-analyzed-mappings.json") //
|
||||
@Nullable private byte[] mappingProperty;
|
||||
}
|
||||
|
||||
@Document(indexName = "fieldname-index")
|
||||
static class GeoPointEntity {
|
||||
|
||||
@Nullable @Id @Field("id-property") private String id;
|
||||
@Nullable
|
||||
@Id
|
||||
@Field("id-property") private String id;
|
||||
|
||||
@Nullable @Field("geopoint-property") private GeoPoint geoPoint;
|
||||
@Nullable
|
||||
@Field("geopoint-property") private GeoPoint geoPoint;
|
||||
}
|
||||
|
||||
@Document(indexName = "fieldname-index")
|
||||
static class CircularEntity {
|
||||
|
||||
@Nullable @Id @Field("id-property") private String id;
|
||||
@Nullable
|
||||
@Id
|
||||
@Field("id-property") private String id;
|
||||
|
||||
@Nullable @Field(name = "circular-property", type = FieldType.Object, ignoreFields = { "circular-property" }) //
|
||||
@Nullable
|
||||
@Field(name = "circular-property", type = FieldType.Object, ignoreFields = { "circular-property" }) //
|
||||
private CircularEntity circularProperty;
|
||||
}
|
||||
|
||||
@Document(indexName = "fieldname-index")
|
||||
static class CompletionEntity {
|
||||
|
||||
@Nullable @Id @Field("id-property") private String id;
|
||||
@Nullable
|
||||
@Id
|
||||
@Field("id-property") private String id;
|
||||
|
||||
@Nullable @Field("completion-property") @CompletionField(maxInputLength = 100) //
|
||||
@Nullable
|
||||
@Field("completion-property")
|
||||
@CompletionField(maxInputLength = 100) //
|
||||
private Completion suggest;
|
||||
}
|
||||
|
||||
@Document(indexName = "fieldname-index")
|
||||
static class MultiFieldEntity {
|
||||
|
||||
@Nullable @Id @Field("id-property") private String id;
|
||||
@Nullable
|
||||
@Id
|
||||
@Field("id-property") private String id;
|
||||
|
||||
@Nullable //
|
||||
@MultiField(mainField = @Field(name = "main-field", type = FieldType.Text, analyzer = "whitespace"),
|
||||
@@ -396,11 +417,15 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
|
||||
|
||||
@Document(indexName = "test-index-book-mapping-builder")
|
||||
static class Book {
|
||||
@Nullable @Id private String id;
|
||||
@Nullable
|
||||
@Id private String id;
|
||||
@Nullable private String name;
|
||||
@Nullable @Field(type = FieldType.Object) private Author author;
|
||||
@Nullable @Field(type = FieldType.Nested) private Map<Integer, Collection<String>> buckets = new HashMap<>();
|
||||
@Nullable @MultiField(mainField = @Field(type = FieldType.Text, analyzer = "whitespace"),
|
||||
@Nullable
|
||||
@Field(type = FieldType.Object) private Author author;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Nested) private Map<Integer, Collection<String>> buckets = new HashMap<>();
|
||||
@Nullable
|
||||
@MultiField(mainField = @Field(type = FieldType.Text, analyzer = "whitespace"),
|
||||
otherFields = { @InnerField(suffix = "prefix", type = FieldType.Text, analyzer = "stop",
|
||||
searchAnalyzer = "standard") }) private String description;
|
||||
|
||||
@@ -452,9 +477,10 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
|
||||
|
||||
@Document(indexName = "test-index-simple-recursive-mapping-builder")
|
||||
static class SimpleRecursiveEntity {
|
||||
@Nullable @Id private String id;
|
||||
@Nullable @Field(type = FieldType.Object,
|
||||
ignoreFields = { "circularObject" }) private SimpleRecursiveEntity circularObject;
|
||||
@Nullable
|
||||
@Id private String id;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Object, ignoreFields = { "circularObject" }) private SimpleRecursiveEntity circularObject;
|
||||
|
||||
@Nullable
|
||||
public String getId() {
|
||||
@@ -477,10 +503,14 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
|
||||
|
||||
@Document(indexName = "test-copy-to-mapping-builder")
|
||||
static class CopyToEntity {
|
||||
@Nullable @Id private String id;
|
||||
@Nullable @Field(type = FieldType.Keyword, copyTo = "name") private String firstName;
|
||||
@Nullable @Field(type = FieldType.Keyword, copyTo = "name") private String lastName;
|
||||
@Nullable @Field(type = FieldType.Keyword) private String name;
|
||||
@Nullable
|
||||
@Id private String id;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Keyword, copyTo = "name") private String firstName;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Keyword, copyTo = "name") private String lastName;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Keyword) private String name;
|
||||
|
||||
@Nullable
|
||||
public String getId() {
|
||||
@@ -522,9 +552,12 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
|
||||
@Document(indexName = "test-index-normalizer-mapping-builder")
|
||||
@Setting(settingPath = "/settings/test-normalizer.json")
|
||||
static class NormalizerEntity {
|
||||
@Nullable @Id private String id;
|
||||
@Nullable @Field(type = FieldType.Keyword, normalizer = "lower_case_normalizer") private String name;
|
||||
@Nullable @MultiField(mainField = @Field(type = FieldType.Text), otherFields = { @InnerField(suffix = "lower_case",
|
||||
@Nullable
|
||||
@Id private String id;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Keyword, normalizer = "lower_case_normalizer") private String name;
|
||||
@Nullable
|
||||
@MultiField(mainField = @Field(type = FieldType.Text), otherFields = { @InnerField(suffix = "lower_case",
|
||||
type = FieldType.Keyword, normalizer = "lower_case_normalizer") }) private String description;
|
||||
|
||||
@Nullable
|
||||
@@ -582,7 +615,8 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
|
||||
@Document(indexName = "test-index-sample-inherited-mapping-builder")
|
||||
static class SampleInheritedEntity extends AbstractInheritedEntity {
|
||||
|
||||
@Nullable @Field(type = Text, index = false, store = true, analyzer = "standard") private String message;
|
||||
@Nullable
|
||||
@Field(type = Text, index = false, store = true, analyzer = "standard") private String message;
|
||||
|
||||
@Nullable
|
||||
public String getMessage() {
|
||||
@@ -627,9 +661,11 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
|
||||
|
||||
@Document(indexName = "test-index-stock-mapping-builder")
|
||||
static class StockPrice {
|
||||
@Nullable @Id private String id;
|
||||
@Nullable
|
||||
@Id private String id;
|
||||
@Nullable private String symbol;
|
||||
@Nullable @Field(type = FieldType.Double) private BigDecimal price;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Double) private BigDecimal price;
|
||||
|
||||
@Nullable
|
||||
public String getId() {
|
||||
@@ -660,8 +696,10 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
|
||||
}
|
||||
|
||||
static class AbstractInheritedEntity {
|
||||
@Nullable @Id private String id;
|
||||
@Nullable @Field(type = FieldType.Date, format = DateFormat.date_time, index = false) private Date createdDate;
|
||||
@Nullable
|
||||
@Id private String id;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Date, format = DateFormat.date_time, index = false) private Date createdDate;
|
||||
|
||||
@Nullable
|
||||
public String getId() {
|
||||
@@ -684,19 +722,25 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
|
||||
|
||||
@Document(indexName = "test-index-geo-mapping-builder")
|
||||
static class GeoEntity {
|
||||
@Nullable @Id private String id;
|
||||
@Nullable
|
||||
@Id private String id;
|
||||
// geo shape - Spring Data
|
||||
@Nullable private Box box;
|
||||
@Nullable private Circle circle;
|
||||
@Nullable private Polygon polygon;
|
||||
// geo point - Custom implementation + Spring Data
|
||||
@Nullable @GeoPointField private Point pointA;
|
||||
@Nullable
|
||||
@GeoPointField private Point pointA;
|
||||
@Nullable private GeoPoint pointB;
|
||||
@Nullable @GeoPointField private String pointC;
|
||||
@Nullable @GeoPointField private double[] pointD;
|
||||
@Nullable
|
||||
@GeoPointField private String pointC;
|
||||
@Nullable
|
||||
@GeoPointField private double[] pointD;
|
||||
// geo shape, until e have the classes for this, us a strng
|
||||
@Nullable @GeoShapeField private String shape1;
|
||||
@Nullable @GeoShapeField(coerce = true, ignoreMalformed = true, ignoreZValue = false,
|
||||
@Nullable
|
||||
@GeoShapeField private String shape1;
|
||||
@Nullable
|
||||
@GeoShapeField(coerce = true, ignoreMalformed = true, ignoreZValue = false,
|
||||
orientation = GeoShapeField.Orientation.clockwise) private String shape2;
|
||||
|
||||
@Nullable
|
||||
@@ -792,7 +836,8 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
|
||||
|
||||
@Document(indexName = "test-index-user-mapping-builder")
|
||||
static class User {
|
||||
@Nullable @Id private String id;
|
||||
@Nullable
|
||||
@Id private String id;
|
||||
|
||||
@Field(type = FieldType.Nested, ignoreFields = { "users" }) private Set<Group> groups = new HashSet<>();
|
||||
}
|
||||
@@ -800,7 +845,8 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
|
||||
@Document(indexName = "test-index-group-mapping-builder")
|
||||
static class Group {
|
||||
|
||||
@Nullable @Id String id;
|
||||
@Nullable
|
||||
@Id String id;
|
||||
|
||||
@Field(type = FieldType.Nested, ignoreFields = { "groups" }) private Set<User> users = new HashSet<>();
|
||||
}
|
||||
@@ -819,8 +865,10 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
|
||||
|
||||
@Document(indexName = "completion")
|
||||
static class CompletionDocument {
|
||||
@Nullable @Id private String id;
|
||||
@Nullable @CompletionField(contexts = { @CompletionContext(name = "location", type = ContextMapping.Type.GEO,
|
||||
@Nullable
|
||||
@Id private String id;
|
||||
@Nullable
|
||||
@CompletionField(contexts = { @CompletionContext(name = "location", type = ContextMapping.Type.GEO,
|
||||
path = "proppath") }) private Completion suggest;
|
||||
|
||||
@Nullable
|
||||
@@ -844,7 +892,8 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
|
||||
|
||||
@Document(indexName = "test-index-entity-with-seq-no-primary-term-mapping-builder")
|
||||
static class EntityWithSeqNoPrimaryTerm {
|
||||
@Nullable @Field(type = Object) private SeqNoPrimaryTerm seqNoPrimaryTerm;
|
||||
@Nullable
|
||||
@Field(type = Object) private SeqNoPrimaryTerm seqNoPrimaryTerm;
|
||||
|
||||
@Nullable
|
||||
public SeqNoPrimaryTerm getSeqNoPrimaryTerm() {
|
||||
@@ -857,10 +906,14 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
|
||||
}
|
||||
|
||||
static class RankFeatureEntity {
|
||||
@Nullable @Id private String id;
|
||||
@Nullable @Field(type = FieldType.Rank_Feature) private Integer pageRank;
|
||||
@Nullable @Field(type = FieldType.Rank_Feature, positiveScoreImpact = false) private Integer urlLength;
|
||||
@Nullable @Field(type = FieldType.Rank_Features) private Map<String, Integer> topics;
|
||||
@Nullable
|
||||
@Id private String id;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Rank_Feature) private Integer pageRank;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Rank_Feature, positiveScoreImpact = false) private Integer urlLength;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Rank_Features) private Map<String, Integer> topics;
|
||||
|
||||
@Nullable
|
||||
public String getId() {
|
||||
@@ -901,16 +954,23 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
|
||||
|
||||
@Document(indexName = "termvectors-test")
|
||||
static class TermVectorFieldEntity {
|
||||
@Nullable @Id private String id;
|
||||
@Nullable @Field(type = FieldType.Text, termVector = TermVector.no) private String no;
|
||||
@Nullable @Field(type = FieldType.Text, termVector = TermVector.yes) private String yes;
|
||||
@Nullable @Field(type = FieldType.Text, termVector = TermVector.with_positions) private String with_positions;
|
||||
@Nullable @Field(type = FieldType.Text, termVector = TermVector.with_offsets) private String with_offsets;
|
||||
@Nullable @Field(type = FieldType.Text,
|
||||
termVector = TermVector.with_positions_offsets) private String with_positions_offsets;
|
||||
@Nullable @Field(type = FieldType.Text,
|
||||
@Nullable
|
||||
@Id private String id;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Text, termVector = TermVector.no) private String no;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Text, termVector = TermVector.yes) private String yes;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Text, termVector = TermVector.with_positions) private String with_positions;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Text, termVector = TermVector.with_offsets) private String with_offsets;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Text, termVector = TermVector.with_positions_offsets) private String with_positions_offsets;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Text,
|
||||
termVector = TermVector.with_positions_payloads) private String with_positions_payloads;
|
||||
@Nullable @Field(type = FieldType.Text,
|
||||
@Nullable
|
||||
@Field(type = FieldType.Text,
|
||||
termVector = TermVector.with_positions_offsets_payloads) private String with_positions_offsets_payloads;
|
||||
|
||||
@Nullable
|
||||
@@ -988,8 +1048,10 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
|
||||
|
||||
@Document(indexName = "wildcard-test")
|
||||
static class WildcardEntity {
|
||||
@Nullable @Field(type = Wildcard) private String wildcardWithoutParams;
|
||||
@Nullable @Field(type = Wildcard, nullValue = "WILD", ignoreAbove = 42) private String wildcardWithParams;
|
||||
@Nullable
|
||||
@Field(type = Wildcard) private String wildcardWithoutParams;
|
||||
@Nullable
|
||||
@Field(type = Wildcard, nullValue = "WILD", ignoreAbove = 42) private String wildcardWithParams;
|
||||
|
||||
@Nullable
|
||||
public String getWildcardWithoutParams() {
|
||||
@@ -1013,8 +1075,10 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
|
||||
@Document(indexName = "disabled-entity-mapping")
|
||||
@Mapping(enabled = false)
|
||||
static class DisabledMappingEntity {
|
||||
@Nullable @Id private String id;
|
||||
@Nullable @Field(type = Text) private String text;
|
||||
@Nullable
|
||||
@Id private String id;
|
||||
@Nullable
|
||||
@Field(type = Text) private String text;
|
||||
|
||||
@Nullable
|
||||
public String getId() {
|
||||
@@ -1037,9 +1101,13 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
|
||||
|
||||
@Document(indexName = "disabled-property-mapping")
|
||||
static class DisabledMappingProperty {
|
||||
@Nullable @Id private String id;
|
||||
@Nullable @Field(type = Text) private String text;
|
||||
@Nullable @Mapping(enabled = false) @Field(type = Object) private Object object;
|
||||
@Nullable
|
||||
@Id private String id;
|
||||
@Nullable
|
||||
@Field(type = Text) private String text;
|
||||
@Nullable
|
||||
@Mapping(enabled = false)
|
||||
@Field(type = Object) private Object object;
|
||||
|
||||
@Nullable
|
||||
public String getId() {
|
||||
@@ -1071,8 +1139,10 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
|
||||
|
||||
@Document(indexName = "densevector-test")
|
||||
static class DenseVectorEntity {
|
||||
@Nullable @Id private String id;
|
||||
@Nullable @Field(type = Dense_Vector, dims = 3) private float[] dense_vector;
|
||||
@Nullable
|
||||
@Id private String id;
|
||||
@Nullable
|
||||
@Field(type = Dense_Vector, dims = 3) private float[] dense_vector;
|
||||
|
||||
@Nullable
|
||||
public String getId() {
|
||||
@@ -1097,11 +1167,15 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
|
||||
@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
|
||||
@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() {
|
||||
@@ -1113,4 +1187,71 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Document(indexName = "allTypes")
|
||||
private static class EntityWithAllTypes {
|
||||
@Nullable
|
||||
@Field(type = FieldType.Auto) String autoField;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Text) String textField;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Keyword) String keywordField;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Long) String longField;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Integer) String integerField;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Short) String shortField;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Byte) String byteField;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Double) String doubleField;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Float) String floatField;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Half_Float) String halfFloatField;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Scaled_Float) String scaledFloatField;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Date) String dateField;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Date_Nanos) String dateNanosField;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Boolean) String booleanField;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Binary) String binaryField;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Integer_Range) String integerRangeField;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Float_Range) String floatRangeField;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Long_Range) String longRangeField;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Double_Range) String doubleRangeField;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Date_Range) String dateRangeField;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Ip_Range) String ipRangeField;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Object) String objectField;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Nested) String nestedField;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Ip) String ipField;
|
||||
@Nullable
|
||||
@Field(type = FieldType.TokenCount, analyzer = "standard") String tokenCountField;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Percolator) String percolatorField;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Flattened) String flattenedField;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Search_As_You_Type) String searchAsYouTypeField;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Rank_Feature) String rankFeatureField;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Rank_Features) String rankFeaturesField;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Wildcard) String wildcardField;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Dense_Vector, dims = 1) String denseVectorField;
|
||||
}
|
||||
}
|
||||
|
||||
+18
@@ -29,10 +29,12 @@ import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.elasticsearch.annotations.Document;
|
||||
import org.springframework.data.elasticsearch.annotations.Routing;
|
||||
import org.springframework.data.elasticsearch.annotations.Setting;
|
||||
import org.springframework.data.elasticsearch.core.AbstractElasticsearchTemplate;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
||||
import org.springframework.data.elasticsearch.core.IndexOperations;
|
||||
import org.springframework.data.elasticsearch.core.SearchHits;
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
|
||||
import org.springframework.data.elasticsearch.core.query.Query;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.ElasticsearchRestTemplateConfiguration;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.SpringIntegrationTest;
|
||||
@@ -41,6 +43,7 @@ import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
/**
|
||||
* @author Peter-Josef Meisch
|
||||
* @author Anton Naydenov
|
||||
*/
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@SpringIntegrationTest
|
||||
@@ -118,6 +121,21 @@ public class ElasticsearchOperationsRoutingTests {
|
||||
assertThat(searchHits.getSearchHit(0).getRouting()).isEqualTo(ID_2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCreateACopyOfTheClientWithRefreshPolicy() {
|
||||
// given
|
||||
AbstractElasticsearchTemplate sourceTemplate = (AbstractElasticsearchTemplate) operations;
|
||||
SimpleElasticsearchMappingContext mappingContext = new SimpleElasticsearchMappingContext();
|
||||
DefaultRoutingResolver defaultRoutingResolver = new DefaultRoutingResolver(mappingContext);
|
||||
|
||||
// when
|
||||
ElasticsearchOperations operationsCopy = this.operations.withRouting(defaultRoutingResolver);
|
||||
AbstractElasticsearchTemplate copyTemplate = (AbstractElasticsearchTemplate) operationsCopy;
|
||||
|
||||
// then
|
||||
assertThat(sourceTemplate.getRefreshPolicy()).isEqualTo(copyTemplate.getRefreshPolicy());
|
||||
}
|
||||
|
||||
@Document(indexName = INDEX)
|
||||
@Setting(shards = 5)
|
||||
@Routing("routing")
|
||||
|
||||
+28
-11
@@ -1610,19 +1610,18 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
assertThat((nextPageable.getPageNumber())).isEqualTo(1);
|
||||
}
|
||||
|
||||
private List<SampleEntity> createSampleEntities(String type, int numberOfEntities) {
|
||||
@Test // #1917
|
||||
@DisplayName("shouldReturnAllDocumentsWithUnpagedQuery")
|
||||
void shouldReturnAllDocumentsWithUnpagedQuery() {
|
||||
|
||||
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);
|
||||
}
|
||||
List<SampleEntity> entities = createSampleEntities("abc", 20);
|
||||
repository.saveAll(entities);
|
||||
|
||||
return entities;
|
||||
SearchHits<SampleEntity> searchHits = repository.searchWithQueryByMessageUnpaged("Message");
|
||||
|
||||
assertThat(searchHits).isNotNull();
|
||||
assertThat((searchHits.getTotalHits())).isEqualTo(20);
|
||||
assertThat(searchHits.getSearchHits()).hasSize(20);
|
||||
}
|
||||
|
||||
@Test // DATAES-891
|
||||
@@ -1647,6 +1646,21 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
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")
|
||||
static class SampleEntity {
|
||||
@Nullable @Id private String id;
|
||||
@@ -1854,6 +1868,9 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
@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\"}}}}")
|
||||
long countWithQueryByType(String type);
|
||||
}
|
||||
|
||||
+78
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+81
-32
@@ -16,8 +16,10 @@
|
||||
package org.springframework.data.elasticsearch.repository.query;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
@@ -39,9 +41,6 @@ import org.springframework.data.elasticsearch.annotations.MultiField;
|
||||
import org.springframework.data.elasticsearch.annotations.Query;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
||||
import org.springframework.data.elasticsearch.core.SearchHits;
|
||||
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
||||
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.projection.SpelAwareProxyProjectionFactory;
|
||||
import org.springframework.data.repository.Repository;
|
||||
@@ -51,16 +50,16 @@ import org.springframework.lang.Nullable;
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @author Peter-Josef Meisch
|
||||
* @author Niklas Herder
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class ElasticsearchStringQueryUnitTests {
|
||||
public class ElasticsearchStringQueryUnitTests extends ElasticsearchStringQueryUnitTestBase {
|
||||
|
||||
@Mock ElasticsearchOperations operations;
|
||||
ElasticsearchConverter converter;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
converter = new MappingElasticsearchConverter(new SimpleElasticsearchMappingContext());
|
||||
when(operations.getElasticsearchConverter()).thenReturn(setupConverter());
|
||||
}
|
||||
|
||||
@Test // DATAES-552
|
||||
@@ -95,7 +94,42 @@ public class ElasticsearchStringQueryUnitTests {
|
||||
.isEqualTo("{\"bool\":{\"must\": [{\"match\": {\"prefix\": {\"name\" : \"hello \\\"Stranger\\\"\"}}]}}");
|
||||
}
|
||||
|
||||
private org.springframework.data.elasticsearch.core.query.Query createQuery(String methodName, String... args)
|
||||
@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 {
|
||||
|
||||
Class<?>[] argTypes = Arrays.stream(args).map(Object::getClass).toArray(Class[]::new);
|
||||
@@ -103,6 +137,22 @@ public class ElasticsearchStringQueryUnitTests {
|
||||
ElasticsearchStringQuery elasticsearchStringQuery = queryForMethod(queryMethod);
|
||||
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) {
|
||||
return new ElasticsearchStringQuery(queryMethod, operations, queryMethod.getAnnotatedQuery());
|
||||
}
|
||||
@@ -111,36 +161,59 @@ public class ElasticsearchStringQueryUnitTests {
|
||||
|
||||
Method method = SampleRepository.class.getMethod(name, parameters);
|
||||
return new ElasticsearchQueryMethod(method, new DefaultRepositoryMetadata(SampleRepository.class),
|
||||
new SpelAwareProxyProjectionFactory(), converter.getMappingContext());
|
||||
new SpelAwareProxyProjectionFactory(), operations.getElasticsearchConverter().getMappingContext());
|
||||
}
|
||||
|
||||
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' } } } }")
|
||||
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)")
|
||||
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);
|
||||
|
||||
@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 Mohsin Husen
|
||||
* @author Artur Konczak
|
||||
* @author Niklas Herder
|
||||
*/
|
||||
|
||||
@Document(indexName = "test-index-person-query-unittest")
|
||||
static class Person {
|
||||
|
||||
@Nullable public int age;
|
||||
@Nullable @Id private String id;
|
||||
@Nullable private String name;
|
||||
@Nullable @Field(type = FieldType.Nested) private List<Car> car;
|
||||
@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
|
||||
public String getId() {
|
||||
return id;
|
||||
@@ -234,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 {
|
||||
|
||||
@Nullable private String id;
|
||||
@@ -280,5 +330,4 @@ public class ElasticsearchStringQueryUnitTests {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+23
-31
@@ -16,6 +16,7 @@
|
||||
package org.springframework.data.elasticsearch.repository.query;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
@@ -43,9 +44,6 @@ import org.springframework.data.elasticsearch.annotations.MultiField;
|
||||
import org.springframework.data.elasticsearch.annotations.Query;
|
||||
import org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations;
|
||||
import org.springframework.data.elasticsearch.core.SearchHit;
|
||||
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
||||
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.projection.SpelAwareProxyProjectionFactory;
|
||||
import org.springframework.data.repository.Repository;
|
||||
@@ -59,16 +57,15 @@ import org.springframework.lang.Nullable;
|
||||
* @author Peter-Josef Meisch
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class ReactiveElasticsearchStringQueryUnitTests {
|
||||
public class ReactiveElasticsearchStringQueryUnitTests extends ElasticsearchStringQueryUnitTestBase {
|
||||
|
||||
SpelExpressionParser PARSER = new SpelExpressionParser();
|
||||
ElasticsearchConverter converter;
|
||||
|
||||
@Mock ReactiveElasticsearchOperations operations;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
converter = new MappingElasticsearchConverter(new SimpleElasticsearchMappingContext());
|
||||
when(operations.getElasticsearchConverter()).thenReturn(setupConverter());
|
||||
}
|
||||
|
||||
@Test // DATAES-519
|
||||
@@ -132,7 +129,22 @@ public class ReactiveElasticsearchStringQueryUnitTests {
|
||||
.isEqualTo("{\"bool\":{\"must\": [{\"match\": {\"prefix\": {\"name\" : \"hello \\\"Stranger\\\"\"}}]}}");
|
||||
}
|
||||
|
||||
private org.springframework.data.elasticsearch.core.query.Query createQuery(String methodName, String... args)
|
||||
@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 {
|
||||
|
||||
Class<?>[] argTypes = Arrays.stream(args).map(Object::getClass).toArray(Class[]::new);
|
||||
@@ -152,7 +164,7 @@ public class ReactiveElasticsearchStringQueryUnitTests {
|
||||
|
||||
Method method = SampleRepository.class.getMethod(name, parameters);
|
||||
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 {
|
||||
@@ -180,6 +192,9 @@ public class ReactiveElasticsearchStringQueryUnitTests {
|
||||
@Query("{\"bool\":{\"must\": [{\"match\": {\"prefix\": {\"name\" : \"?0\"}}]}}")
|
||||
Flux<SearchHit<Book>> findByPrefix(String prefix);
|
||||
|
||||
@Query("{ 'bool' : { 'must' : { 'term' : { 'car' : '?0' } } } }")
|
||||
Mono<Person> findByCar(Car car);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -292,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 {
|
||||
|
||||
@Nullable private String id;
|
||||
|
||||
+31
-5
@@ -28,6 +28,7 @@ import java.lang.Long;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.elasticsearch.ElasticsearchStatusException;
|
||||
@@ -541,14 +542,36 @@ class SimpleReactiveElasticsearchRepositoryTests {
|
||||
@Test // DATAES-519
|
||||
void annotatedFinderMethodShouldBeExecutedCorrectly() {
|
||||
|
||||
bulkIndex(new SampleEntity("id-one", "message"), //
|
||||
new SampleEntity("id-two", "test message"), //
|
||||
new SampleEntity("id-three", "test test")) //
|
||||
.block();
|
||||
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.findAllViaAnnotatedQueryByMessageLike("test") //
|
||||
.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();
|
||||
}
|
||||
|
||||
@@ -596,6 +619,9 @@ class SimpleReactiveElasticsearchRepositoryTests {
|
||||
@Query("{ \"bool\" : { \"must\" : { \"term\" : { \"message\" : \"?0\" } } } }")
|
||||
Flux<SampleEntity> findAllViaAnnotatedQueryByMessageLike(String message);
|
||||
|
||||
@Query("{ \"bool\" : { \"must\" : { \"term\" : { \"message\" : \"?0\" } } } }")
|
||||
Flux<SampleEntity> findAllViaAnnotatedQueryByMessageLikePaged(String message, Pageable pageable);
|
||||
|
||||
Mono<SampleEntity> findFirstByMessageLike(String message);
|
||||
|
||||
Mono<Long> countAllByMessage(String message);
|
||||
|
||||
Reference in New Issue
Block a user