1
0
mirror of synced 2026-07-05 17:50:00 +00:00

Compare commits

...

43 Commits

Author SHA1 Message Date
Mark Paluch 6faa70b0b2 Release version 5.5.7 (2025.0.7).
See #3196
2025-12-12 11:42:28 +01:00
Mark Paluch 0bcbc45373 Prepare 5.5.7 (2025.0.7).
See #3196
2025-12-12 11:42:06 +01:00
Mark Paluch 79321965f8 Update CI Properties.
See #3196
2025-12-10 08:34:38 +01:00
Mark Paluch e1f81f0c42 Add docker-java.properties.
See spring-projects/spring-data-build#2726
2025-12-04 09:00:50 +01:00
Mark Paluch 983e0e552c After release cleanups.
See #3185
2025-11-14 11:33:16 +01:00
Mark Paluch d9028609a8 Prepare next development iteration.
See #3185
2025-11-14 11:33:15 +01:00
Mark Paluch 3e2b114c5d Release version 5.5.6 (2025.0.6).
See #3185
2025-11-14 11:30:08 +01:00
Mark Paluch 6662e29aa5 Prepare 5.5.6 (2025.0.6).
See #3185
2025-11-14 11:29:46 +01:00
Mark Paluch 0b9cfca28f Update Update security documentation.
See #3185
2025-11-14 10:43:24 +01:00
Christoph Strobl f985e1efe5 After release cleanups.
See #3170
2025-10-17 11:39:06 +02:00
Christoph Strobl 8f6fca5b43 Prepare next development iteration.
See #3170
2025-10-17 11:39:05 +02:00
Christoph Strobl 0471b54d3b Release version 5.5.5 (2025.0.5).
See #3170
2025-10-17 11:34:13 +02:00
Christoph Strobl 1302c14920 Prepare 5.5.5 (2025.0.5).
See #3170
2025-10-17 11:33:06 +02:00
Peter-Josef Meisch 66894a5b0e Upgrade to Elasticsearch 8.18.8.
Original Pull Request #3183
Closes #3181
Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-10-17 00:09:34 +02:00
Peter-Josef Meisch 00c99852fa Fix string comparison in TypeUtils.
Original Pull Request #3177
Closes #3176
Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
(cherry picked from commit 0e1a97a27a)
2025-10-03 10:51:43 +02:00
Mark Paluch 4152378d32 Update GitHub Actions.
See #3170
2025-09-23 10:51:47 +02:00
Peter-Josef Meisch 3fca4e8be3 Adjust test to slower performance of build machines in Jenkins
Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
(cherry picked from commit 5529af8f76)
2025-09-20 20:42:54 +02:00
Peter-Josef Meisch 91f3393abc Speedup Criteria hashcode calculation
Original Pull Request #3172
Closes #3083
Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
(cherry picked from commit c0dd082f4e)
2025-09-20 19:52:33 +02:00
Christoph Strobl eee009fc18 After release cleanups.
See #3153
2025-09-12 11:45:34 +02:00
Christoph Strobl e394464724 Prepare next development iteration.
See #3153
2025-09-12 11:45:33 +02:00
Christoph Strobl 47815a69fb Release version 5.5.4 (2025.0.4).
See #3153
2025-09-12 11:41:39 +02:00
Christoph Strobl 01ca42fd2e Prepare 5.5.4 (2025.0.4).
See #3153
2025-09-12 11:41:09 +02:00
Mark Paluch 604c88b6a4 Polishing.
Update project metadata, add PJ as project lead (long overdue).

See #3154
2025-09-12 11:39:50 +02:00
Peter-Josef Meisch ed05313b17 Upgrade to Elasticsearch 8.18.6.
Original Pull Request #3164
Closes #3160

Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-08-31 17:05:14 +02:00
Mark Paluch 822843a93a Refine version properties for documentation build.
See spring-projects/spring-data-build#2638
2025-08-18 09:16:40 +02:00
Mark Paluch 7f7731acdc After release cleanups.
See #3134
2025-08-15 10:04:17 +02:00
Mark Paluch a0ee571cc7 Prepare next development iteration.
See #3134
2025-08-15 10:04:16 +02:00
Mark Paluch 5bbccbf9d0 Release version 5.5.3 (2025.0.3).
See #3134
2025-08-15 10:01:35 +02:00
Mark Paluch 19af94f87e Prepare 5.5.3 (2025.0.3).
See #3134
2025-08-15 10:01:14 +02:00
Mark Paluch 71a3e24096 Polishing.
Use documentation variables for references, reorder antora keys.

See #3135
2025-08-14 17:28:01 +02:00
Peter-Josef Meisch 23eacd4d4b Upgrade to Elasticsearch 8.18.5.
Original Pull Request #3151
Closes #3149
Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
2025-08-12 18:39:04 +02:00
Mark Paluch 56bda34666 After release cleanups.
See #3120
2025-07-18 10:30:34 +02:00
Mark Paluch 76ba2324a2 Prepare next development iteration.
See #3120
2025-07-18 10:30:33 +02:00
Mark Paluch 4c217fa9c4 Release version 5.5.2 (2025.0.2).
See #3120
2025-07-18 10:27:59 +02:00
Mark Paluch 003213d4b0 Prepare 5.5.2 (2025.0.2).
See #3120
2025-07-18 10:27:38 +02:00
Mark Paluch 85d52014dc Upgrade to Maven Wrapper 3.9.11.
See #3131
2025-07-17 14:00:55 +02:00
Peter-Josef Meisch 786e0928ed Fix the calculation of the requested number of documents.
Original Pull Request #3128
Closes #3127

Signed-off-by: Peter-Josef Meisch <pj.meisch@sothawo.com>
(cherry picked from commit 12ddb74fae)
2025-07-15 18:41:17 +02:00
Mark Paluch ef6f091d6b After release cleanups.
See #3114
2025-06-13 13:42:19 +02:00
Mark Paluch 9ff829a829 Prepare next development iteration.
See #3114
2025-06-13 13:42:18 +02:00
Mark Paluch 30f32b6bbe Release version 5.5.1 (2025.0.1).
See #3114
2025-06-13 13:39:35 +02:00
Mark Paluch 8ce113a083 Prepare 5.5.1 (2025.0.1).
See #3114
2025-06-13 13:39:14 +02:00
Mark Paluch 262781c0a0 After release cleanups.
See #3096
2025-05-16 11:31:36 +02:00
Mark Paluch ffe8293365 Prepare next development iteration.
See #3096
2025-05-16 11:31:35 +02:00
22 changed files with 414 additions and 95 deletions
+21
View File
@@ -0,0 +1,21 @@
# GitHub Actions for CodeQL Scanning
name: "CodeQL Advanced"
on:
push:
pull_request:
workflow_dispatch:
schedule:
# https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#schedule
- cron: '0 5 * * *'
permissions: read-all
jobs:
codeql-analysis-call:
permissions:
actions: read
contents: read
security-events: write
uses: spring-io/github-actions/.github/workflows/codeql-analysis.yml@1
+45
View File
@@ -0,0 +1,45 @@
# GitHub Actions to automate GitHub issues for Spring Data Project Management
name: Spring Data GitHub Issues
on:
issues:
types: [opened, edited, reopened]
issue_comment:
types: [created]
pull_request_target:
types: [opened, edited, reopened]
permissions:
contents: read
issues: write
pull-requests: write
jobs:
Inbox:
runs-on: ubuntu-latest
if: github.repository_owner == 'spring-projects' && (github.event.action == 'opened' || github.event.action == 'reopened') && github.event.pull_request == null && !contains(join(github.event.issue.labels.*.name, ', '), 'dependency-upgrade') && !contains(github.event.issue.title, 'Release ')
steps:
- name: Create or Update Issue Card
uses: actions/add-to-project@v1.0.2
with:
project-url: https://github.com/orgs/spring-projects/projects/25
github-token: ${{ secrets.GH_ISSUES_TOKEN_SPRING_DATA }}
Pull-Request:
runs-on: ubuntu-latest
if: github.repository_owner == 'spring-projects' && (github.event.action == 'opened' || github.event.action == 'reopened') && github.event.pull_request != null
steps:
- name: Create or Update Pull Request Card
uses: actions/add-to-project@v1.0.2
with:
project-url: https://github.com/orgs/spring-projects/projects/25
github-token: ${{ secrets.GH_ISSUES_TOKEN_SPRING_DATA }}
Feedback-Provided:
runs-on: ubuntu-latest
if: github.repository_owner == 'spring-projects' && github.event_name == 'issue_comment' && github.event.action == 'created' && github.actor != 'spring-projects-issues' && github.event.pull_request == null && github.event.issue.state == 'open' && contains(toJSON(github.event.issue.labels), 'waiting-for-feedback')
steps:
- name: Update Project Card
uses: actions/add-to-project@v1.0.2
with:
project-url: https://github.com/orgs/spring-projects/projects/25
github-token: ${{ secrets.GH_ISSUES_TOKEN_SPRING_DATA }}
+2 -2
View File
@@ -1,3 +1,3 @@
#Thu Nov 07 09:47:28 CET 2024 #Thu Jul 17 14:00:55 CEST 2025
wrapperUrl=https\://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar wrapperUrl=https\://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
distributionUrl=https\://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip distributionUrl=https\://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip
Vendored
+1 -1
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.5.x", threshold: hudson.model.Result.SUCCESS)
} }
options { options {
+11 -5
View File
@@ -1,9 +1,15 @@
# Security Policy = Security Policy
## Supported Versions == Reporting a Vulnerability
Please see the https://spring.io/projects/spring-data-elasticsearch[Spring Data Elasticsearch] project page for supported versions. Please, https://github.com/spring-projects/security-advisories/security/advisories/new[open a draft security advisory] if you need to disclose and discuss a security issue in private with the Spring Data team.
Note that we only accept reports against https://spring.io/projects/spring-data#support[supported versions].
## Reporting a Vulnerability For more details, check out our https://spring.io/security-policy[security policy].
Please don't raise security vulnerabilities here. Head over to https://pivotal.io/security to learn how to disclose them responsibly. == JAR signing
Spring Data JARs released on Maven Central are signed.
You'll find more information about the key here: https://spring.io/GPG-KEY-spring.txt
Versions released prior to 2023 may be signed with a different key.
+2 -2
View File
@@ -17,8 +17,8 @@ docker.redis.7.version=7.2.4
docker.valkey.8.version=8.1.1 docker.valkey.8.version=8.1.1
# Docker environment settings # Docker environment settings
docker.java.inside.basic=-v $HOME:/tmp/jenkins-home docker.java.inside.basic=-v $HOME:/tmp/jenkins-home --ulimit nofile=32000:32000
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 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 --ulimit nofile=32000:32000
# Credentials # Credentials
docker.registry= docker.registry=
+14 -10
View File
@@ -1,16 +1,16 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.data</groupId> <groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId> <artifactId>spring-data-elasticsearch</artifactId>
<version>5.5.0</version> <version>5.5.7</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.5.0</version> <version>3.5.7</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.5.0</springdata.commons> <springdata.commons>3.5.7</springdata.commons>
<!-- version of the ElasticsearchClient --> <!-- version of the ElasticsearchClient -->
<elasticsearch-java>8.18.1</elasticsearch-java> <elasticsearch-java>8.18.8</elasticsearch-java>
<hoverfly>0.19.0</hoverfly> <hoverfly>0.19.0</hoverfly>
<log4j>2.23.1</log4j> <log4j>2.23.1</log4j>
@@ -41,6 +41,15 @@
</properties> </properties>
<developers> <developers>
<developer>
<id>sothawo</id>
<name>Peter-Josef Meisch</name>
<email>pj.meisch at sothawo.com</email>
<roles>
<role>Project Lead</role>
</roles>
<timezone>+1</timezone>
</developer>
<developer> <developer>
<id>biomedcentral</id> <id>biomedcentral</id>
<name>BioMed Central Development Team</name> <name>BioMed Central Development Team</name>
@@ -77,11 +86,6 @@
</developerConnection> </developerConnection>
</scm> </scm>
<ciManagement>
<system>Bamboo</system>
<url>https://build.spring.io/browse/SPRINGDATAES</url>
</ciManagement>
<issueManagement> <issueManagement>
<system>GitHub</system> <system>GitHub</system>
<url>https://github.com/spring-projects/spring-data-elasticsearch/issues</url> <url>https://github.com/spring-projects/spring-data-elasticsearch/issues</url>
@@ -376,7 +376,7 @@ So calling the method with a `List` of `["id1", "id2", "id3"]` would produce the
.Declare query on the method using the `@Query` annotation with SpEL expression. .Declare query on the method using the `@Query` annotation with SpEL expression.
==== ====
https://docs.spring.io/spring-framework/reference/core/expressions.html[SpEL expression] is also supported when defining query in `@Query`. {spring-framework-docs}/core/expressions.html[SpEL expression] is also supported when defining query in `@Query`.
[source,java] [source,java]
---- ----
@@ -453,7 +453,7 @@ We can pass `new QueryParameter("John")` as the parameter now, and it will produ
.accessing bean property. .accessing bean property.
==== ====
https://docs.spring.io/spring-framework/reference/core/expressions/language-ref/bean-references.html[Bean property] is also supported to access. {spring-framework-docs}/core/expressions/language-ref/bean-references.html[Bean property] is also supported to access.
Given that there is a bean named `queryParameter` of type `QueryParameter`, we can access the bean with symbol `@` rather than `#`, and there is no need to declare a parameter of type `QueryParameter` in the query method: Given that there is a bean named `queryParameter` of type `QueryParameter`, we can access the bean with symbol `@` rather than `#`, and there is no need to declare a parameter of type `QueryParameter` in the query method:
[source,java] [source,java]
@@ -523,7 +523,7 @@ A collection of `names` like `List.of("name1", "name2")` will produce the follow
.access property in the `Collection` param. .access property in the `Collection` param.
==== ====
https://docs.spring.io/spring-framework/reference/core/expressions/language-ref/collection-projection.html[SpEL Collection Projection] is convenient to use when values in the `Collection` parameter is not plain `String`: {spring-framework-docs}/core/expressions/language-ref/collection-projection.html[SpEL Collection Projection] is convenient to use when values in the `Collection` parameter is not plain `String`:
[source,java] [source,java]
---- ----
@@ -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
| 2025.0 | 5.5.x | 8.18.1 | 6.2.x | 2025.0 | 5.5.x | 8.18.8 | 6.2.x
| 2024.1 | 5.4.x | 8.15.5 | 6.1.x | 2024.1 | 5.4.x | 8.15.5 | 6.1.x
| 2024.0 | 5.3.xfootnote:oom[Out of maintenance] | 8.13.4 | 6.1.x | 2024.0 | 5.3.xfootnote:oom[Out of maintenance] | 8.13.4 | 6.1.x
| 2023.1 (Vaughan) | 5.2.xfootnote:oom[] | 8.11.1 | 6.1.x | 2023.1 (Vaughan) | 5.2.xfootnote:oom[] | 8.11.1 | 6.1.x
@@ -3,19 +3,20 @@ prerelease: ${antora-component.prerelease}
asciidoc: asciidoc:
attributes: attributes:
copyright-year: ${current.year}
version: ${project.version}
springversionshort: ${spring.short}
springversion: ${spring}
attribute-missing: 'warn' attribute-missing: 'warn'
commons: ${springdata.commons.docs} chomp: 'all'
version: '${project.version}'
copyright-year: '${current.year}'
springversionshort: '${spring.short}'
springversion: '${spring}'
commons: '${springdata.commons.docs}'
include-xml-namespaces: false include-xml-namespaces: false
spring-data-commons-docs-url: https://docs.spring.io/spring-data/commons/reference spring-data-commons-docs-url: '${documentation.baseurl}/spring-data/commons/reference/${springdata.commons.short}'
spring-data-commons-javadoc-base: https://docs.spring.io/spring-data/commons/docs/${springdata.commons}/api/ spring-data-commons-javadoc-base: '{spring-data-commons-docs-url}/api/java'
springdocsurl: https://docs.spring.io/spring-framework/reference/{springversionshort} springdocsurl: '${documentation.baseurl}/spring-framework/reference/{springversionshort}'
springjavadocurl: https://docs.spring.io/spring-framework/docs/${spring}/javadoc-api
spring-framework-docs: '{springdocsurl}' spring-framework-docs: '{springdocsurl}'
springjavadocurl: '${documentation.spring-javadoc-url}'
spring-framework-javadoc: '{springjavadocurl}' spring-framework-javadoc: '{springjavadocurl}'
springhateoasversion: ${spring-hateoas} springhateoasversion: '${spring-hateoas}'
releasetrainversion: ${releasetrain} releasetrainversion: '${releasetrain}'
store: Elasticsearch store: Elasticsearch
@@ -120,9 +120,6 @@ class RequestConverter extends AbstractQueryProcessor {
private static final Log LOGGER = LogFactory.getLog(RequestConverter.class); private static final Log LOGGER = LogFactory.getLog(RequestConverter.class);
// the default max result window size of Elasticsearch
public static final Integer INDEX_MAX_RESULT_WINDOW = 10_000;
protected final JsonpMapper jsonpMapper; protected final JsonpMapper jsonpMapper;
protected final ElasticsearchConverter elasticsearchConverter; protected final ElasticsearchConverter elasticsearchConverter;
@@ -1039,18 +1036,7 @@ class RequestConverter extends AbstractQueryProcessor {
List<SortOptions> sortOptions = getSortOptions(query.getSort(), persistentEntity); List<SortOptions> sortOptions = getSortOptions(query.getSort(), persistentEntity);
if (!sortOptions.isEmpty()) { if (!sortOptions.isEmpty()) {
dqb.sort( dqb.sort(sortOptions);
sortOptions.stream()
.map(sortOption -> {
String order = "asc";
var sortField = sortOption.field();
if (sortField.order() != null) {
order = sortField.order().jsonValue();
}
return sortField.field() + ':' + order;
})
.collect(Collectors.toList()));
} }
} }
if (query.getRefresh() != null) { if (query.getRefresh() != null) {
@@ -1295,15 +1281,8 @@ class RequestConverter extends AbstractQueryProcessor {
.timeout(timeStringMs(query.getTimeout())) // .timeout(timeStringMs(query.getTimeout())) //
; ;
var offset = query.getPageable().isPaged() ? query.getPageable().getOffset() : 0; bb.from((int) (query.getPageable().isPaged() ? query.getPageable().getOffset() : 0))
var pageSize = query.getPageable().isPaged() ? query.getPageable().getPageSize() .size(query.getRequestSize());
: INDEX_MAX_RESULT_WINDOW;
// if we have both a page size and a max results, we take the min, this is necessary for
// searchForStream to work correctly (#3098) as there the page size defines what is
// returned in a single request, and the max result determines the total number of
// documents returned
var size = query.isLimiting() ? Math.min(pageSize, query.getMaxResults()) : pageSize;
bb.from((int) offset).size(size);
if (!isEmpty(query.getFields())) { if (!isEmpty(query.getFields())) {
bb.fields(fb -> { bb.fields(fb -> {
@@ -1473,14 +1452,8 @@ class RequestConverter extends AbstractQueryProcessor {
builder.seqNoPrimaryTerm(true); builder.seqNoPrimaryTerm(true);
} }
var offset = query.getPageable().isPaged() ? query.getPageable().getOffset() : 0; builder.from((int) (query.getPageable().isPaged() ? query.getPageable().getOffset() : 0))
var pageSize = query.getPageable().isPaged() ? query.getPageable().getPageSize() : INDEX_MAX_RESULT_WINDOW; .size(query.getRequestSize());
// if we have both a page size and a max results, we take the min, this is necessary for
// searchForStream to work correctly (#3098) as there the page size defines what is
// returned in a single request, and the max result determines the total number of
// documents returned
var size = query.isLimiting() ? Math.min(pageSize, query.getMaxResults()) : pageSize;
builder.from((int) offset).size(size);
if (!isEmpty(query.getFields())) { if (!isEmpty(query.getFields())) {
var fieldAndFormats = query.getFields().stream().map(field -> FieldAndFormat.of(b -> b.field(field))).toList(); var fieldAndFormats = query.getFields().stream().map(field -> FieldAndFormat.of(b -> b.field(field))).toList();
@@ -436,7 +436,7 @@ final class TypeUtils {
// values taken from the RHLC implementation // values taken from the RHLC implementation
if (value == null) { if (value == null) {
return -2; return -2;
} else if ("all".equals(value.toUpperCase())) { } else if ("all".equals(value.toLowerCase())) {
return -1; return -1;
} else { } else {
try { try {
@@ -27,6 +27,7 @@ import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
@@ -47,10 +48,15 @@ import org.springframework.util.Assert;
*/ */
public class BaseQuery implements Query { public class BaseQuery implements Query {
public static final int INDEX_MAX_RESULT_WINDOW = 10_000;
private static final int DEFAULT_REACTIVE_BATCH_SIZE = 500; private static final int DEFAULT_REACTIVE_BATCH_SIZE = 500;
// the instance to mark the query pageable initial status, needed to distinguish between the initial
// value and a user-set unpaged value; values don't matter, the RequestConverter compares to the isntance.
private static final Pageable UNSET_PAGE = PageRequest.of(0, 1);
@Nullable protected Sort sort; @Nullable protected Sort sort;
protected Pageable pageable = DEFAULT_PAGE; protected Pageable pageable = UNSET_PAGE;
protected List<String> fields = new ArrayList<>(); protected List<String> fields = new ArrayList<>();
@Nullable protected List<String> storedFields; @Nullable protected List<String> storedFields;
@Nullable protected SourceFilter sourceFilter; @Nullable protected SourceFilter sourceFilter;
@@ -78,7 +84,7 @@ public class BaseQuery implements Query {
private boolean queryIsUpdatedByConverter = false; private boolean queryIsUpdatedByConverter = false;
@Nullable private Integer reactiveBatchSize = null; @Nullable private Integer reactiveBatchSize = null;
@Nullable private Boolean allowNoIndices = null; @Nullable private Boolean allowNoIndices = null;
private EnumSet<IndicesOptions.WildcardStates> expandWildcards; private EnumSet<IndicesOptions.WildcardStates> expandWildcards = EnumSet.noneOf(IndicesOptions.WildcardStates.class);
private List<DocValueField> docValueFields = new ArrayList<>(); private List<DocValueField> docValueFields = new ArrayList<>();
private List<ScriptedField> scriptedFields = new ArrayList<>(); private List<ScriptedField> scriptedFields = new ArrayList<>();
@@ -87,7 +93,7 @@ public class BaseQuery implements Query {
public <Q extends BaseQuery, B extends BaseQueryBuilder<Q, B>> BaseQuery(BaseQueryBuilder<Q, B> builder) { public <Q extends BaseQuery, B extends BaseQueryBuilder<Q, B>> BaseQuery(BaseQueryBuilder<Q, B> builder) {
this.sort = builder.getSort(); this.sort = builder.getSort();
// do a setPageable after setting the sort, because the pageable may contain an additional sort // do a setPageable after setting the sort, because the pageable may contain an additional sort
this.setPageable(builder.getPageable() != null ? builder.getPageable() : DEFAULT_PAGE); this.setPageable(builder.getPageable() != null ? builder.getPageable() : UNSET_PAGE);
this.fields = builder.getFields(); this.fields = builder.getFields();
this.storedFields = builder.getStoredFields(); this.storedFields = builder.getStoredFields();
this.sourceFilter = builder.getSourceFilter(); this.sourceFilter = builder.getSourceFilter();
@@ -203,7 +209,7 @@ public class BaseQuery implements Query {
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final <T extends Query> T addSort(@Nullable Sort sort) { public final <T extends Query> T addSort(@Nullable Sort sort) {
if (sort == null) { if (sort == null || sort.isUnsorted()) {
return (T) this; return (T) this;
} }
@@ -561,4 +567,52 @@ public class BaseQuery implements Query {
public List<ScriptedField> getScriptedFields() { public List<ScriptedField> getScriptedFields() {
return scriptedFields; return scriptedFields;
} }
@Override
public Integer getRequestSize() {
var pageable = getPageable();
Integer requestSize = null;
if (pageable.isPaged() && pageable != UNSET_PAGE) {
// pagesize defined by the user
if (!isLimiting()) {
// no maxResults
requestSize = pageable.getPageSize();
} else {
// if we have both a page size and a max results, we take the min, this is necessary for
// searchForStream to work correctly (#3098) as there the page size defines what is
// returned in a single request, and the max result determines the total number of
// documents returned.
requestSize = Math.min(pageable.getPageSize(), getMaxResults());
}
} else if (pageable == UNSET_PAGE) {
// no user defined pageable
if (isLimiting()) {
// maxResults
requestSize = getMaxResults();
} else {
requestSize = DEFAULT_PAGE_SIZE;
}
} else {
// explicitly set unpaged
if (!isLimiting()) {
// no maxResults
requestSize = INDEX_MAX_RESULT_WINDOW;
} else {
// if we have both a implicit page size and a max results, we take the min, this is necessary for
// searchForStream to work correctly (#3098) as there the page size defines what is
// returned in a single request, and the max result determines the total number of
// documents returned.
requestSize = Math.min(INDEX_MAX_RESULT_WINDOW, getMaxResults());
}
}
if (requestSize == null) {
// this should not happen
requestSize = DEFAULT_PAGE_SIZE;
}
return requestSize;
}
} }
@@ -61,12 +61,16 @@ public class Criteria {
private float boost = Float.NaN; private float boost = Float.NaN;
private boolean negating = false; private boolean negating = false;
private final CriteriaChain criteriaChain = new CriteriaChain(); // we cash this and recalculate when properties used in equals change
private final Set<CriteriaEntry> queryCriteriaEntries = new LinkedHashSet<>(); // see https://github.com/spring-projects/spring-data-elasticsearch/issues/3083
private final Set<CriteriaEntry> filterCriteriaEntries = new LinkedHashSet<>(); private int hashCode;
private final Set<Criteria> subCriteria = new LinkedHashSet<>();
// region criteria creation private final CriteriaChain criteriaChain = new CriteriaChain();
private final Set<CriteriaEntry> queryCriteriaEntries = new LinkedHashSet<>();
private final Set<CriteriaEntry> filterCriteriaEntries = new LinkedHashSet<>();
private final Set<Criteria> subCriteria = new LinkedHashSet<>();
// region criteria creation
/** /**
* @return factory method to create an and-Criteria that is not bound to a field * @return factory method to create an and-Criteria that is not bound to a field
@@ -84,7 +88,9 @@ public class Criteria {
return new OrCriteria(); return new OrCriteria();
} }
public Criteria() {} public Criteria() {
recalculateHashCode();
}
/** /**
* Creates a new Criteria with provided field name * Creates a new Criteria with provided field name
@@ -107,6 +113,7 @@ public class Criteria {
this.field = field; this.field = field;
this.criteriaChain.add(this); this.criteriaChain.add(this);
recalculateHashCode();
} }
/** /**
@@ -136,6 +143,7 @@ public class Criteria {
this.field = field; this.field = field;
this.criteriaChain.addAll(criteriaChain); this.criteriaChain.addAll(criteriaChain);
this.criteriaChain.add(this); this.criteriaChain.add(this);
recalculateHashCode();
} }
/** /**
@@ -189,6 +197,7 @@ public class Criteria {
*/ */
public Criteria not() { public Criteria not() {
this.negating = true; this.negating = true;
recalculateHashCode();
return this; return this;
} }
@@ -207,6 +216,7 @@ public class Criteria {
Assert.isTrue(boost >= 0, "boost must not be negative"); Assert.isTrue(boost >= 0, "boost must not be negative");
this.boost = boost; this.boost = boost;
recalculateHashCode();
return this; return this;
} }
@@ -223,7 +233,7 @@ public class Criteria {
} }
/** /**
* @return the set ob subCriteria * @return the set of subCriteria
* @since 4.1 * @since 4.1
*/ */
public Set<Criteria> getSubCriteria() { public Set<Criteria> getSubCriteria() {
@@ -264,6 +274,7 @@ public class Criteria {
Assert.notNull(criteria, "Cannot chain 'null' criteria."); Assert.notNull(criteria, "Cannot chain 'null' criteria.");
this.criteriaChain.add(criteria); this.criteriaChain.add(criteria);
recalculateHashCode();
return this; return this;
} }
@@ -278,6 +289,7 @@ public class Criteria {
Assert.notNull(criterias, "Cannot chain 'null' criterias."); Assert.notNull(criterias, "Cannot chain 'null' criterias.");
this.criteriaChain.addAll(Arrays.asList(criterias)); this.criteriaChain.addAll(Arrays.asList(criterias));
recalculateHashCode();
return this; return this;
} }
@@ -320,6 +332,7 @@ public class Criteria {
orCriteria.subCriteria.addAll(criteria.subCriteria); orCriteria.subCriteria.addAll(criteria.subCriteria);
orCriteria.boost = criteria.boost; orCriteria.boost = criteria.boost;
orCriteria.negating = criteria.isNegating(); orCriteria.negating = criteria.isNegating();
orCriteria.recalculateHashCode();
return orCriteria; return orCriteria;
} }
@@ -335,6 +348,7 @@ public class Criteria {
Assert.notNull(criteria, "criteria must not be null"); Assert.notNull(criteria, "criteria must not be null");
subCriteria.add(criteria); subCriteria.add(criteria);
recalculateHashCode();
return this; return this;
} }
@@ -349,6 +363,7 @@ public class Criteria {
*/ */
public Criteria is(Object o) { public Criteria is(Object o) {
queryCriteriaEntries.add(new CriteriaEntry(OperationKey.EQUALS, o)); queryCriteriaEntries.add(new CriteriaEntry(OperationKey.EQUALS, o));
recalculateHashCode();
return this; return this;
} }
@@ -360,6 +375,7 @@ public class Criteria {
*/ */
public Criteria exists() { public Criteria exists() {
queryCriteriaEntries.add(new CriteriaEntry(OperationKey.EXISTS)); queryCriteriaEntries.add(new CriteriaEntry(OperationKey.EXISTS));
recalculateHashCode();
return this; return this;
} }
@@ -378,6 +394,7 @@ public class Criteria {
} }
queryCriteriaEntries.add(new CriteriaEntry(OperationKey.BETWEEN, new Object[] { lowerBound, upperBound })); queryCriteriaEntries.add(new CriteriaEntry(OperationKey.BETWEEN, new Object[] { lowerBound, upperBound }));
recalculateHashCode();
return this; return this;
} }
@@ -393,6 +410,7 @@ public class Criteria {
assertNoBlankInWildcardQuery(s, false, true); assertNoBlankInWildcardQuery(s, false, true);
queryCriteriaEntries.add(new CriteriaEntry(OperationKey.STARTS_WITH, s)); queryCriteriaEntries.add(new CriteriaEntry(OperationKey.STARTS_WITH, s));
recalculateHashCode();
return this; return this;
} }
@@ -409,6 +427,7 @@ public class Criteria {
assertNoBlankInWildcardQuery(s, true, true); assertNoBlankInWildcardQuery(s, true, true);
queryCriteriaEntries.add(new CriteriaEntry(OperationKey.CONTAINS, s)); queryCriteriaEntries.add(new CriteriaEntry(OperationKey.CONTAINS, s));
recalculateHashCode();
return this; return this;
} }
@@ -425,6 +444,7 @@ public class Criteria {
assertNoBlankInWildcardQuery(s, true, false); assertNoBlankInWildcardQuery(s, true, false);
queryCriteriaEntries.add(new CriteriaEntry(OperationKey.ENDS_WITH, s)); queryCriteriaEntries.add(new CriteriaEntry(OperationKey.ENDS_WITH, s));
recalculateHashCode();
return this; return this;
} }
@@ -452,6 +472,7 @@ public class Criteria {
Assert.notNull(values, "Collection of 'in' values must not be null"); Assert.notNull(values, "Collection of 'in' values must not be null");
queryCriteriaEntries.add(new CriteriaEntry(OperationKey.IN, values)); queryCriteriaEntries.add(new CriteriaEntry(OperationKey.IN, values));
recalculateHashCode();
return this; return this;
} }
@@ -478,6 +499,7 @@ public class Criteria {
Assert.notNull(values, "Collection of 'NotIn' values must not be null"); Assert.notNull(values, "Collection of 'NotIn' values must not be null");
queryCriteriaEntries.add(new CriteriaEntry(OperationKey.NOT_IN, values)); queryCriteriaEntries.add(new CriteriaEntry(OperationKey.NOT_IN, values));
recalculateHashCode();
return this; return this;
} }
@@ -490,6 +512,7 @@ public class Criteria {
*/ */
public Criteria expression(String s) { public Criteria expression(String s) {
queryCriteriaEntries.add(new CriteriaEntry(OperationKey.EXPRESSION, s)); queryCriteriaEntries.add(new CriteriaEntry(OperationKey.EXPRESSION, s));
recalculateHashCode();
return this; return this;
} }
@@ -501,6 +524,7 @@ public class Criteria {
*/ */
public Criteria fuzzy(String s) { public Criteria fuzzy(String s) {
queryCriteriaEntries.add(new CriteriaEntry(OperationKey.FUZZY, s)); queryCriteriaEntries.add(new CriteriaEntry(OperationKey.FUZZY, s));
recalculateHashCode();
return this; return this;
} }
@@ -515,6 +539,7 @@ public class Criteria {
Assert.notNull(upperBound, "upperBound must not be null"); Assert.notNull(upperBound, "upperBound must not be null");
queryCriteriaEntries.add(new CriteriaEntry(OperationKey.LESS_EQUAL, upperBound)); queryCriteriaEntries.add(new CriteriaEntry(OperationKey.LESS_EQUAL, upperBound));
recalculateHashCode();
return this; return this;
} }
@@ -529,6 +554,7 @@ public class Criteria {
Assert.notNull(upperBound, "upperBound must not be null"); Assert.notNull(upperBound, "upperBound must not be null");
queryCriteriaEntries.add(new CriteriaEntry(OperationKey.LESS, upperBound)); queryCriteriaEntries.add(new CriteriaEntry(OperationKey.LESS, upperBound));
recalculateHashCode();
return this; return this;
} }
@@ -543,6 +569,7 @@ public class Criteria {
Assert.notNull(lowerBound, "lowerBound must not be null"); Assert.notNull(lowerBound, "lowerBound must not be null");
queryCriteriaEntries.add(new CriteriaEntry(OperationKey.GREATER_EQUAL, lowerBound)); queryCriteriaEntries.add(new CriteriaEntry(OperationKey.GREATER_EQUAL, lowerBound));
recalculateHashCode();
return this; return this;
} }
@@ -557,6 +584,7 @@ public class Criteria {
Assert.notNull(lowerBound, "lowerBound must not be null"); Assert.notNull(lowerBound, "lowerBound must not be null");
queryCriteriaEntries.add(new CriteriaEntry(OperationKey.GREATER, lowerBound)); queryCriteriaEntries.add(new CriteriaEntry(OperationKey.GREATER, lowerBound));
recalculateHashCode();
return this; return this;
} }
@@ -573,6 +601,7 @@ public class Criteria {
Assert.notNull(value, "value must not be null"); Assert.notNull(value, "value must not be null");
queryCriteriaEntries.add(new CriteriaEntry(OperationKey.MATCHES, value)); queryCriteriaEntries.add(new CriteriaEntry(OperationKey.MATCHES, value));
recalculateHashCode();
return this; return this;
} }
@@ -589,6 +618,7 @@ public class Criteria {
Assert.notNull(value, "value must not be null"); Assert.notNull(value, "value must not be null");
queryCriteriaEntries.add(new CriteriaEntry(OperationKey.MATCHES_ALL, value)); queryCriteriaEntries.add(new CriteriaEntry(OperationKey.MATCHES_ALL, value));
recalculateHashCode();
return this; return this;
} }
@@ -601,6 +631,7 @@ public class Criteria {
public Criteria empty() { public Criteria empty() {
queryCriteriaEntries.add(new CriteriaEntry(OperationKey.EMPTY)); queryCriteriaEntries.add(new CriteriaEntry(OperationKey.EMPTY));
recalculateHashCode();
return this; return this;
} }
@@ -613,6 +644,7 @@ public class Criteria {
public Criteria notEmpty() { public Criteria notEmpty() {
queryCriteriaEntries.add(new CriteriaEntry(OperationKey.NOT_EMPTY)); queryCriteriaEntries.add(new CriteriaEntry(OperationKey.NOT_EMPTY));
recalculateHashCode();
return this; return this;
} }
@@ -628,6 +660,7 @@ public class Criteria {
Assert.notNull(value, "value must not be null"); Assert.notNull(value, "value must not be null");
queryCriteriaEntries.add(new CriteriaEntry(OperationKey.REGEXP, value)); queryCriteriaEntries.add(new CriteriaEntry(OperationKey.REGEXP, value));
recalculateHashCode();
return this; return this;
} }
@@ -646,6 +679,7 @@ public class Criteria {
Assert.notNull(boundingBox, "boundingBox value for boundedBy criteria must not be null"); Assert.notNull(boundingBox, "boundingBox value for boundedBy criteria must not be null");
filterCriteriaEntries.add(new CriteriaEntry(OperationKey.BBOX, new Object[] { boundingBox })); filterCriteriaEntries.add(new CriteriaEntry(OperationKey.BBOX, new Object[] { boundingBox }));
recalculateHashCode();
return this; return this;
} }
@@ -662,6 +696,7 @@ public class Criteria {
filterCriteriaEntries filterCriteriaEntries
.add(new CriteriaEntry(OperationKey.BBOX, new Object[] { boundingBox.getFirst(), boundingBox.getSecond() })); .add(new CriteriaEntry(OperationKey.BBOX, new Object[] { boundingBox.getFirst(), boundingBox.getSecond() }));
recalculateHashCode();
return this; return this;
} }
@@ -679,6 +714,7 @@ public class Criteria {
filterCriteriaEntries filterCriteriaEntries
.add(new CriteriaEntry(OperationKey.BBOX, new Object[] { topLeftGeohash, bottomRightGeohash })); .add(new CriteriaEntry(OperationKey.BBOX, new Object[] { topLeftGeohash, bottomRightGeohash }));
recalculateHashCode();
return this; return this;
} }
@@ -695,6 +731,7 @@ public class Criteria {
Assert.notNull(bottomRightPoint, "bottomRightPoint must not be null"); Assert.notNull(bottomRightPoint, "bottomRightPoint must not be null");
filterCriteriaEntries.add(new CriteriaEntry(OperationKey.BBOX, new Object[] { topLeftPoint, bottomRightPoint })); filterCriteriaEntries.add(new CriteriaEntry(OperationKey.BBOX, new Object[] { topLeftPoint, bottomRightPoint }));
recalculateHashCode();
return this; return this;
} }
@@ -712,6 +749,7 @@ public class Criteria {
filterCriteriaEntries.add(new CriteriaEntry(OperationKey.BBOX, filterCriteriaEntries.add(new CriteriaEntry(OperationKey.BBOX,
new Object[] { GeoPoint.fromPoint(topLeftPoint), GeoPoint.fromPoint(bottomRightPoint) })); new Object[] { GeoPoint.fromPoint(topLeftPoint), GeoPoint.fromPoint(bottomRightPoint) }));
recalculateHashCode();
return this; return this;
} }
@@ -729,6 +767,7 @@ public class Criteria {
Assert.notNull(location, "Distance value for near criteria must not be null"); Assert.notNull(location, "Distance value for near criteria must not be null");
filterCriteriaEntries.add(new CriteriaEntry(OperationKey.WITHIN, new Object[] { location, distance })); filterCriteriaEntries.add(new CriteriaEntry(OperationKey.WITHIN, new Object[] { location, distance }));
recalculateHashCode();
return this; return this;
} }
@@ -745,6 +784,7 @@ public class Criteria {
Assert.notNull(location, "Distance value for near criteria must not be null"); Assert.notNull(location, "Distance value for near criteria must not be null");
filterCriteriaEntries.add(new CriteriaEntry(OperationKey.WITHIN, new Object[] { location, distance })); filterCriteriaEntries.add(new CriteriaEntry(OperationKey.WITHIN, new Object[] { location, distance }));
recalculateHashCode();
return this; return this;
} }
@@ -761,6 +801,7 @@ public class Criteria {
Assert.isTrue(StringUtils.hasLength(geoLocation), "geoLocation value must not be null"); Assert.isTrue(StringUtils.hasLength(geoLocation), "geoLocation value must not be null");
filterCriteriaEntries.add(new CriteriaEntry(OperationKey.WITHIN, new Object[] { geoLocation, distance })); filterCriteriaEntries.add(new CriteriaEntry(OperationKey.WITHIN, new Object[] { geoLocation, distance }));
recalculateHashCode();
return this; return this;
} }
@@ -775,6 +816,7 @@ public class Criteria {
Assert.notNull(geoShape, "geoShape must not be null"); Assert.notNull(geoShape, "geoShape must not be null");
filterCriteriaEntries.add(new CriteriaEntry(OperationKey.GEO_INTERSECTS, geoShape)); filterCriteriaEntries.add(new CriteriaEntry(OperationKey.GEO_INTERSECTS, geoShape));
recalculateHashCode();
return this; return this;
} }
@@ -789,6 +831,7 @@ public class Criteria {
Assert.notNull(geoShape, "geoShape must not be null"); Assert.notNull(geoShape, "geoShape must not be null");
filterCriteriaEntries.add(new CriteriaEntry(OperationKey.GEO_IS_DISJOINT, geoShape)); filterCriteriaEntries.add(new CriteriaEntry(OperationKey.GEO_IS_DISJOINT, geoShape));
recalculateHashCode();
return this; return this;
} }
@@ -802,6 +845,7 @@ public class Criteria {
Assert.notNull(geoShape, "geoShape must not be null"); Assert.notNull(geoShape, "geoShape must not be null");
filterCriteriaEntries.add(new CriteriaEntry(OperationKey.GEO_WITHIN, geoShape)); filterCriteriaEntries.add(new CriteriaEntry(OperationKey.GEO_WITHIN, geoShape));
recalculateHashCode();
return this; return this;
} }
@@ -815,6 +859,7 @@ public class Criteria {
Assert.notNull(geoShape, "geoShape must not be null"); Assert.notNull(geoShape, "geoShape must not be null");
filterCriteriaEntries.add(new CriteriaEntry(OperationKey.GEO_CONTAINS, geoShape)); filterCriteriaEntries.add(new CriteriaEntry(OperationKey.GEO_CONTAINS, geoShape));
recalculateHashCode();
return this; return this;
} }
@@ -828,6 +873,7 @@ public class Criteria {
Assert.notNull(query, "has_child query must not be null."); Assert.notNull(query, "has_child query must not be null.");
queryCriteriaEntries.add(new CriteriaEntry(OperationKey.HAS_CHILD, query)); queryCriteriaEntries.add(new CriteriaEntry(OperationKey.HAS_CHILD, query));
recalculateHashCode();
return this; return this;
} }
@@ -841,6 +887,7 @@ public class Criteria {
Assert.notNull(query, "has_parent query must not be null."); Assert.notNull(query, "has_parent query must not be null.");
queryCriteriaEntries.add(new CriteriaEntry(OperationKey.HAS_PARENT, query)); queryCriteriaEntries.add(new CriteriaEntry(OperationKey.HAS_PARENT, query));
recalculateHashCode();
return this; return this;
} }
// endregion // endregion
@@ -887,18 +934,22 @@ public class Criteria {
@Override @Override
public int hashCode() { public int hashCode() {
int result = field != null ? field.hashCode() : 0; return hashCode;
result = 31 * result + (boost != +0.0f ? Float.floatToIntBits(boost) : 0);
result = 31 * result + (negating ? 1 : 0);
// the criteriaChain contains "this" object, so we need to filter it out
// to avoid a stackoverflow here, because the hashcode implementation
// uses the element's hashcodes
result = 31 * result + criteriaChain.filter(this).hashCode();
result = 31 * result + queryCriteriaEntries.hashCode();
result = 31 * result + filterCriteriaEntries.hashCode();
result = 31 * result + subCriteria.hashCode();
return result;
} }
private void recalculateHashCode() {
int result = field != null ? field.hashCode() : 0;
result = 31 * result + (boost != +0.0f ? Float.floatToIntBits(boost) : 0);
result = 31 * result + (negating ? 1 : 0);
// the criteriaChain contains "this" object, so we need to filter it out
// to avoid a stackoverflow here, because the hashcode implementation
// uses the element's hashcodes
result = 31 * result + criteriaChain.filter(this).hashCode();
result = 31 * result + queryCriteriaEntries.hashCode();
result = 31 * result + filterCriteriaEntries.hashCode();
result = 31 * result + subCriteria.hashCode();
this.hashCode = result;
}
// endregion // endregion
@Override @Override
@@ -484,6 +484,13 @@ public interface Query {
*/ */
List<ScriptedField> getScriptedFields(); List<ScriptedField> getScriptedFields();
/**
* @return the number of documents that should be requested from Elasticsearch in this query. Depends wether a
* Pageable and/or maxResult size is set on the query.
* @since 5.4.8 5.5.2
*/
public Integer getRequestSize();
/** /**
* @since 4.3 * @since 4.3
*/ */
+8 -1
View File
@@ -1,4 +1,4 @@
Spring Data Elasticsearch 5.5 GA (2025.0.0) Spring Data Elasticsearch 5.5.7 (2025.0.7)
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").
@@ -21,6 +21,13 @@ conditions of the subcomponent's license, as noted in the LICENSE file.
@@ -448,7 +448,7 @@ public class CriteriaQueryMappingUnitTests {
} }
// the following test failed because of a wrong implementation in Criteria // the following test failed because of a wrong implementation in Criteria
// equals and hscode methods. // equals and hashcode methods.
@Test // #3083 @Test // #3083
@DisplayName("should map correct subcriteria") @DisplayName("should map correct subcriteria")
void shouldMapCorrectSubcriteria() throws JSONException { void shouldMapCorrectSubcriteria() throws JSONException {
@@ -105,8 +105,6 @@ import org.springframework.lang.Nullable;
@SpringIntegrationTest @SpringIntegrationTest
public abstract class ElasticsearchIntegrationTests { public abstract class ElasticsearchIntegrationTests {
static final Integer INDEX_MAX_RESULT_WINDOW = 10_000;
private static final String MULTI_INDEX_PREFIX = "test-index"; private static final String MULTI_INDEX_PREFIX = "test-index";
private static final String MULTI_INDEX_ALL = MULTI_INDEX_PREFIX + "*"; private static final String MULTI_INDEX_ALL = MULTI_INDEX_PREFIX + "*";
private static final String MULTI_INDEX_1_NAME = MULTI_INDEX_PREFIX + "-1"; private static final String MULTI_INDEX_1_NAME = MULTI_INDEX_PREFIX + "-1";
@@ -0,0 +1,106 @@
/*
* Copyright 2025 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.core.query;
import static org.assertj.core.api.Assertions.*;
import static org.springframework.data.elasticsearch.core.query.BaseQuery.*;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.data.domain.Pageable;
class BaseQueryTests {
private static final String MATCH_ALL_QUERY = "{\"match_all\":{}}";
@Test // #3127
@DisplayName("query with no Pageable and no maxResults requests 10 docs from 0")
void queryWithNoPageableAndNoMaxResultsRequests10DocsFrom0() {
var query = StringQuery.builder(MATCH_ALL_QUERY)
.build();
var requestSize = query.getRequestSize();
assertThat(requestSize).isEqualTo(10);
}
@Test // #3127
@DisplayName("query with a Pageable and no MaxResults request with values from Pageable")
void queryWithAPageableAndNoMaxResultsRequestWithValuesFromPageable() {
var query = StringQuery.builder(MATCH_ALL_QUERY)
.withPageable(Pageable.ofSize(42))
.build();
var requestSize = query.getRequestSize();
assertThat(requestSize).isEqualTo(42);
}
@Test // #3127
@DisplayName("query with no Pageable and maxResults requests maxResults")
void queryWithNoPageableAndMaxResultsRequestsMaxResults() {
var query = StringQuery.builder(MATCH_ALL_QUERY)
.withMaxResults(12_345)
.build();
var requestSize = query.getRequestSize();
assertThat(requestSize).isEqualTo(12_345);
}
@Test // #3127
@DisplayName("query with Pageable and maxResults requests with values from Pageable if Pageable is less than maxResults")
void queryWithPageableAndMaxResultsRequestsWithValuesFromPageableIfPageableIsLessThanMaxResults() {
var query = StringQuery.builder(MATCH_ALL_QUERY)
.withPageable(Pageable.ofSize(42))
.withMaxResults(123)
.build();
var requestSize = query.getRequestSize();
assertThat(requestSize).isEqualTo(42);
}
@Test // #3127
@DisplayName("query with Pageable and maxResults requests with values from maxResults if Pageable is more than maxResults")
void queryWithPageableAndMaxResultsRequestsWithValuesFromMaxResultsIfPageableIsMoreThanMaxResults() {
var query = StringQuery.builder(MATCH_ALL_QUERY)
.withPageable(Pageable.ofSize(420))
.withMaxResults(123)
.build();
var requestSize = query.getRequestSize();
assertThat(requestSize).isEqualTo(123);
}
@Test // #3127
@DisplayName("query with explicit unpaged request and no maxResults requests max request window size")
void queryWithExplicitUnpagedRequestAndNoMaxResultsRequestsMaxRequestWindowSize() {
var query = StringQuery.builder(MATCH_ALL_QUERY)
.withPageable(Pageable.unpaged())
.build();
var requestSize = query.getRequestSize();
assertThat(requestSize).isEqualTo(INDEX_MAX_RESULT_WINDOW);
}
}
@@ -0,0 +1,45 @@
/*
* Copyright 2019-2025 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.core.query;
import static org.junit.jupiter.api.Assertions.*;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
/**
* @author Peter-Josef Meisch
*/
class CriteriaTest {
@Test // #3159
@DisplayName("should not slow down on calculating hashcode for long criteria chains")
void shouldNotSlowDownOnCalculatingHashcodeForLongCriteriaChains() {
assertTimeoutPreemptively(Duration.of(1, ChronoUnit.SECONDS), () -> {
var criteria = new Criteria();
var size = 1000;
for (int i = 1; i <= size; i++) {
criteria = criteria.or("field-" + i).contains("value-" + i);
}
final var criteriaChain = criteria.getCriteriaChain();
assertEquals(size, criteriaChain.size());
final var hashCode = Integer.valueOf(criteria.hashCode());
});
}
}
@@ -0,0 +1 @@
api.version=1.44
@@ -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.18.1 sde.testcontainers.image-version=8.18.8
# #
# #
# 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