1
0
mirror of synced 2026-07-05 09:40:00 +00:00

Compare commits

...

14 Commits

Author SHA1 Message Date
Jens Schauder 44b1c9e848 Release version 5.3.2 (2024.0.2).
See #2932
2024-07-12 19:09:19 +02:00
Jens Schauder 1770f98a74 Prepare 5.3.2 (2024.0.2).
See #2932
2024-07-12 19:09:01 +02:00
Peter-Josef Meisch bad0a80313 Enable use of search_after with field_collapse.
Original Pull Request #2937
Closes #2935

(cherry picked from commit dd156b9e29)
2024-07-06 11:37:51 +02:00
Peter-Josef Meisch 92dd6e8599 Update migration-guide-5.2-5.3.adoc 2024-07-04 20:58:41 +02:00
Mark Paluch c793be8ab4 Switch to Broadcom docker proxy.
Closes #2934
2024-06-20 11:21:08 +02:00
Mark Paluch 07ae79f9ce After release cleanups.
See #2913
2024-06-14 10:48:00 +02:00
Mark Paluch 47c84b84af Prepare next development iteration.
See #2913
2024-06-14 10:47:59 +02:00
Mark Paluch 5ba1e5dc77 Release version 5.3.1 (2024.0.1).
See #2913
2024-06-14 10:45:40 +02:00
Mark Paluch 5ddcd55942 Prepare 5.3.1 (2024.0.1).
See #2913
2024-06-14 10:45:24 +02:00
Peter-Josef Meisch be4a77ad21 Update nav.adoc, add loink to migration guide 5.2 to 5.3 2024-05-27 19:39:26 +02:00
Peter-Josef Meisch 7fa3cb74a1 Upgrade to Elasticsearch 8.13.4.
Original Pull Request #2917
Closes #2916
2024-05-18 18:43:34 +00:00
Peter-Josef Meisch ba9edf8ec8 Fix max dim value for dense vector.
Closes #2911

(cherry picked from commit e997b39f68)
2024-05-18 18:26:23 +02:00
Mark Paluch e4a39ae285 After release cleanups.
See #2896
2024-05-17 12:03:29 +02:00
Mark Paluch 7392222793 Prepare next development iteration.
See #2896
2024-05-17 11:51:48 +02:00
16 changed files with 187 additions and 51 deletions
Vendored
+26 -20
View File
@@ -9,7 +9,7 @@ pipeline {
triggers { triggers {
pollSCM 'H/10 * * * *' pollSCM 'H/10 * * * *'
upstream(upstreamProjects: "spring-data-commons/main", threshold: hudson.model.Result.SUCCESS) upstream(upstreamProjects: "spring-data-commons/3.3.x", threshold: hudson.model.Result.SUCCESS)
} }
options { options {
@@ -39,9 +39,11 @@ pipeline {
steps { steps {
script { script {
docker.image(p['docker.java.main.image']).inside(p['docker.java.inside.docker']) { docker.withRegistry(p['docker.proxy.registry'], p['docker.proxy.credentials']) {
sh "PROFILE=none JENKINS_USER_NAME=${p['jenkins.user.name']} ci/verify.sh" docker.image(p['docker.java.main.image']).inside(p['docker.java.inside.docker']) {
sh "JENKINS_USER_NAME=${p['jenkins.user.name']} ci/clean.sh" sh "PROFILE=none JENKINS_USER_NAME=${p['jenkins.user.name']} ci/verify.sh"
sh "JENKINS_USER_NAME=${p['jenkins.user.name']} ci/clean.sh"
}
} }
} }
} }
@@ -68,9 +70,11 @@ pipeline {
} }
steps { steps {
script { script {
docker.image(p['docker.java.next.image']).inside(p['docker.java.inside.docker']) { docker.withRegistry(p['docker.proxy.registry'], p['docker.proxy.credentials']) {
sh "PROFILE=none JENKINS_USER_NAME=${p['jenkins.user.name']} ci/verify.sh" docker.image(p['docker.java.next.image']).inside(p['docker.java.inside.docker']) {
sh "JENKINS_USER_NAME=${p['jenkins.user.name']} ci/clean.sh" sh "PROFILE=none JENKINS_USER_NAME=${p['jenkins.user.name']} ci/verify.sh"
sh "JENKINS_USER_NAME=${p['jenkins.user.name']} ci/clean.sh"
}
} }
} }
} }
@@ -97,19 +101,21 @@ pipeline {
} }
steps { steps {
script { script {
docker.image(p['docker.java.main.image']).inside(p['docker.java.inside.basic']) { docker.withRegistry(p['docker.proxy.registry'], p['docker.proxy.credentials']) {
sh 'MAVEN_OPTS="-Duser.name=' + "${p['jenkins.user.name']}" + ' -Duser.home=/tmp/jenkins-home" ' + docker.image(p['docker.java.main.image']).inside(p['docker.java.inside.basic']) {
"DEVELOCITY_CACHE_USERNAME=${DEVELOCITY_CACHE_USR} " + sh 'MAVEN_OPTS="-Duser.name=' + "${p['jenkins.user.name']}" + ' -Duser.home=/tmp/jenkins-home" ' +
"DEVELOCITY_CACHE_PASSWORD=${DEVELOCITY_CACHE_PSW} " + "DEVELOCITY_CACHE_USERNAME=${DEVELOCITY_CACHE_USR} " +
"GRADLE_ENTERPRISE_ACCESS_KEY=${DEVELOCITY_ACCESS_KEY} " + "DEVELOCITY_CACHE_PASSWORD=${DEVELOCITY_CACHE_PSW} " +
"./mvnw -s settings.xml -Pci,artifactory -Dmaven.repo.local=/tmp/jenkins-home/.m2/spring-data-elasticsearch-non-root " + "GRADLE_ENTERPRISE_ACCESS_KEY=${DEVELOCITY_ACCESS_KEY} " +
"-Dartifactory.server=${p['artifactory.url']} " + "./mvnw -s settings.xml -Pci,artifactory -Dmaven.repo.local=/tmp/jenkins-home/.m2/spring-data-elasticsearch-non-root " +
"-Dartifactory.username=${ARTIFACTORY_USR} " + "-Dartifactory.server=${p['artifactory.url']} " +
"-Dartifactory.password=${ARTIFACTORY_PSW} " + "-Dartifactory.username=${ARTIFACTORY_USR} " +
"-Dartifactory.staging-repository=${p['artifactory.repository.snapshot']} " + "-Dartifactory.password=${ARTIFACTORY_PSW} " +
"-Dartifactory.build-name=spring-data-elasticsearch " + "-Dartifactory.staging-repository=${p['artifactory.repository.snapshot']} " +
"-Dartifactory.build-number=spring-data-elasticsearch-${BRANCH_NAME}-build-${BUILD_NUMBER} " + "-Dartifactory.build-name=spring-data-elasticsearch " +
"-Dmaven.test.skip=true clean deploy -U -B" "-Dartifactory.build-number=spring-data-elasticsearch-${BRANCH_NAME}-build-${BUILD_NUMBER} " +
"-Dmaven.test.skip=true clean deploy -U -B"
}
} }
} }
} }
+5 -2
View File
@@ -3,8 +3,8 @@ java.main.tag=17.0.9_9-jdk-focal
java.next.tag=21.0.1_12-jdk-jammy java.next.tag=21.0.1_12-jdk-jammy
# Docker container images - standard # Docker container images - standard
docker.java.main.image=harbor-repo.vmware.com/dockerhub-proxy-cache/library/eclipse-temurin:${java.main.tag} docker.java.main.image=library/eclipse-temurin:${java.main.tag}
docker.java.next.image=harbor-repo.vmware.com/dockerhub-proxy-cache/library/eclipse-temurin:${java.next.tag} docker.java.next.image=library/eclipse-temurin:${java.next.tag}
# Supported versions of MongoDB # Supported versions of MongoDB
docker.mongodb.4.4.version=4.4.25 docker.mongodb.4.4.version=4.4.25
@@ -14,6 +14,7 @@ docker.mongodb.7.0.version=7.0.2
# Supported versions of Redis # Supported versions of Redis
docker.redis.6.version=6.2.13 docker.redis.6.version=6.2.13
docker.redis.7.version=7.2.4
# Supported versions of Cassandra # Supported versions of Cassandra
docker.cassandra.3.version=3.11.16 docker.cassandra.3.version=3.11.16
@@ -25,6 +26,8 @@ docker.java.inside.docker=-u root -v /var/run/docker.sock:/var/run/docker.sock -
# Credentials # Credentials
docker.registry= docker.registry=
docker.credentials=hub.docker.com-springbuildmaster docker.credentials=hub.docker.com-springbuildmaster
docker.proxy.registry=https://docker-hub.usw1.packages.broadcom.com
docker.proxy.credentials=usw1_packages_broadcom_com-jenkins-token
artifactory.credentials=02bd1690-b54f-4c9f-819d-a77cb7a9822c artifactory.credentials=02bd1690-b54f-4c9f-819d-a77cb7a9822c
artifactory.url=https://repo.spring.io artifactory.url=https://repo.spring.io
artifactory.repository.snapshot=libs-snapshot-local artifactory.repository.snapshot=libs-snapshot-local
+4 -4
View File
@@ -5,12 +5,12 @@
<groupId>org.springframework.data</groupId> <groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId> <artifactId>spring-data-elasticsearch</artifactId>
<version>5.3.0</version> <version>5.3.2</version>
<parent> <parent>
<groupId>org.springframework.data.build</groupId> <groupId>org.springframework.data.build</groupId>
<artifactId>spring-data-parent</artifactId> <artifactId>spring-data-parent</artifactId>
<version>3.3.0</version> <version>3.3.2</version>
</parent> </parent>
<name>Spring Data Elasticsearch</name> <name>Spring Data Elasticsearch</name>
@@ -18,10 +18,10 @@
<url>https://github.com/spring-projects/spring-data-elasticsearch</url> <url>https://github.com/spring-projects/spring-data-elasticsearch</url>
<properties> <properties>
<springdata.commons>3.3.0</springdata.commons> <springdata.commons>3.3.2</springdata.commons>
<!-- version of the ElasticsearchClient --> <!-- version of the ElasticsearchClient -->
<elasticsearch-java>8.13.2</elasticsearch-java> <elasticsearch-java>8.13.4</elasticsearch-java>
<blockhound-junit>1.0.8.RELEASE</blockhound-junit> <blockhound-junit>1.0.8.RELEASE</blockhound-junit>
<hoverfly>0.14.4</hoverfly> <hoverfly>0.14.4</hoverfly>
+1 -1
View File
@@ -9,7 +9,7 @@
*** xref:migration-guides/migration-guide-4.4-5.0.adoc[] *** xref:migration-guides/migration-guide-4.4-5.0.adoc[]
*** xref:migration-guides/migration-guide-5.0-5.1.adoc[] *** xref:migration-guides/migration-guide-5.0-5.1.adoc[]
*** xref:migration-guides/migration-guide-5.1-5.2.adoc[] *** xref:migration-guides/migration-guide-5.1-5.2.adoc[]
*** xref:migration-guides/migration-guide-5.2-5.3.adoc[]
* xref:elasticsearch.adoc[] * xref:elasticsearch.adoc[]
** xref:elasticsearch/clients.adoc[] ** xref:elasticsearch/clients.adoc[]
@@ -1,6 +1,11 @@
[[new-features]] [[new-features]]
= What's new = What's new
[[new-features.5-3-1]]
== New in Spring Data Elasticsearch 5.3.1
* Upgrade to Elasticsearch 8.13.4.
[[new-features.5-3-0]] [[new-features.5-3-0]]
== New in Spring Data Elasticsearch 5.3 == New in Spring Data Elasticsearch 5.3
@@ -6,7 +6,7 @@ The following table shows the Elasticsearch and Spring versions that are used by
[cols="^,^,^,^",options="header"] [cols="^,^,^,^",options="header"]
|=== |===
| Spring Data Release Train | Spring Data Elasticsearch | Elasticsearch | Spring Framework | Spring Data Release Train | Spring Data Elasticsearch | Elasticsearch | Spring Framework
| 2024.0 (?) | 5.3.x | 8.13.2 | ? | 2024.0 | 5.3.1 | 8.13.4 | 6.1.x
| 2023.1 (Vaughan) | 5.2.x | 8.11.1 | 6.1.x | 2023.1 (Vaughan) | 5.2.x | 8.11.1 | 6.1.x
| 2023.0 (Ullmann) | 5.1.x | 8.7.1 | 6.0.x | 2023.0 (Ullmann) | 5.1.x | 8.7.1 | 6.0.x
| 2022.0 (Turing) | 5.0.xfootnote:oom[Out of maintenance] | 8.5.3 | 6.0.x | 2022.0 (Turing) | 5.0.xfootnote:oom[Out of maintenance] | 8.5.3 | 6.0.x
@@ -5,7 +5,10 @@ This section describes breaking changes from version 5.2.x to 5.3.x and how remo
[[elasticsearch-migration-guide-5.2-5.3.breaking-changes]] [[elasticsearch-migration-guide-5.2-5.3.breaking-changes]]
== Breaking Changes == Breaking Changes
During the parameter replacement in `@Query` annotated repository methods previous versions wrote the String _"null"_ into the query that was sent to Elasticsearch
when the actual parameter value was `null`. As Elasticsearch does not store `null` values, this behaviour could lead to problems, for example whent the fields to be
searched contains the string `"null"`. In Version 5.3 a `null` value in a parameter will cause a `ConversionException` to be thrown. If you are using `"null"` as the
`null_value` defined in a field mapping, then pass that string into the query instead of a Java `null`.
[[elasticsearch-migration-guide-5.2-5.3.deprecations]] [[elasticsearch-migration-guide-5.2-5.3.deprecations]]
== Deprecations == Deprecations
@@ -16,6 +16,7 @@
package org.springframework.data.elasticsearch.client.elc; package org.springframework.data.elasticsearch.client.elc;
import co.elastic.clients.elasticsearch._types.KnnQuery; import co.elastic.clients.elasticsearch._types.KnnQuery;
import co.elastic.clients.elasticsearch._types.KnnSearch;
import co.elastic.clients.elasticsearch._types.SortOptions; import co.elastic.clients.elasticsearch._types.SortOptions;
import co.elastic.clients.elasticsearch._types.aggregations.Aggregation; import co.elastic.clients.elasticsearch._types.aggregations.Aggregation;
import co.elastic.clients.elasticsearch._types.query_dsl.Query; import co.elastic.clients.elasticsearch._types.query_dsl.Query;
@@ -54,6 +55,7 @@ public class NativeQuery extends BaseQuery {
private Map<String, JsonData> searchExtensions = Collections.emptyMap(); private Map<String, JsonData> searchExtensions = Collections.emptyMap();
@Nullable private KnnQuery knnQuery; @Nullable private KnnQuery knnQuery;
@Nullable private List<KnnSearch> knnSearches = Collections.emptyList();
public NativeQuery(NativeQueryBuilder builder) { public NativeQuery(NativeQueryBuilder builder) {
super(builder); super(builder);
@@ -71,6 +73,7 @@ public class NativeQuery extends BaseQuery {
} }
this.springDataQuery = builder.getSpringDataQuery(); this.springDataQuery = builder.getSpringDataQuery();
this.knnQuery = builder.getKnnQuery(); this.knnQuery = builder.getKnnQuery();
this.knnSearches = builder.getKnnSearches();
} }
public NativeQuery(@Nullable Query query) { public NativeQuery(@Nullable Query query) {
@@ -129,6 +132,14 @@ public class NativeQuery extends BaseQuery {
return knnQuery; return knnQuery;
} }
/**
* @since 5.3.1
*/
@Nullable
public List<KnnSearch> getKnnSearches() {
return knnSearches;
}
@Nullable @Nullable
public org.springframework.data.elasticsearch.core.query.Query getSpringDataQuery() { public org.springframework.data.elasticsearch.core.query.Query getSpringDataQuery() {
return springDataQuery; return springDataQuery;
@@ -16,6 +16,7 @@
package org.springframework.data.elasticsearch.client.elc; package org.springframework.data.elasticsearch.client.elc;
import co.elastic.clients.elasticsearch._types.KnnQuery; import co.elastic.clients.elasticsearch._types.KnnQuery;
import co.elastic.clients.elasticsearch._types.KnnSearch;
import co.elastic.clients.elasticsearch._types.SortOptions; import co.elastic.clients.elasticsearch._types.SortOptions;
import co.elastic.clients.elasticsearch._types.aggregations.Aggregation; import co.elastic.clients.elasticsearch._types.aggregations.Aggregation;
import co.elastic.clients.elasticsearch._types.query_dsl.Query; import co.elastic.clients.elasticsearch._types.query_dsl.Query;
@@ -26,6 +27,7 @@ import co.elastic.clients.util.ObjectBuilder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -52,6 +54,7 @@ public class NativeQueryBuilder extends BaseQueryBuilder<NativeQuery, NativeQuer
@Nullable private org.springframework.data.elasticsearch.core.query.Query springDataQuery; @Nullable private org.springframework.data.elasticsearch.core.query.Query springDataQuery;
@Nullable private KnnQuery knnQuery; @Nullable private KnnQuery knnQuery;
@Nullable private List<KnnSearch> knnSearches = Collections.emptyList();
public NativeQueryBuilder() {} public NativeQueryBuilder() {}
@@ -92,6 +95,14 @@ public class NativeQueryBuilder extends BaseQueryBuilder<NativeQuery, NativeQuer
return knnQuery; return knnQuery;
} }
/**
* @since 5.3.1
*/
@Nullable
public List<KnnSearch> getKnnSearches() {
return knnSearches;
}
@Nullable @Nullable
public org.springframework.data.elasticsearch.core.query.Query getSpringDataQuery() { public org.springframework.data.elasticsearch.core.query.Query getSpringDataQuery() {
return springDataQuery; return springDataQuery;
@@ -395,7 +395,28 @@ public class ReactiveElasticsearchTemplate extends AbstractReactiveElasticsearch
Function<PitSearchAfter, Publisher<? extends ResponseBody<EntityAsMap>>> resourceClosure = psa -> { Function<PitSearchAfter, Publisher<? extends ResponseBody<EntityAsMap>>> resourceClosure = psa -> {
baseQuery.setPointInTime(new Query.PointInTime(psa.getPit(), pitKeepAlive)); baseQuery.setPointInTime(new Query.PointInTime(psa.getPit(), pitKeepAlive));
baseQuery.addSort(Sort.by("_shard_doc"));
// only add _shard_doc if there is not a field_collapse and a sort with the same name
boolean addShardDoc = true;
if (query instanceof NativeQuery nativeQuery && nativeQuery.getFieldCollapse() != null) {
var field = nativeQuery.getFieldCollapse().field();
if (nativeQuery.getSortOptions().stream()
.anyMatch(sortOptions -> sortOptions.isField() && sortOptions.field().field().equals(field))) {
addShardDoc = false;
}
if (query.getSort() != null
&& query.getSort().stream().anyMatch(order -> order.getProperty().equals(field))) {
addShardDoc = false;
}
}
if (addShardDoc) {
baseQuery.addSort(Sort.by("_shard_doc"));
}
SearchRequest firstSearchRequest = requestConverter.searchRequest(baseQuery, routingResolver.getRouting(), SearchRequest firstSearchRequest = requestConverter.searchRequest(baseQuery, routingResolver.getRouting(),
clazz, index, false, true); clazz, index, false, true);
@@ -1477,8 +1477,8 @@ class RequestConverter extends AbstractQueryProcessor {
if (query instanceof NativeQuery nativeQuery) { if (query instanceof NativeQuery nativeQuery) {
prepareNativeSearch(nativeQuery, builder); prepareNativeSearch(nativeQuery, builder);
} }
// query.getSort() must be checked after prepareNativeSearch as this already might hav a sort set that must have // query.getSort() must be checked after prepareNativeSearch as this already might have a sort set
// higher priority // that must have higher priority
if (query.getSort() != null) { if (query.getSort() != null) {
List<SortOptions> sortOptions = getSortOptions(query.getSort(), persistentEntity); List<SortOptions> sortOptions = getSortOptions(query.getSort(), persistentEntity);
@@ -1500,7 +1500,15 @@ class RequestConverter extends AbstractQueryProcessor {
} }
if (!isEmpty(query.getSearchAfter())) { if (!isEmpty(query.getSearchAfter())) {
builder.searchAfter(query.getSearchAfter().stream().map(TypeUtils::toFieldValue).toList()); var fieldValues = query.getSearchAfter().stream().map(TypeUtils::toFieldValue).toList();
// when there is a field collapse on a native query, and we have a search_after, then the search_after
// must only have one entry
if (query instanceof NativeQuery nativeQuery && nativeQuery.getFieldCollapse() != null) {
builder.searchAfter(fieldValues.get(0));
} else {
builder.searchAfter(fieldValues);
}
} }
query.getRescorerQueries().forEach(rescorerQuery -> builder.rescore(getRescore(rescorerQuery))); query.getRescorerQueries().forEach(rescorerQuery -> builder.rescore(getRescore(rescorerQuery)));
@@ -1719,7 +1727,18 @@ class RequestConverter extends AbstractQueryProcessor {
; ;
if (query.getKnnQuery() != null) { if (query.getKnnQuery() != null) {
builder.knn(query.getKnnQuery()); var kq = query.getKnnQuery();
builder.knn(ksb -> ksb
.field(kq.field())
.queryVector(kq.queryVector())
.numCandidates(kq.numCandidates())
.filter(kq.filter())
.similarity(kq.similarity()));
}
if (!isEmpty(query.getKnnSearches())) {
builder.knn(query.getKnnSearches());
} }
if (!isEmpty(query.getAggregations())) { if (!isEmpty(query.getAggregations())) {
@@ -1740,7 +1759,18 @@ class RequestConverter extends AbstractQueryProcessor {
.sort(query.getSortOptions()); .sort(query.getSortOptions());
if (query.getKnnQuery() != null) { if (query.getKnnQuery() != null) {
builder.knn(query.getKnnQuery()); var kq = query.getKnnQuery();
builder.knn(ksb -> ksb
.field(kq.field())
.queryVector(kq.queryVector())
.numCandidates(kq.numCandidates())
.filter(kq.filter())
.similarity(kq.similarity()));
}
if (!isEmpty(query.getKnnSearches())) {
builder.knn(query.getKnnSearches());
} }
if (!isEmpty(query.getAggregations())) { if (!isEmpty(query.getAggregations())) {
@@ -171,8 +171,8 @@ public final class MappingParameters {
positiveScoreImpact = field.positiveScoreImpact(); positiveScoreImpact = field.positiveScoreImpact();
dims = field.dims(); dims = field.dims();
if (type == FieldType.Dense_Vector) { if (type == FieldType.Dense_Vector) {
Assert.isTrue(dims >= 1 && dims <= 2048, Assert.isTrue(dims >= 1 && dims <= 4096,
"Invalid required parameter! Dense_Vector value \"dims\" must be between 1 and 2048."); "Invalid required parameter! Dense_Vector value \"dims\" must be between 1 and 4096.");
} }
Assert.isTrue(field.enabled() || type == FieldType.Object, "enabled false is only allowed for field type object"); Assert.isTrue(field.enabled() || type == FieldType.Object, "enabled false is only allowed for field type object");
enabled = field.enabled(); enabled = field.enabled();
@@ -214,8 +214,8 @@ public final class MappingParameters {
positiveScoreImpact = field.positiveScoreImpact(); positiveScoreImpact = field.positiveScoreImpact();
dims = field.dims(); dims = field.dims();
if (type == FieldType.Dense_Vector) { if (type == FieldType.Dense_Vector) {
Assert.isTrue(dims >= 1 && dims <= 2048, Assert.isTrue(dims >= 1 && dims <= 4096,
"Invalid required parameter! Dense_Vector value \"dims\" must be between 1 and 2048."); "Invalid required parameter! Dense_Vector value \"dims\" must be between 1 and 4096.");
} }
enabled = true; enabled = true;
eagerGlobalOrdinals = field.eagerGlobalOrdinals(); eagerGlobalOrdinals = field.eagerGlobalOrdinals();
+3 -1
View File
@@ -1,4 +1,4 @@
Spring Data Elasticsearch 5.3 GA (2024.0.0) Spring Data Elasticsearch 5.3.2 (2024.0.2)
Copyright (c) [2013-2022] Pivotal Software, Inc. Copyright (c) [2013-2022] Pivotal Software, Inc.
This product is licensed to you under the Apache License, Version 2.0 (the "License"). This product is licensed to you under the Apache License, Version 2.0 (the "License").
@@ -22,3 +22,5 @@ conditions of the subcomponent's license, as noted in the LICENSE file.
@@ -70,8 +70,8 @@ public class MappingParametersTest extends MappingContextBaseTests {
} }
@Test // #1700 @Test // #1700
@DisplayName("should not allow dims length greater than 2048 for dense_vector type") @DisplayName("should not allow dims length greater than 4096 for dense_vector type")
void shouldNotAllowDimsLengthGreaterThan2048ForDenseVectorType() { void shouldNotAllowDimsLengthGreaterThan4096ForDenseVectorType() {
ElasticsearchPersistentEntity<?> failEntity = elasticsearchConverter.get().getMappingContext() ElasticsearchPersistentEntity<?> failEntity = elasticsearchConverter.get().getMappingContext()
.getRequiredPersistentEntity(DenseVectorInvalidDimsClass.class); .getRequiredPersistentEntity(DenseVectorInvalidDimsClass.class);
Annotation annotation = failEntity.getRequiredPersistentProperty("dense_vector").findAnnotation(Field.class); Annotation annotation = failEntity.getRequiredPersistentProperty("dense_vector").findAnnotation(Field.class);
@@ -90,21 +90,28 @@ public class MappingParametersTest extends MappingContextBaseTests {
} }
static class AnnotatedClass { static class AnnotatedClass {
@Nullable @Field private String field; @Nullable
@Nullable @MultiField(mainField = @Field, @Field private String field;
@Nullable
@MultiField(mainField = @Field,
otherFields = { @InnerField(suffix = "test", type = FieldType.Text) }) private String mainField; otherFields = { @InnerField(suffix = "test", type = FieldType.Text) }) private String mainField;
@Nullable @Field(type = FieldType.Text, docValues = false) private String docValuesText; @Nullable
@Nullable @Field(type = FieldType.Nested, docValues = false) private String docValuesNested; @Field(type = FieldType.Text, docValues = false) private String docValuesText;
@Nullable @Field(type = Object, enabled = true) private String enabledObject; @Nullable
@Nullable @Field(type = Object, enabled = false) private String disabledObject; @Field(type = FieldType.Nested, docValues = false) private String docValuesNested;
@Nullable
@Field(type = Object, enabled = true) private String enabledObject;
@Nullable
@Field(type = Object, enabled = false) private String disabledObject;
} }
static class InvalidEnabledFieldClass { static class InvalidEnabledFieldClass {
@Nullable @Field(type = FieldType.Text, enabled = false) private String disabledObject; @Nullable
@Field(type = FieldType.Text, enabled = false) private String disabledObject;
} }
static class DenseVectorInvalidDimsClass { static class DenseVectorInvalidDimsClass {
@Field(type = Dense_Vector, dims = 2049) private float[] dense_vector; @Field(type = Dense_Vector, dims = 4097) private float[] dense_vector;
} }
static class DenseVectorMissingDimsClass { static class DenseVectorMissingDimsClass {
@@ -15,14 +15,22 @@
*/ */
package org.springframework.data.elasticsearch.repository.support; package org.springframework.data.elasticsearch.repository.support;
import co.elastic.clients.elasticsearch.core.search.FieldCollapse;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.client.elc.NativeQuery;
import org.springframework.data.elasticsearch.client.elc.Queries;
import org.springframework.data.elasticsearch.junit.jupiter.ReactiveElasticsearchTemplateConfiguration; import org.springframework.data.elasticsearch.junit.jupiter.ReactiveElasticsearchTemplateConfiguration;
import org.springframework.data.elasticsearch.repositories.custommethod.QueryParameter; import org.springframework.data.elasticsearch.repositories.custommethod.QueryParameter;
import org.springframework.data.elasticsearch.repository.config.EnableReactiveElasticsearchRepositories; import org.springframework.data.elasticsearch.repository.config.EnableReactiveElasticsearchRepositories;
import org.springframework.data.elasticsearch.utils.IndexNameProvider; import org.springframework.data.elasticsearch.utils.IndexNameProvider;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfiguration;
import reactor.test.StepVerifier;
/** /**
* @author Peter-Josef Meisch * @author Peter-Josef Meisch
@@ -51,4 +59,33 @@ public class SimpleReactiveElasticsearchRepositoryELCIntegrationTests
} }
} }
/**
* search_after is used by the reactive search operation, it normally always adds _shard_doc as a tiebreaker sort
* parameter. This must not be done when a collapse field is used as sort field, as in that case the collapse field
* must be the only sort field.
*/
@Test // #2935
@DisplayName("should use collapse_field for search_after in pit search")
void shouldUseCollapseFieldForSearchAfterI() {
var entity = new SampleEntity();
entity.setId("42");
entity.setMessage("m");
entity.setKeyword("kw");
repository.save(entity).block();
var query = NativeQuery.builder()
.withQuery(Queries.matchAllQueryAsQuery())
.withPageable(Pageable.unpaged())
.withFieldCollapse(FieldCollapse.of(fcb -> fcb
.field("keyword")))
.withSort(Sort.by("keyword"))
.build();
operations.search(query, SampleEntity.class)
.as(StepVerifier::create)
.expectNextCount(1)
.verifyComplete();
}
} }
@@ -15,7 +15,7 @@
# #
# #
sde.testcontainers.image-name=docker.elastic.co/elasticsearch/elasticsearch sde.testcontainers.image-name=docker.elastic.co/elasticsearch/elasticsearch
sde.testcontainers.image-version=8.13.2 sde.testcontainers.image-version=8.13.4
# #
# #
# needed as we do a DELETE /* at the end of the tests, will be required from 8.0 on, produces a warning since 7.13 # needed as we do a DELETE /* at the end of the tests, will be required from 8.0 on, produces a warning since 7.13