Compare commits
55 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 22fe50c73a | |||
| ef90755c27 | |||
| 9153d4dff4 | |||
| 9109dfa257 | |||
| 64eee02b85 | |||
| 31365fb722 | |||
| c218c1d5e3 | |||
| 5bce5dd880 | |||
| 32c4c4d03f | |||
| 5102d98e10 | |||
| 57a4b755c1 | |||
| edaae2a4e8 | |||
| 4747caf57a | |||
| aba2ff6f5c | |||
| 0dc2902cab | |||
| 3c60e5f9cc | |||
| ef822355ac | |||
| 94d23a1403 | |||
| 13b4d62031 | |||
| 1087b0355f | |||
| 22ed898d63 | |||
| a474a0f533 | |||
| 1d23fb14fa | |||
| e1741ca255 | |||
| 3e4477af16 | |||
| 2244f855f3 | |||
| 03265a4551 | |||
| fdc03cf29e | |||
| e1da43ca9f | |||
| 4a1a4d3851 | |||
| a9ee467455 | |||
| ebccb34db1 | |||
| d1e349f689 | |||
| b8722bab84 | |||
| 9e35f70833 | |||
| 59f3a6b120 | |||
| e534e952a1 | |||
| 868a9d049a | |||
| 28727c6b36 | |||
| 89528e0e59 | |||
| 42e49e8ff7 | |||
| b52fc2f0d7 | |||
| 1923721ebf | |||
| 8834cbfe03 | |||
| 2dabb2f89f | |||
| 40a91d01a8 | |||
| aab18b55ab | |||
| 6351b9f026 | |||
| 7d5b9d5b7c | |||
| 5cf7b2baae | |||
| b005c77cad | |||
| d90d0ed71c | |||
| 5b3cf9af4c | |||
| 85a7ed7dc8 | |||
| a64c24e64b |
+2
-2
@@ -1,3 +1,3 @@
|
||||
#Fri Jun 03 09:32:51 CEST 2022
|
||||
#Mon Jul 03 09:46:39 CEST 2023
|
||||
wrapperUrl=https\://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
|
||||
distributionUrl=https\://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.5/apache-maven-3.8.5-bin.zip
|
||||
distributionUrl=https\://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.3/apache-maven-3.9.3-bin.zip
|
||||
|
||||
Vendored
+43
-24
@@ -1,7 +1,7 @@
|
||||
def p = [:]
|
||||
node {
|
||||
checkout scm
|
||||
p = readProperties interpolate: true, file: 'ci/pipeline.properties'
|
||||
checkout scm
|
||||
p = readProperties interpolate: true, file: 'ci/pipeline.properties'
|
||||
}
|
||||
|
||||
pipeline {
|
||||
@@ -18,7 +18,7 @@ pipeline {
|
||||
}
|
||||
|
||||
stages {
|
||||
stage("test: baseline (Java 17)") {
|
||||
stage("test: baseline (main)") {
|
||||
when {
|
||||
beforeAgent(true)
|
||||
anyOf {
|
||||
@@ -32,17 +32,42 @@ pipeline {
|
||||
options { timeout(time: 30, unit: 'MINUTES') }
|
||||
|
||||
environment {
|
||||
DOCKER_HUB = credentials("${p['docker.credentials']}")
|
||||
ARTIFACTORY = credentials("${p['artifactory.credentials']}")
|
||||
}
|
||||
|
||||
steps {
|
||||
script {
|
||||
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"
|
||||
docker.image(p['docker.java.main.image']).inside(p['docker.java.inside.docker']) {
|
||||
sh 'PROFILE=none ci/verify.sh'
|
||||
sh "ci/clean.sh"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage("Test other configurations") {
|
||||
when {
|
||||
beforeAgent(true)
|
||||
allOf {
|
||||
branch(pattern: "main|(\\d\\.\\d\\.x)", comparator: "REGEXP")
|
||||
not { triggeredBy 'UpstreamCause' }
|
||||
}
|
||||
}
|
||||
parallel {
|
||||
stage("test: baseline (next)") {
|
||||
agent {
|
||||
label 'data'
|
||||
}
|
||||
options { timeout(time: 30, unit: 'MINUTES') }
|
||||
environment {
|
||||
ARTIFACTORY = credentials("${p['artifactory.credentials']}")
|
||||
}
|
||||
steps {
|
||||
script {
|
||||
docker.image(p['docker.java.next.image']).inside(p['docker.java.inside.docker']) {
|
||||
sh 'PROFILE=none ci/verify.sh'
|
||||
sh "ci/clean.sh"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -68,17 +93,15 @@ pipeline {
|
||||
|
||||
steps {
|
||||
script {
|
||||
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} " +
|
||||
"-Dartifactory.password=${ARTIFACTORY_PSW} " +
|
||||
"-Dartifactory.staging-repository=libs-snapshot-local " +
|
||||
"-Dartifactory.build-name=spring-data-elasticsearch " +
|
||||
"-Dartifactory.build-number=${BUILD_NUMBER} " +
|
||||
'-Dmaven.test.skip=true clean deploy -U -B'
|
||||
}
|
||||
docker.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} " +
|
||||
"-Dartifactory.password=${ARTIFACTORY_PSW} " +
|
||||
"-Dartifactory.staging-repository=libs-snapshot-local " +
|
||||
"-Dartifactory.build-name=spring-data-elasticsearch " +
|
||||
"-Dartifactory.build-number=${BUILD_NUMBER} " +
|
||||
'-Dmaven.test.skip=true clean deploy -U -B'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -88,10 +111,6 @@ pipeline {
|
||||
post {
|
||||
changed {
|
||||
script {
|
||||
slackSend(
|
||||
color: (currentBuild.currentResult == 'SUCCESS') ? 'good' : 'danger',
|
||||
channel: '#spring-data-dev',
|
||||
message: "${currentBuild.fullDisplayName} - `${currentBuild.currentResult}`\n${env.BUILD_URL}")
|
||||
emailext(
|
||||
subject: "[${currentBuild.fullDisplayName}] ${currentBuild.currentResult}",
|
||||
mimeType: 'text/html',
|
||||
|
||||
+4
-4
@@ -137,9 +137,9 @@ To use the Release candidate versions of the upcoming major version, use our Mav
|
||||
</dependency>
|
||||
|
||||
<repository>
|
||||
<id>spring-libs-snapshot</id>
|
||||
<id>spring-snapshot</id>
|
||||
<name>Spring Snapshot Repository</name>
|
||||
<url>https://repo.spring.io/libs-milestone</url>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
</repository>
|
||||
----
|
||||
|
||||
@@ -154,9 +154,9 @@ If you'd rather like the latest snapshots of the upcoming major version, use our
|
||||
</dependency>
|
||||
|
||||
<repository>
|
||||
<id>spring-libs-snapshot</id>
|
||||
<id>spring-snapshot</id>
|
||||
<name>Spring Snapshot Repository</name>
|
||||
<url>https://repo.spring.io/libs-snapshot</url>
|
||||
<url>https://repo.spring.io/snapshot</url>
|
||||
</repository>
|
||||
----
|
||||
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
# Java versions
|
||||
java.main.tag=17.0.5_8-jdk-focal
|
||||
java.main.tag=17.0.7_7-jdk-focal
|
||||
java.next.tag=20-jdk-jammy
|
||||
|
||||
# Docker container images - standard
|
||||
docker.java.main.image=harbor-repo.vmware.com/dockerhub-proxy-cache/library/eclipse-temurin:${java.main.tag}
|
||||
docker.java.next.image=harbor-repo.vmware.com/dockerhub-proxy-cache/library/eclipse-temurin:${java.next.tag}
|
||||
|
||||
# Supported versions of MongoDB
|
||||
docker.mongodb.4.4.version=4.4.17
|
||||
docker.mongodb.5.0.version=5.0.13
|
||||
docker.mongodb.6.0.version=6.0.2
|
||||
docker.mongodb.4.4.version=4.4.22
|
||||
docker.mongodb.5.0.version=5.0.18
|
||||
docker.mongodb.6.0.version=6.0.7
|
||||
|
||||
# Supported versions of Redis
|
||||
docker.redis.6.version=6.2.6
|
||||
docker.redis.6.version=6.2.12
|
||||
|
||||
# Supported versions of Cassandra
|
||||
docker.cassandra.3.version=3.11.14
|
||||
docker.cassandra.3.version=3.11.15
|
||||
|
||||
# Docker environment settings
|
||||
docker.java.inside.basic=-v $HOME:/tmp/jenkins-home
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-elasticsearch</artifactId>
|
||||
<version>5.0.1</version>
|
||||
<version>5.0.8</version>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.data.build</groupId>
|
||||
<artifactId>spring-data-parent</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<version>3.0.8</version>
|
||||
</parent>
|
||||
|
||||
<name>Spring Data Elasticsearch</name>
|
||||
@@ -18,17 +18,17 @@
|
||||
<url>https://github.com/spring-projects/spring-data-elasticsearch</url>
|
||||
|
||||
<properties>
|
||||
<springdata.commons>3.0.1</springdata.commons>
|
||||
<springdata.commons>3.0.8</springdata.commons>
|
||||
|
||||
<!-- version of the RestHighLevelClient -->
|
||||
<elasticsearch-rhlc>7.17.8</elasticsearch-rhlc>
|
||||
<elasticsearch-rhlc>7.17.11</elasticsearch-rhlc>
|
||||
<!-- version of the new ElasticsearchClient -->
|
||||
<elasticsearch-java>8.5.3</elasticsearch-java>
|
||||
|
||||
<log4j>2.18.0</log4j>
|
||||
<netty>4.1.65.Final</netty>
|
||||
|
||||
<blockhound-junit>1.0.6.RELEASE</blockhound-junit>
|
||||
<blockhound-junit>1.0.7.RELEASE</blockhound-junit>
|
||||
<hoverfly>0.14.3</hoverfly>
|
||||
<jsonassert>1.5.1</jsonassert>
|
||||
<testcontainers>1.17.3</testcontainers>
|
||||
@@ -279,24 +279,6 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!--
|
||||
we don't use lombok in Spring Data Elasticsearch anymore. But the dependency is set in the parent project, and so the
|
||||
lombok compiler stuff is executed regardless of the fact that we don't need it.
|
||||
On AdoptOpenJdk 16.0.0 this leads to an error, so the project does not build.
|
||||
Therefore we replace lombok with a jar - that just contains an empty file - that lives in a local maven repository in
|
||||
src/test/resources/local-maven-repo/
|
||||
It was installed with
|
||||
mvn deploy:deploy-file -DgroupId=org.projectlombok -DartifactId=lombok -Dversion=999999 -Durl=file:./src/test/resources/local-maven-repo/ -DrepositoryId=local-maven-repo -DupdateReleaseInfo=true -Dfile=path/to/empty.jar
|
||||
-->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<!--suppress MavenPackageUpdate -->
|
||||
<version>999999</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.skyscreamer</groupId>
|
||||
<artifactId>jsonassert</artifactId>
|
||||
@@ -466,7 +448,7 @@
|
||||
<groupId>org.asciidoctor</groupId>
|
||||
<artifactId>asciidoctor-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
@@ -519,23 +501,8 @@
|
||||
</profiles>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-libs-release</id>
|
||||
<url>https://repo.spring.io/libs-release</url>
|
||||
</repository>
|
||||
|
||||
<repository>
|
||||
<id>local-maven-repo</id>
|
||||
<url>file:///${project.basedir}/src/test/resources/local-maven-repo</url>
|
||||
</repository>
|
||||
|
||||
|
||||
|
||||
</repositories>
|
||||
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>spring-plugins-release</id>
|
||||
<url>https://repo.spring.io/plugins-release</url>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -17,9 +17,9 @@ include::reference/elasticsearch-new.adoc[leveloffset=+1]
|
||||
* Version Control - https://github.com/spring-projects/spring-data-elasticsearch
|
||||
* API Documentation - https://docs.spring.io/spring-data/elasticsearch/docs/current/api/
|
||||
* Bugtracker - https://github.com/spring-projects/spring-data-elasticsearch/issues
|
||||
* Release repository - https://repo.spring.io/libs-release
|
||||
* Milestone repository - https://repo.spring.io/libs-milestone
|
||||
* Snapshot repository - https://repo.spring.io/libs-snapshot
|
||||
* Release repository - https://repo1.maven.org/maven2/
|
||||
* Milestone repository - https://repo.spring.io/milestone/
|
||||
* Snapshot repository - https://repo.spring.io/snapshot/
|
||||
|
||||
[[preface.requirements]]
|
||||
== Requirements
|
||||
|
||||
@@ -154,7 +154,7 @@ The old deprecated `RestHighLevelClient` can still be used, but you will need to
|
||||
<dependency>
|
||||
<groupId>org.elasticsearch.client</groupId>
|
||||
<artifactId>elasticsearch-rest-high-level-client</artifactId>
|
||||
<version>7.17.5</version>
|
||||
<version>7.17.11</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
@@ -165,4 +165,4 @@ The old deprecated `RestHighLevelClient` can still be used, but you will need to
|
||||
----
|
||||
====
|
||||
|
||||
Make sure to specify the version 7.17.6 explicitly, otherwise maven will resolve to 8.5.3, and this does not exist.
|
||||
Make sure to specify the version 7.17.11 explicitly, otherwise maven will resolve to 8.5.3, and this does not exist.
|
||||
|
||||
@@ -29,7 +29,7 @@ See <<elasticsearch.repositories.autocreation>>
|
||||
|
||||
|
||||
* `@Id`: Applied at the field level to mark the field used for identity purpose.
|
||||
* `@Transient`: By default all fields are mapped to the document when it is stored or retrieved, this annotation excludes the field.
|
||||
* `@Transient`, `@ReadOnlyProperty`, `@WriteOnlyProperty`: see the following section <<elasticsearch.mapping.meta-model.annotations.read-write>> for detailed information.
|
||||
* `@PersistenceConstructor`: Marks a given constructor - even a package protected one - to use when instantiating the object from the database.
|
||||
Constructor arguments are mapped by name to the key values in the retrieved Document.
|
||||
* `@Field`: Applied at the field level and defines properties of the field, most of the attributes map to the respective https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html[Elasticsearch Mapping] definitions (the following list is not complete, check the annotation Javadoc for a complete reference):
|
||||
@@ -49,6 +49,25 @@ In difference to a registered Spring `Converter` this only converts the annotate
|
||||
|
||||
The mapping metadata infrastructure is defined in a separate spring-data-commons project that is technology agnostic.
|
||||
|
||||
[[elasticsearch.mapping.meta-model.annotations.read-write]]
|
||||
==== Controlling which properties are written to and read from Elasticsearch
|
||||
|
||||
This section details the annotations that define if the value of a property is written to or
|
||||
read from Elasticsearch.
|
||||
|
||||
`@Transient`: A property annotated with this annotation will not be written to the mapping, it's value will not be
|
||||
sent to Elasticsearch and when documents are returned from Elasticsearch, this property will not be set in the
|
||||
resulting entity.
|
||||
|
||||
`@ReadOnlyProperty`: A property with this annotaiton will not have its value written to Elasticsearch, but when
|
||||
returning data, the proeprty will be filled with the value returned in the document from Elasticsearch. One use case
|
||||
for this are runtime fields defined in the index mapping.
|
||||
|
||||
`@WriteOnlyProperty`: A property with this annotaiton will have its value stored in Elasticsearch but will not be set
|
||||
with any value when reading document. This can be used for example for synthesized fields which should go into the
|
||||
Elasticsearch index but are not used elsewhere.
|
||||
|
||||
|
||||
[[elasticsearch.mapping.meta-model.annotations.date-formats]]
|
||||
==== Date format mapping
|
||||
|
||||
|
||||
+1
-1
@@ -184,7 +184,7 @@ public class NativeQueryBuilder extends BaseQueryBuilder<NativeQuery, NativeQuer
|
||||
|
||||
Assert.notNull(searchExtensions, "searchExtensions must not be null");
|
||||
|
||||
searchExtensions.putAll(searchExtensions);
|
||||
this.searchExtensions.putAll(searchExtensions);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -154,7 +154,8 @@ public class ReactiveIndicesTemplate
|
||||
|
||||
@Override
|
||||
public Mono<Void> refresh() {
|
||||
return Mono.from(execute(ReactiveElasticsearchIndicesClient::refresh)).then();
|
||||
RefreshRequest refreshRequest = requestConverter.indicesRefreshRequest(getIndexCoordinates());
|
||||
return Mono.from(execute(client -> client.refresh(refreshRequest))).then();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+18
-38
@@ -78,6 +78,7 @@ import jakarta.json.stream.JsonParser;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.StringReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
@@ -176,14 +177,12 @@ class RequestConverter {
|
||||
createRequestBuilder.index(indexCoordinates.getIndexName());
|
||||
|
||||
// note: the new client does not support the index.storeType anymore
|
||||
String settingsJson = Document.from(settings).toJson();
|
||||
IndexSettings indexSettings = fromJson(settingsJson, IndexSettings._DESERIALIZER);
|
||||
createRequestBuilder.settings(indexSettings);
|
||||
createRequestBuilder.settings(IndexSettings.of(b -> b //
|
||||
.withJson(new StringReader(Document.from(settings).toJson()))));
|
||||
|
||||
if (mapping != null) {
|
||||
String mappingJson = mapping.toJson();
|
||||
TypeMapping typeMapping = fromJson(mappingJson, TypeMapping._DESERIALIZER);
|
||||
createRequestBuilder.mappings(typeMapping);
|
||||
createRequestBuilder.mappings(TypeMapping.of(b -> b //
|
||||
.withJson(new StringReader(mapping.toJson()))));
|
||||
}
|
||||
|
||||
return createRequestBuilder.build();
|
||||
@@ -275,11 +274,12 @@ class RequestConverter {
|
||||
Assert.notNull(indexCoordinates, "indexCoordinates must not be null");
|
||||
Assert.notNull(mapping, "mapping must not be null");
|
||||
|
||||
PutMappingRequest.Builder builder = new PutMappingRequest.Builder();
|
||||
builder.index(Arrays.asList(indexCoordinates.getIndexNames()));
|
||||
addPropertiesToMapping(builder, mapping);
|
||||
PutMappingRequest request = new PutMappingRequest.Builder() //
|
||||
.withJson(new StringReader(mapping.toJson())) //
|
||||
.index(Arrays.asList(indexCoordinates.getIndexNames())) //
|
||||
.build();
|
||||
|
||||
return builder.build();
|
||||
return request;
|
||||
}
|
||||
|
||||
public GetMappingRequest indicesGetMappingRequest(IndexCoordinates indexCoordinates) {
|
||||
@@ -289,23 +289,6 @@ class RequestConverter {
|
||||
return new GetMappingRequest.Builder().index(Arrays.asList(indexCoordinates.getIndexNames())).build();
|
||||
}
|
||||
|
||||
private void addPropertiesToMapping(PutMappingRequest.Builder builder, Document mapping) {
|
||||
Object properties = mapping.get("properties");
|
||||
|
||||
if (properties != null) {
|
||||
|
||||
if (properties instanceof Map) {
|
||||
Map<String, Property> propertiesMap = new HashMap<>();
|
||||
// noinspection unchecked
|
||||
((Map<String, Object>) properties).forEach((key, value) -> {
|
||||
Property property = getProperty(value);
|
||||
propertiesMap.put(key, property);
|
||||
});
|
||||
builder.properties(propertiesMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Property getProperty(Object value) {
|
||||
// noinspection SpellCheckingInspection
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
@@ -1163,11 +1146,9 @@ class RequestConverter {
|
||||
}
|
||||
|
||||
if (!isEmpty(query.getIndicesBoost())) {
|
||||
Map<String, Double> boosts = new LinkedHashMap<>();
|
||||
query.getIndicesBoost()
|
||||
.forEach(indexBoost -> boosts.put(indexBoost.getIndexName(), (double) indexBoost.getBoost()));
|
||||
// noinspection unchecked
|
||||
bb.indicesBoost(boosts);
|
||||
bb.indicesBoost(query.getIndicesBoost().stream()
|
||||
.map(indexBoost -> Map.of(indexBoost.getIndexName(), Double.valueOf(indexBoost.getBoost())))
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
if (query instanceof NativeQuery) {
|
||||
@@ -1318,11 +1299,9 @@ class RequestConverter {
|
||||
}
|
||||
|
||||
if (!isEmpty(query.getIndicesBoost())) {
|
||||
Map<String, Double> boosts = new LinkedHashMap<>();
|
||||
query.getIndicesBoost()
|
||||
.forEach(indexBoost -> boosts.put(indexBoost.getIndexName(), (double) indexBoost.getBoost()));
|
||||
// noinspection unchecked
|
||||
builder.indicesBoost(boosts);
|
||||
builder.indicesBoost(query.getIndicesBoost().stream()
|
||||
.map(indexBoost -> Map.of(indexBoost.getIndexName(), Double.valueOf(indexBoost.getBoost())))
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1390,9 +1369,10 @@ class RequestConverter {
|
||||
return SortOptions.of(so -> so //
|
||||
.geoDistance(gd -> gd //
|
||||
.field(fieldName) //
|
||||
.location(loc -> loc.latlon(QueryBuilders.latLon(geoDistanceOrder.getGeoPoint())))//
|
||||
.location(loc -> loc.latlon(QueryBuilders.latLon(geoDistanceOrder.getGeoPoint()))) //
|
||||
.distanceType(TypeUtils.geoDistanceType(geoDistanceOrder.getDistanceType()))
|
||||
.mode(TypeUtils.sortMode(finalMode)) //
|
||||
.order(TypeUtils.sortOrder(geoDistanceOrder.getDirection())) //
|
||||
.unit(TypeUtils.distanceUnit(geoDistanceOrder.getUnit())) //
|
||||
.ignoreUnmapped(geoDistanceOrder.getIgnoreUnmapped())));
|
||||
} else {
|
||||
|
||||
@@ -27,6 +27,7 @@ import co.elastic.clients.elasticsearch.core.search.ScoreMode;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.elasticsearch.core.RefreshPolicy;
|
||||
import org.springframework.data.elasticsearch.core.query.GeoDistanceOrder;
|
||||
import org.springframework.data.elasticsearch.core.query.IndexQuery;
|
||||
@@ -136,6 +137,20 @@ final class TypeUtils {
|
||||
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static SortOrder sortOrder(@Nullable Sort.Direction direction) {
|
||||
|
||||
if (direction == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return switch (direction) {
|
||||
case ASC -> SortOrder.Asc;
|
||||
case DESC -> SortOrder.Desc;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static HighlighterFragmenter highlighterFragmenter(@Nullable String value) {
|
||||
|
||||
|
||||
@@ -963,6 +963,8 @@ class RequestFactory {
|
||||
sort.ignoreUnmapped(geoDistanceOrder.getIgnoreUnmapped());
|
||||
}
|
||||
|
||||
sort.order(order.isAscending() ? SortOrder.ASC : SortOrder.DESC);
|
||||
|
||||
return sort;
|
||||
} else {
|
||||
FieldSortBuilder sort = SortBuilders //
|
||||
|
||||
+61
-58
@@ -362,6 +362,67 @@ public abstract class AbstractElasticsearchTemplate implements ElasticsearchOper
|
||||
public abstract List<IndexedObjectInformation> doBulkOperation(List<?> queries, BulkOptions bulkOptions,
|
||||
IndexCoordinates index);
|
||||
|
||||
@Override
|
||||
public <T> UpdateResponse update(T entity) {
|
||||
|
||||
Assert.notNull(entity, "entity must not be null");
|
||||
|
||||
return update(buildUpdateQueryByEntity(entity), getIndexCoordinatesFor(entity.getClass()));
|
||||
}
|
||||
|
||||
protected <T> UpdateQuery buildUpdateQueryByEntity(T entity) {
|
||||
|
||||
Assert.notNull(entity, "entity must not be null");
|
||||
|
||||
String id = getEntityId(entity);
|
||||
Assert.notNull(id, "entity must have an id that is notnull");
|
||||
|
||||
UpdateQuery.Builder updateQueryBuilder = UpdateQuery.builder(id)
|
||||
.withDocument(elasticsearchConverter.mapObject(entity));
|
||||
|
||||
String routing = getEntityRouting(entity);
|
||||
if (StringUtils.hasText(routing)) {
|
||||
updateQueryBuilder.withRouting(routing);
|
||||
}
|
||||
|
||||
return updateQueryBuilder.build();
|
||||
}
|
||||
|
||||
protected <T> T updateIndexedObject(T entity, IndexedObjectInformation indexedObjectInformation) {
|
||||
|
||||
ElasticsearchPersistentEntity<?> persistentEntity = elasticsearchConverter.getMappingContext()
|
||||
.getPersistentEntity(entity.getClass());
|
||||
|
||||
if (persistentEntity != null) {
|
||||
PersistentPropertyAccessor<Object> propertyAccessor = persistentEntity.getPropertyAccessor(entity);
|
||||
ElasticsearchPersistentProperty idProperty = persistentEntity.getIdProperty();
|
||||
|
||||
// Only deal with text because ES generated Ids are strings!
|
||||
if (indexedObjectInformation.getId() != null && idProperty != null && idProperty.isReadable()
|
||||
&& idProperty.getType().isAssignableFrom(String.class)) {
|
||||
propertyAccessor.setProperty(idProperty, indexedObjectInformation.getId());
|
||||
}
|
||||
|
||||
if (indexedObjectInformation.getSeqNo() != null && indexedObjectInformation.getPrimaryTerm() != null
|
||||
&& persistentEntity.hasSeqNoPrimaryTermProperty()) {
|
||||
ElasticsearchPersistentProperty seqNoPrimaryTermProperty = persistentEntity.getSeqNoPrimaryTermProperty();
|
||||
// noinspection ConstantConditions
|
||||
propertyAccessor.setProperty(seqNoPrimaryTermProperty,
|
||||
new SeqNoPrimaryTerm(indexedObjectInformation.getSeqNo(), indexedObjectInformation.getPrimaryTerm()));
|
||||
}
|
||||
|
||||
if (indexedObjectInformation.getVersion() != null && persistentEntity.hasVersionProperty()) {
|
||||
ElasticsearchPersistentProperty versionProperty = persistentEntity.getVersionProperty();
|
||||
// noinspection ConstantConditions
|
||||
propertyAccessor.setProperty(versionProperty, indexedObjectInformation.getVersion());
|
||||
}
|
||||
|
||||
// noinspection unchecked
|
||||
return (T) propertyAccessor.getBean();
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region SearchOperations
|
||||
@@ -463,64 +524,6 @@ public abstract class AbstractElasticsearchTemplate implements ElasticsearchOper
|
||||
return getRequiredPersistentEntity(clazz).getIndexCoordinates();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> UpdateResponse update(T entity) {
|
||||
return update(buildUpdateQueryByEntity(entity), getIndexCoordinatesFor(entity.getClass()));
|
||||
}
|
||||
|
||||
protected <T> UpdateQuery buildUpdateQueryByEntity(T entity) {
|
||||
|
||||
Assert.notNull(entity, "entity must not be null");
|
||||
|
||||
String id = getEntityId(entity);
|
||||
Assert.notNull(id, "entity must have an id that is notnull");
|
||||
|
||||
UpdateQuery.Builder updateQueryBuilder = UpdateQuery.builder(id)
|
||||
.withDocument(elasticsearchConverter.mapObject(entity));
|
||||
|
||||
String routing = getEntityRouting(entity);
|
||||
if (StringUtils.hasText(routing)) {
|
||||
updateQueryBuilder.withRouting(routing);
|
||||
}
|
||||
|
||||
return updateQueryBuilder.build();
|
||||
}
|
||||
|
||||
protected <T> T updateIndexedObject(T entity, IndexedObjectInformation indexedObjectInformation) {
|
||||
|
||||
ElasticsearchPersistentEntity<?> persistentEntity = elasticsearchConverter.getMappingContext()
|
||||
.getPersistentEntity(entity.getClass());
|
||||
|
||||
if (persistentEntity != null) {
|
||||
PersistentPropertyAccessor<Object> propertyAccessor = persistentEntity.getPropertyAccessor(entity);
|
||||
ElasticsearchPersistentProperty idProperty = persistentEntity.getIdProperty();
|
||||
|
||||
// Only deal with text because ES generated Ids are strings!
|
||||
if (indexedObjectInformation.getId() != null && idProperty != null && idProperty.isWritable()
|
||||
&& idProperty.getType().isAssignableFrom(String.class)) {
|
||||
propertyAccessor.setProperty(idProperty, indexedObjectInformation.getId());
|
||||
}
|
||||
|
||||
if (indexedObjectInformation.getSeqNo() != null && indexedObjectInformation.getPrimaryTerm() != null
|
||||
&& persistentEntity.hasSeqNoPrimaryTermProperty()) {
|
||||
ElasticsearchPersistentProperty seqNoPrimaryTermProperty = persistentEntity.getSeqNoPrimaryTermProperty();
|
||||
// noinspection ConstantConditions
|
||||
propertyAccessor.setProperty(seqNoPrimaryTermProperty,
|
||||
new SeqNoPrimaryTerm(indexedObjectInformation.getSeqNo(), indexedObjectInformation.getPrimaryTerm()));
|
||||
}
|
||||
|
||||
if (indexedObjectInformation.getVersion() != null && persistentEntity.hasVersionProperty()) {
|
||||
ElasticsearchPersistentProperty versionProperty = persistentEntity.getVersionProperty();
|
||||
// noinspection ConstantConditions
|
||||
propertyAccessor.setProperty(versionProperty, indexedObjectInformation.getVersion());
|
||||
}
|
||||
|
||||
// noinspection unchecked
|
||||
return (T) propertyAccessor.getBean();
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
ElasticsearchPersistentEntity<?> getRequiredPersistentEntity(Class<?> clazz) {
|
||||
return elasticsearchConverter.getMappingContext().getRequiredPersistentEntity(clazz);
|
||||
}
|
||||
|
||||
+1
-1
@@ -260,7 +260,7 @@ abstract public class AbstractReactiveElasticsearchTemplate
|
||||
ElasticsearchPersistentProperty idProperty = persistentEntity.getIdProperty();
|
||||
|
||||
// Only deal with text because ES generated Ids are strings!
|
||||
if (indexedObjectInformation.getId() != null && idProperty != null && idProperty.isWritable()
|
||||
if (indexedObjectInformation.getId() != null && idProperty != null && idProperty.isReadable()
|
||||
&& idProperty.getType().isAssignableFrom(String.class)) {
|
||||
propertyAccessor.setProperty(idProperty, indexedObjectInformation.getId());
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ import org.springframework.util.Assert;
|
||||
* @author Roman Puchkovskiy
|
||||
* @author Matt Gilene
|
||||
* @author Sascha Woo
|
||||
* @author Jakob Hoeper
|
||||
* @since 4.0
|
||||
*/
|
||||
public class SearchHitMapping<T> {
|
||||
@@ -199,9 +200,10 @@ public class SearchHitMapping<T> {
|
||||
}
|
||||
|
||||
try {
|
||||
ElasticsearchPersistentEntity<?> persistentEntityForType = mappingContext.getPersistentEntity(type);
|
||||
NestedMetaData nestedMetaData = searchHits.getSearchHit(0).getContent().getNestedMetaData();
|
||||
ElasticsearchPersistentEntityWithNestedMetaData persistentEntityWithNestedMetaData = getPersistentEntity(
|
||||
mappingContext.getPersistentEntity(type), nestedMetaData);
|
||||
persistentEntityForType, nestedMetaData);
|
||||
|
||||
if (persistentEntityWithNestedMetaData.entity != null) {
|
||||
List<SearchHit<Object>> convertedSearchHits = new ArrayList<>();
|
||||
@@ -219,7 +221,8 @@ public class SearchHitMapping<T> {
|
||||
searchDocument.getSortValues(), //
|
||||
searchDocument.getHighlightFields(), //
|
||||
searchHit.getInnerHits(), //
|
||||
persistentEntityWithNestedMetaData.nestedMetaData, //
|
||||
getPersistentEntity(persistentEntityForType, //
|
||||
searchHit.getContent().getNestedMetaData()).nestedMetaData, //
|
||||
searchHit.getExplanation(), //
|
||||
searchHit.getMatchedQueries(), //
|
||||
targetObject));
|
||||
|
||||
+2
-2
@@ -349,7 +349,7 @@ public class MappingElasticsearchConverter
|
||||
PersistentPropertyAccessor<R> propertyAccessor = new ConvertingPropertyAccessor<>(
|
||||
targetEntity.getPropertyAccessor(result), conversionService);
|
||||
// Only deal with String because ES generated Ids are strings !
|
||||
if (idProperty != null && idProperty.isWritable() && idProperty.getType().isAssignableFrom(String.class)) {
|
||||
if (idProperty != null && idProperty.isReadable() && idProperty.getType().isAssignableFrom(String.class)) {
|
||||
propertyAccessor.setProperty(idProperty, document.getId());
|
||||
}
|
||||
}
|
||||
@@ -411,7 +411,7 @@ public class MappingElasticsearchConverter
|
||||
|
||||
for (ElasticsearchPersistentProperty prop : entity) {
|
||||
|
||||
if (entity.isCreatorArgument(prop) || !prop.isReadable() || !prop.isWritable()) {
|
||||
if (entity.isCreatorArgument(prop) || !prop.isReadable()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -61,7 +61,7 @@ public interface ElasticsearchPersistentProperty extends PersistentProperty<Elas
|
||||
PropertyValueConverter getPropertyValueConverter();
|
||||
|
||||
/**
|
||||
* Returns true if the property may be read.
|
||||
* Returns true if the property may be read from the store into the entity.
|
||||
*
|
||||
* @return true if readable, false otherwise
|
||||
* @since 4.0
|
||||
|
||||
+2
-1
@@ -24,6 +24,7 @@ import java.util.List;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.data.annotation.ReadOnlyProperty;
|
||||
import org.springframework.data.domain.Range;
|
||||
import org.springframework.data.elasticsearch.annotations.DateFormat;
|
||||
import org.springframework.data.elasticsearch.annotations.Field;
|
||||
@@ -119,7 +120,7 @@ public class SimpleElasticsearchPersistentProperty extends
|
||||
|
||||
@Override
|
||||
public boolean isWritable() {
|
||||
return super.isWritable() && !isSeqNoPrimaryTermProperty();
|
||||
return !isTransient() && !isSeqNoPrimaryTermProperty() && !isAnnotationPresent(ReadOnlyProperty.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -71,7 +71,7 @@ public class BaseQuery implements Query {
|
||||
protected List<RescorerQuery> rescorerQueries = new ArrayList<>();
|
||||
@Nullable protected Boolean requestCache;
|
||||
protected List<IdWithRouting> idsWithRouting = Collections.emptyList();
|
||||
protected final List<RuntimeField> runtimeFields = new ArrayList<>();
|
||||
protected List<RuntimeField> runtimeFields = new ArrayList<>();
|
||||
@Nullable protected PointInTime pointInTime;
|
||||
|
||||
private boolean queryIsUpdatedByConverter = false;
|
||||
@@ -105,6 +105,14 @@ public class BaseQuery implements Query {
|
||||
this.requestCache = builder.getRequestCache();
|
||||
this.idsWithRouting = builder.getIdsWithRouting();
|
||||
this.pointInTime = builder.getPointInTime();
|
||||
this.runtimeFields = builder.getRuntimeFields();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 5.1
|
||||
*/
|
||||
public void setSort(@Nullable Sort sort) {
|
||||
this.sort = sort;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
-1
@@ -62,6 +62,8 @@ public class ElasticsearchStringQuery extends AbstractElasticsearchRepositoryQue
|
||||
String queryString = new StringQueryUtil(elasticsearchOperations.getElasticsearchConverter().getConversionService())
|
||||
.replacePlaceholders(this.queryString, parameterAccessor);
|
||||
|
||||
return new StringQuery(queryString);
|
||||
var query = new StringQuery(queryString);
|
||||
query.addSort(parameterAccessor.getSort());
|
||||
return query;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Spring Data Elasticsearch 5.0.1 (2022.0.1)
|
||||
Spring Data Elasticsearch 5.0.8 (2022.0.8)
|
||||
Copyright (c) [2013-2021] Pivotal Software, Inc.
|
||||
|
||||
This product is licensed to you under the Apache License, Version 2.0 (the "License").
|
||||
@@ -17,3 +17,10 @@ conditions of the subcomponent's license, as noted in the LICENSE file.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2021-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.client.elc;
|
||||
|
||||
import co.elastic.clients.elasticsearch.indices.RefreshRequest;
|
||||
import co.elastic.clients.json.JsonpMapper;
|
||||
import co.elastic.clients.transport.ElasticsearchTransport;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
/**
|
||||
* @author Urs Keller
|
||||
* @since 5.0
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class ReactiveIndicesTemplateTest {
|
||||
@Mock private ElasticsearchConverter elasticsearchConverter;
|
||||
@Mock private ReactiveElasticsearchIndicesClient client;
|
||||
@Mock private ElasticsearchTransport transport;
|
||||
@Mock private JsonpMapper jsonpMapper;
|
||||
@Captor ArgumentCaptor<RefreshRequest> refreshRequest;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
doReturn(transport).when(client)._transport();
|
||||
doReturn(jsonpMapper).when(transport).jsonpMapper();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that refresh is called with the indices bound to the template
|
||||
*/
|
||||
@Test
|
||||
void refresh() {
|
||||
IndexCoordinates indexCoordinate = IndexCoordinates.of("i1", "i2");
|
||||
ReactiveIndicesTemplate template = new ReactiveIndicesTemplate(client, elasticsearchConverter, indexCoordinate);
|
||||
doReturn(Mono.empty()).when(client).refresh(any(RefreshRequest.class));
|
||||
|
||||
template.refresh().as(StepVerifier::create).verifyComplete();
|
||||
|
||||
verify(client).refresh(refreshRequest.capture());
|
||||
assertEquals(List.of("i1", "i2"), refreshRequest.getValue().index());
|
||||
|
||||
verifyNoMoreInteractions(elasticsearchConverter, client, transport, jsonpMapper);
|
||||
}
|
||||
}
|
||||
+14
-29
@@ -15,21 +15,20 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.core;
|
||||
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.assertj.core.api.Assertions.fail;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
|
||||
import static org.springframework.data.elasticsearch.annotations.Document.VersionType.EXTERNAL_GTE;
|
||||
import static java.util.Collections.*;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.*;
|
||||
import static org.springframework.data.elasticsearch.annotations.Document.VersionType.*;
|
||||
import static org.springframework.data.elasticsearch.annotations.FieldType.*;
|
||||
import static org.springframework.data.elasticsearch.annotations.FieldType.Integer;
|
||||
import static org.springframework.data.elasticsearch.annotations.FieldType.Keyword;
|
||||
import static org.springframework.data.elasticsearch.annotations.FieldType.Text;
|
||||
import static org.springframework.data.elasticsearch.core.document.Document.create;
|
||||
import static org.springframework.data.elasticsearch.core.document.Document.parse;
|
||||
import static org.springframework.data.elasticsearch.utils.IdGenerator.nextIdAsString;
|
||||
import static org.springframework.data.elasticsearch.utils.IndexBuilder.buildIndex;
|
||||
import static org.springframework.data.elasticsearch.core.document.Document.*;
|
||||
import static org.springframework.data.elasticsearch.utils.IdGenerator.*;
|
||||
import static org.springframework.data.elasticsearch.utils.IndexBuilder.*;
|
||||
|
||||
import java.lang.Double;
|
||||
import java.lang.Integer;
|
||||
import java.lang.Long;
|
||||
import java.lang.Object;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@@ -55,7 +54,6 @@ import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.dao.OptimisticLockingFailureException;
|
||||
import org.springframework.data.annotation.AccessType;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.annotation.ReadOnlyProperty;
|
||||
import org.springframework.data.annotation.Version;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
@@ -79,20 +77,7 @@ import org.springframework.data.elasticsearch.core.index.AliasActions;
|
||||
import org.springframework.data.elasticsearch.core.index.Settings;
|
||||
import org.springframework.data.elasticsearch.core.join.JoinField;
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
import org.springframework.data.elasticsearch.core.query.BaseQueryBuilder;
|
||||
import org.springframework.data.elasticsearch.core.query.Criteria;
|
||||
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.FetchSourceFilterBuilder;
|
||||
import org.springframework.data.elasticsearch.core.query.HighlightQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.IndexQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.IndexQueryBuilder;
|
||||
import org.springframework.data.elasticsearch.core.query.IndicesOptions;
|
||||
import org.springframework.data.elasticsearch.core.query.MoreLikeThisQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.Query;
|
||||
import org.springframework.data.elasticsearch.core.query.SeqNoPrimaryTerm;
|
||||
import org.springframework.data.elasticsearch.core.query.SourceFilter;
|
||||
import org.springframework.data.elasticsearch.core.query.StringQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.UpdateQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.*;
|
||||
import org.springframework.data.elasticsearch.core.query.highlight.Highlight;
|
||||
import org.springframework.data.elasticsearch.core.query.highlight.HighlightField;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.SpringIntegrationTest;
|
||||
@@ -4582,7 +4567,7 @@ public abstract class ElasticsearchIntegrationTests {
|
||||
@Field(type = FieldType.Keyword) private String part2;
|
||||
|
||||
@Id
|
||||
@ReadOnlyProperty
|
||||
@WriteOnlyProperty
|
||||
@AccessType(AccessType.Type.PROPERTY)
|
||||
public String getId() {
|
||||
return part1 + '-' + part2;
|
||||
|
||||
+10
-4
@@ -42,6 +42,7 @@ import org.springframework.lang.Nullable;
|
||||
* Testing the querying and parsing of inner_hits.
|
||||
*
|
||||
* @author Peter-Josef Meisch
|
||||
* @author Jakob Hoeper
|
||||
*/
|
||||
@SpringIntegrationTest
|
||||
public abstract class InnerHitsIntegrationTests {
|
||||
@@ -58,8 +59,9 @@ public abstract class InnerHitsIntegrationTests {
|
||||
indexOps.createWithMapping();
|
||||
|
||||
Inhabitant john = new Inhabitant("John", "Smith");
|
||||
Inhabitant carla = new Inhabitant("Carla", "Miller");
|
||||
House cornerHouse = new House("Round the corner", "7", Arrays.asList(john, carla));
|
||||
Inhabitant carla1 = new Inhabitant("Carla", "Miller");
|
||||
Inhabitant carla2 = new Inhabitant("Carla", "Nguyen");
|
||||
House cornerHouse = new House("Round the corner", "7", Arrays.asList(john, carla1, carla2));
|
||||
City metropole = new City("Metropole", Arrays.asList(cornerHouse));
|
||||
|
||||
Inhabitant jack = new Inhabitant("Jack", "Wayne");
|
||||
@@ -76,7 +78,7 @@ public abstract class InnerHitsIntegrationTests {
|
||||
operations.indexOps(IndexCoordinates.of(indexNameProvider.getPrefix() + "*")).delete();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test // #2521
|
||||
void shouldReturnInnerHits() {
|
||||
|
||||
Query query = buildQueryForInnerHits("inner_hit_name", "hou-ses.in-habi-tants", "hou-ses.in-habi-tants.first-name",
|
||||
@@ -91,7 +93,7 @@ public abstract class InnerHitsIntegrationTests {
|
||||
softly.assertThat(searchHit.getInnerHits()).hasSize(1);
|
||||
|
||||
SearchHits<?> innerHits = searchHit.getInnerHits("inner_hit_name");
|
||||
softly.assertThat(innerHits).hasSize(1);
|
||||
softly.assertThat(innerHits).hasSize(2);
|
||||
|
||||
SearchHit<?> innerHit = innerHits.getSearchHit(0);
|
||||
Object content = innerHit.getContent();
|
||||
@@ -106,6 +108,10 @@ public abstract class InnerHitsIntegrationTests {
|
||||
softly.assertThat(nestedMetaData.getChild().getField()).isEqualTo("inhabitants");
|
||||
softly.assertThat(nestedMetaData.getChild().getOffset()).isEqualTo(1);
|
||||
|
||||
innerHit = innerHits.getSearchHit(1);
|
||||
softly.assertThat(((Inhabitant) innerHit.getContent()).getLastName()).isEqualTo("Nguyen");
|
||||
softly.assertThat(innerHit.getNestedMetaData().getChild().getOffset()).isEqualTo(2);
|
||||
|
||||
softly.assertAll();
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -52,7 +52,6 @@ import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.OptimisticLockingFailureException;
|
||||
import org.springframework.data.annotation.AccessType;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.annotation.ReadOnlyProperty;
|
||||
import org.springframework.data.annotation.Version;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
@@ -63,6 +62,7 @@ import org.springframework.data.elasticsearch.annotations.Field;
|
||||
import org.springframework.data.elasticsearch.annotations.FieldType;
|
||||
import org.springframework.data.elasticsearch.annotations.Mapping;
|
||||
import org.springframework.data.elasticsearch.annotations.Setting;
|
||||
import org.springframework.data.elasticsearch.annotations.WriteOnlyProperty;
|
||||
import org.springframework.data.elasticsearch.client.erhlc.NativeSearchQuery;
|
||||
import org.springframework.data.elasticsearch.client.erhlc.NativeSearchQueryBuilder;
|
||||
import org.springframework.data.elasticsearch.client.erhlc.ReactiveElasticsearchTemplate;
|
||||
@@ -1503,7 +1503,7 @@ public abstract class ReactiveElasticsearchIntegrationTests {
|
||||
@Field(type = FieldType.Keyword) private String part2;
|
||||
|
||||
@Id
|
||||
@ReadOnlyProperty
|
||||
@WriteOnlyProperty
|
||||
@AccessType(AccessType.Type.PROPERTY)
|
||||
public String getId() {
|
||||
return part1 + '-' + part2;
|
||||
|
||||
+66
-5
@@ -17,19 +17,24 @@ package org.springframework.data.elasticsearch.core;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.elasticsearch.NewElasticsearchClientDevelopment;
|
||||
import org.springframework.data.annotation.ReadOnlyProperty;
|
||||
import org.springframework.data.elasticsearch.annotations.DateFormat;
|
||||
import org.springframework.data.elasticsearch.annotations.Document;
|
||||
import org.springframework.data.elasticsearch.annotations.Field;
|
||||
import org.springframework.data.elasticsearch.annotations.FieldType;
|
||||
import org.springframework.data.elasticsearch.annotations.Mapping;
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
import org.springframework.data.elasticsearch.core.query.Criteria;
|
||||
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.FetchSourceFilterBuilder;
|
||||
import org.springframework.data.elasticsearch.core.query.Query;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.SpringIntegrationTest;
|
||||
import org.springframework.data.elasticsearch.utils.IndexNameProvider;
|
||||
@@ -44,14 +49,13 @@ public abstract class RuntimeFieldsIntegrationTests {
|
||||
|
||||
@Autowired private ElasticsearchOperations operations;
|
||||
@Autowired protected IndexNameProvider indexNameProvider;
|
||||
private IndexOperations indexOperations;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
|
||||
indexNameProvider.increment();
|
||||
indexOperations = operations.indexOps(SomethingToBuy.class);
|
||||
indexOperations.createWithMapping();
|
||||
operations.indexOps(SomethingToBuy.class).createWithMapping();
|
||||
operations.indexOps(Person.class).createWithMapping();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -91,6 +95,24 @@ public abstract class RuntimeFieldsIntegrationTests {
|
||||
assertThat(searchHits.getSearchHit(0).getId()).isEqualTo("1");
|
||||
}
|
||||
|
||||
@Test // #2431
|
||||
@DisplayName("should return value from runtime field defined in mapping")
|
||||
void shouldReturnValueFromRuntimeFieldDefinedInMapping() {
|
||||
|
||||
var person = new Person();
|
||||
var years = 10;
|
||||
person.setBirthDate(LocalDate.now().minusDays(years * 365 + 100));
|
||||
operations.save(person);
|
||||
var query = Query.findAll();
|
||||
query.addFields("age");
|
||||
query.addSourceFilter(new FetchSourceFilterBuilder().withIncludes("*").build());
|
||||
|
||||
var searchHits = operations.search(query, Person.class);
|
||||
|
||||
assertThat(searchHits.getTotalHits()).isEqualTo(1);
|
||||
assertThat(searchHits.getSearchHit(0).getContent().getAge()).isEqualTo(years);
|
||||
}
|
||||
|
||||
private void insert(String id, String description, double price) {
|
||||
SomethingToBuy entity = new SomethingToBuy();
|
||||
entity.setId(id);
|
||||
@@ -99,7 +121,7 @@ public abstract class RuntimeFieldsIntegrationTests {
|
||||
operations.save(entity);
|
||||
}
|
||||
|
||||
@Document(indexName = "#{@indexNameProvider.indexName()}")
|
||||
@Document(indexName = "#{@indexNameProvider.indexName()}-something")
|
||||
private static class SomethingToBuy {
|
||||
private @Id @Nullable String id;
|
||||
|
||||
@@ -136,4 +158,43 @@ public abstract class RuntimeFieldsIntegrationTests {
|
||||
this.price = price;
|
||||
}
|
||||
}
|
||||
|
||||
@Document(indexName = "#{@indexNameProvider.indexName()}-person")
|
||||
@Mapping(runtimeFieldsPath = "/runtime-fields-person.json")
|
||||
public class Person {
|
||||
@Nullable private String id;
|
||||
|
||||
@Field(type = FieldType.Date, format = DateFormat.basic_date)
|
||||
@Nullable private LocalDate birthDate;
|
||||
|
||||
@ReadOnlyProperty // do not write to prevent ES from automapping
|
||||
@Nullable private Integer age;
|
||||
|
||||
@Nullable
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(@Nullable String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public LocalDate getBirthDate() {
|
||||
return birthDate;
|
||||
}
|
||||
|
||||
public void setBirthDate(@Nullable LocalDate birthDate) {
|
||||
this.birthDate = birthDate;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Integer getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(@Nullable Integer age) {
|
||||
this.age = age;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+38
-3
@@ -43,7 +43,16 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.elasticsearch.NewElasticsearchClientDevelopment;
|
||||
import org.springframework.data.elasticsearch.annotations.*;
|
||||
import org.springframework.data.elasticsearch.annotations.DateFormat;
|
||||
import org.springframework.data.elasticsearch.annotations.Document;
|
||||
import org.springframework.data.elasticsearch.annotations.Dynamic;
|
||||
import org.springframework.data.elasticsearch.annotations.Field;
|
||||
import org.springframework.data.elasticsearch.annotations.FieldType;
|
||||
import org.springframework.data.elasticsearch.annotations.InnerField;
|
||||
import org.springframework.data.elasticsearch.annotations.Mapping;
|
||||
import org.springframework.data.elasticsearch.annotations.MultiField;
|
||||
import org.springframework.data.elasticsearch.annotations.Setting;
|
||||
import org.springframework.data.elasticsearch.annotations.TermVector;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
||||
import org.springframework.data.elasticsearch.core.IndexOperations;
|
||||
import org.springframework.data.elasticsearch.core.MappingContextBaseTests;
|
||||
@@ -205,11 +214,37 @@ public abstract class MappingBuilderIntegrationTests extends MappingContextBaseT
|
||||
}
|
||||
|
||||
@Test // #1767
|
||||
@DisplayName("should write dynamic mapping annotations")
|
||||
void shouldWriteDynamicMappingAnnotations() {
|
||||
@DisplayName("should write dynamic mapping annotations on create")
|
||||
void shouldWriteDynamicMappingAnnotationsOnCreate() {
|
||||
|
||||
IndexOperations indexOps = operations.indexOps(DynamicMappingAnnotationEntity.class);
|
||||
indexOps.createWithMapping();
|
||||
|
||||
var mapping = indexOps.getMapping();
|
||||
var dynamic = mapping.get("dynamic");
|
||||
if (dynamic instanceof String s) {
|
||||
assertThat(dynamic).isEqualTo("false");
|
||||
} else {
|
||||
assertThat(mapping.get("dynamic")).isEqualTo(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Test // #2478
|
||||
@DisplayName("should write dynamic mapping annotations on put")
|
||||
void shouldWriteDynamicMappingAnnotationsOnPut() {
|
||||
|
||||
IndexOperations indexOps = operations.indexOps(DynamicMappingAnnotationEntity.class);
|
||||
indexOps.create();
|
||||
|
||||
indexOps.putMapping();
|
||||
|
||||
var mapping = indexOps.getMapping();
|
||||
var dynamic = mapping.get("dynamic");
|
||||
if (dynamic instanceof String s) {
|
||||
assertThat(dynamic).isEqualTo("false");
|
||||
} else {
|
||||
assertThat(mapping.get("dynamic")).isEqualTo(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Test // #1871
|
||||
|
||||
+35
@@ -1590,6 +1590,41 @@ public abstract class CustomMethodRepositoryIntegrationTests implements NewElast
|
||||
assertThat(searchHits.getSearchHit(2).getId()).isEqualTo("oslo");
|
||||
}
|
||||
|
||||
@Test // #2601
|
||||
void shouldUseGeoSortReverseParameter() {
|
||||
GeoPoint munich = new GeoPoint(48.137154, 11.5761247);
|
||||
GeoPoint berlin = new GeoPoint(52.520008, 13.404954);
|
||||
GeoPoint vienna = new GeoPoint(48.20849, 16.37208);
|
||||
GeoPoint oslo = new GeoPoint(59.9127, 10.7461);
|
||||
|
||||
List<SampleEntity> entities = new ArrayList<>();
|
||||
|
||||
SampleEntity entity1 = new SampleEntity();
|
||||
entity1.setId("berlin");
|
||||
entity1.setLocation(berlin);
|
||||
entities.add(entity1);
|
||||
|
||||
SampleEntity entity2 = new SampleEntity();
|
||||
entity2.setId("vienna");
|
||||
entity2.setLocation(vienna);
|
||||
entities.add(entity2);
|
||||
|
||||
SampleEntity entity3 = new SampleEntity();
|
||||
entity3.setId("oslo");
|
||||
entity3.setLocation(oslo);
|
||||
entities.add(entity3);
|
||||
|
||||
repository.saveAll(entities);
|
||||
|
||||
SearchHits<SampleEntity> searchHits = repository
|
||||
.searchBy(Sort.by(new GeoDistanceOrder("location", munich).with(Sort.Direction.DESC)));
|
||||
|
||||
assertThat(searchHits.getTotalHits()).isEqualTo(3);
|
||||
assertThat(searchHits.getSearchHit(0).getId()).isEqualTo("oslo");
|
||||
assertThat(searchHits.getSearchHit(1).getId()).isEqualTo("berlin");
|
||||
assertThat(searchHits.getSearchHit(2).getId()).isEqualTo("vienna");
|
||||
}
|
||||
|
||||
@Test // DATAES-749
|
||||
void shouldReturnSearchPage() {
|
||||
List<SampleEntity> entities = createSampleEntities("abc", 20);
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"age": {
|
||||
"type": "long",
|
||||
"script": {
|
||||
"lang": "painless",
|
||||
"source": "Instant currentDate = Instant.ofEpochMilli(new Date().getTime()); Instant startDate = doc['birthDate'].value.toInstant(); emit(ChronoUnit.DAYS.between(startDate, currentDate) / 365);"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user