Compare commits
48 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| db2a6b84a9 | |||
| 223ff41145 | |||
| 604f23384b | |||
| 011d2d5740 | |||
| 5b1e179e88 | |||
| 6332534ea1 | |||
| 36f0907881 | |||
| 7cd871a419 | |||
| d428db704e | |||
| 9bf1c09457 | |||
| 92f16846ab | |||
| 1de1aeb2c7 | |||
| b177dd1681 | |||
| aeaa27cb99 | |||
| 3c44a1c969 | |||
| 384e52b2c3 | |||
| 7b24ea9575 | |||
| 282214f8bc | |||
| bbf4c24195 | |||
| 407c8c6c17 | |||
| 407da040ab | |||
| 275560ecf3 | |||
| 846dbea2b8 | |||
| 8dbbc80887 | |||
| 8fea655854 | |||
| caebe08cf2 | |||
| 859b22db8e | |||
| 79dae4ee03 | |||
| 852273eff5 | |||
| d26dfbba70 | |||
| fa317014a7 | |||
| cb750e03a9 | |||
| 0f84158e1e | |||
| dc6734db43 | |||
| bcd7c2a1d8 | |||
| d8d3f9431b | |||
| 2875c62cfe | |||
| 75a430d431 | |||
| 49f1516b9e | |||
| b439acac16 | |||
| 506f79a45a | |||
| 391e240b49 | |||
| aaef626684 | |||
| c7339dc248 | |||
| 7540a2a1a8 | |||
| 6487d0ddd4 | |||
| 9ac18855fc | |||
| 0dc0f40cba |
@@ -1,27 +0,0 @@
|
||||
= Contributor Code of Conduct
|
||||
|
||||
As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
|
||||
|
||||
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality.
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery
|
||||
* Personal attacks
|
||||
* Trolling or insulting/derogatory comments
|
||||
* Public or private harassment
|
||||
* Publishing other's private information, such as physical or electronic addresses,
|
||||
without explicit permission
|
||||
* Other unethical or unprofessional conduct
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team.
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community.
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting a project maintainer at spring-code-of-conduct@pivotal.io.
|
||||
All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances.
|
||||
Maintainers are obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
|
||||
This Code of Conduct is adapted from the https://contributor-covenant.org[Contributor Covenant], version 1.3.0, available at https://contributor-covenant.org/version/1/3/0/[contributor-covenant.org/version/1/3/0/].
|
||||
Vendored
+5
-5
@@ -3,7 +3,7 @@ pipeline {
|
||||
|
||||
triggers {
|
||||
pollSCM 'H/10 * * * *'
|
||||
upstream(upstreamProjects: "spring-data-commons/2.3.x", threshold: hudson.model.Result.SUCCESS)
|
||||
upstream(upstreamProjects: "spring-data-commons/master", threshold: hudson.model.Result.SUCCESS)
|
||||
}
|
||||
|
||||
options {
|
||||
@@ -15,7 +15,7 @@ pipeline {
|
||||
stage("test: baseline (jdk8)") {
|
||||
when {
|
||||
anyOf {
|
||||
branch '4.0.x'
|
||||
branch 'master'
|
||||
not { triggeredBy 'UpstreamCause' }
|
||||
}
|
||||
}
|
||||
@@ -36,7 +36,7 @@ pipeline {
|
||||
stage("Test other configurations") {
|
||||
when {
|
||||
anyOf {
|
||||
branch '4.0.x'
|
||||
branch 'master'
|
||||
not { triggeredBy 'UpstreamCause' }
|
||||
}
|
||||
}
|
||||
@@ -76,7 +76,7 @@ pipeline {
|
||||
stage('Release to artifactory') {
|
||||
when {
|
||||
anyOf {
|
||||
branch '4.0.x'
|
||||
branch 'master'
|
||||
not { triggeredBy 'UpstreamCause' }
|
||||
}
|
||||
}
|
||||
@@ -107,7 +107,7 @@ pipeline {
|
||||
}
|
||||
stage('Publish documentation') {
|
||||
when {
|
||||
branch '4.0.x'
|
||||
branch 'master'
|
||||
}
|
||||
agent {
|
||||
docker {
|
||||
|
||||
+1
-1
@@ -123,7 +123,7 @@ Add the Maven dependency:
|
||||
// Always change both files!
|
||||
**Compatibility Matrix**
|
||||
|
||||
The compatibility between Spring Data Elasticsearch, Elasticsearch client drivers and Spring Boot versions can be found in the https://docs.spring.io/spring-data/elasticsearch/docs/3.2.0.RC3/reference/html/#preface.versions[reference documentation].
|
||||
The compatibility between Spring Data Elasticsearch, Elasticsearch client drivers and Spring Boot versions can be found in the https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/#preface.versions[reference documentation].
|
||||
|
||||
To use the Release candidate versions of the upcoming major version, use our Maven milestone repository and declare the appropriate dependency version:
|
||||
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-elasticsearch</artifactId>
|
||||
<version>4.0.1.RELEASE</version>
|
||||
<version>4.1.0-M1</version>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.data.build</groupId>
|
||||
<artifactId>spring-data-parent</artifactId>
|
||||
<version>2.3.1.RELEASE</version>
|
||||
<version>2.4.0-M1</version>
|
||||
</parent>
|
||||
|
||||
<name>Spring Data Elasticsearch</name>
|
||||
@@ -19,10 +19,10 @@
|
||||
|
||||
<properties>
|
||||
<commonslang>2.6</commonslang>
|
||||
<elasticsearch>7.6.2</elasticsearch>
|
||||
<elasticsearch>7.7.1</elasticsearch>
|
||||
<log4j>2.9.1</log4j>
|
||||
<springdata.commons>2.3.1.RELEASE</springdata.commons>
|
||||
<netty>4.1.39.Final</netty>
|
||||
<springdata.commons>2.4.0-M1</springdata.commons>
|
||||
<netty>4.1.50.Final</netty>
|
||||
<java-module-name>spring.data.elasticsearch</java-module-name>
|
||||
</properties>
|
||||
|
||||
@@ -373,8 +373,8 @@
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-libs-release</id>
|
||||
<url>https://repo.spring.io/libs-release</url>
|
||||
<id>spring-libs-milestone</id>
|
||||
<url>https://repo.spring.io/libs-milestone</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
|
||||
@@ -35,8 +35,9 @@ The following table shows the Elasticsearch versions that are used by Spring Dat
|
||||
[cols="^,^,^,^",options="header"]
|
||||
|===
|
||||
| Spring Data Release Train |Spring Data Elasticsearch |Elasticsearch | Spring Boot
|
||||
| Neumannfootnote:cdv[Currently in development] |4.0.xfootnote:cdv[]|7.6.2 |2.3.xfootnote:cdv[]
|
||||
| Moore | 3.2.x |6.8.6 | 2.2.x
|
||||
| 2020.0.0footnote:cdv[Currently in development] |4.1.xfootnote:cdv[]|7.7.1 |2.3.xfootnote:cdv[]
|
||||
| Neumann | 4.0.x | 7.6.2 |2.3.x
|
||||
| Moore | 3.2.x |6.8.10 | 2.2.x
|
||||
| Lovelace | 3.1.x | 6.2.2 |2.1.x
|
||||
| Kayfootnote:oom[Out of maintenance] | 3.0.xfootnote:oom[] | 5.5.0 | 2.0.xfootnote:oom[]
|
||||
| Ingallsfootnote:oom[] | 2.1.xfootnote:oom[] | 2.4.0 | 1.5.xfootnote:oom[]
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
[[elasticsearch-migration-guide-4.0-4.1]]
|
||||
= Upgrading from 4.0.x to 4.1.x
|
||||
|
||||
This section describes breaking changes from version 4.0.x to 4.1.x and how removed features can be replaced by new introduced features.
|
||||
|
||||
[[elasticsearch-migration-guide-4.0-4.1.deprecations]]
|
||||
== Deprecations
|
||||
|
||||
.Definition of the id property
|
||||
It is possible to define a property of en entity as the id property by naming it either `id` or `document`.
|
||||
This behaviour is now deprecated and will produce a warning.
|
||||
PLease us the `@Id` annotation to mark a property as being the id property.
|
||||
|
||||
In the `ReactiveElasticsearchClient.Indices` interface the `updateMapping` methods are deprecated in favour of the `putMapping` methods.
|
||||
They do the same, but `putMapping` is consistent with the naming in the Elasticsearch API:
|
||||
|
||||
[[elasticsearch-migration-guide-4.0-4.1.removal]]
|
||||
== Removals
|
||||
|
||||
.Type mappings
|
||||
The _type mappings_ parameters of the `@Document` annotation and the `IndexCoordinates` object were removed.
|
||||
They had been deprecated in Spring Data Elasticsearch 4.0 and their values weren't used anymore.
|
||||
|
||||
[[elasticsearch-migration-guide-4.0-4.1.breaking-changes]]
|
||||
== Breaking Changes
|
||||
|
||||
=== Return types of ReactiveElasticsearchClient.Indices methods
|
||||
|
||||
The methods in the `ReactiveElasticsearchClient.Indices` were not used up to now.
|
||||
With the introduction of the `ReactiveIndexOperations` it became necessary to change some of the return types:
|
||||
|
||||
* the `createIndex` variants now return a `Mono<Boolean>` instead of a `Mono<Void>` to signal successful index creation.
|
||||
* the `updateMapping` variants now return a `Mono<Boolean>` instead of a `Mono<Void>` to signal successful mappings storage.
|
||||
@@ -134,6 +134,7 @@ Contains the following information:
|
||||
* Score
|
||||
* Sort Values
|
||||
* Highlight fields
|
||||
* Inner hits (this is an embedded `SearchHits` object containing eventually returned inner hits)
|
||||
* The retrieved entity of type <T>
|
||||
|
||||
.SearchHits<T>
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
[[elasticsearch.migration]]
|
||||
= Appendix E: Migration Guides
|
||||
|
||||
// line breaks required otherwise the TOC breaks due to joining of first/last lines.
|
||||
:leveloffset: +1
|
||||
include::elasticsearch-migration-guide-3.2-4.0.adoc[]
|
||||
|
||||
include::elasticsearch-migration-guide-4.0-4.1.adoc[]
|
||||
:leveloffset: -1
|
||||
|
||||
@@ -21,7 +21,7 @@ import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Peter-Josef Meisch
|
||||
* @since 4.0.1 (ported back from master (4.1) branch)
|
||||
* @since 4.1
|
||||
*/
|
||||
public class BulkFailureException extends DataRetrievalFailureException {
|
||||
private final Map<String, String> failedDocuments;
|
||||
|
||||
+4
@@ -23,6 +23,10 @@ import org.springframework.dao.UncategorizedDataAccessException;
|
||||
*/
|
||||
public class UncategorizedElasticsearchException extends UncategorizedDataAccessException {
|
||||
|
||||
public UncategorizedElasticsearchException(String msg) {
|
||||
super(msg, null);
|
||||
}
|
||||
|
||||
public UncategorizedElasticsearchException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
|
||||
@@ -16,16 +16,58 @@
|
||||
package org.springframework.data.elasticsearch.annotations;
|
||||
|
||||
/**
|
||||
* Values based on reference doc - https://www.elastic.co/guide/reference/mapping/date-format/
|
||||
*
|
||||
* @author Jakub Vavrik
|
||||
* Values based on reference doc - https://www.elastic.co/guide/reference/mapping/date-format/
|
||||
* @author Tim te Beek
|
||||
* @author Peter-Josef Meisch
|
||||
*/
|
||||
public enum DateFormat {
|
||||
none, custom, basic_date, basic_date_time, basic_date_time_no_millis, basic_ordinal_date, basic_ordinal_date_time,
|
||||
basic_ordinal_date_time_no_millis, basic_time, basic_time_no_millis, basic_t_time, basic_t_time_no_millis,
|
||||
basic_week_date, basic_week_date_time, basic_week_date_time_no_millis, date, date_hour, date_hour_minute,
|
||||
date_hour_minute_second, date_hour_minute_second_fraction, date_hour_minute_second_millis, date_optional_time,
|
||||
date_time, date_time_no_millis, hour, hour_minute, hour_minute_second, hour_minute_second_fraction,
|
||||
hour_minute_second_millis, ordinal_date, ordinal_date_time, ordinal_date_time_no_millis, time, time_no_millis,
|
||||
t_time, t_time_no_millis, week_date, week_date_time, weekDateTimeNoMillis, week_year, weekyearWeek,
|
||||
weekyearWeekDay, year, year_month, year_month_day
|
||||
none, //
|
||||
custom, //
|
||||
basic_date, //
|
||||
basic_date_time, //
|
||||
basic_date_time_no_millis, //
|
||||
basic_ordinal_date, //
|
||||
basic_ordinal_date_time, //
|
||||
basic_ordinal_date_time_no_millis, //
|
||||
basic_time, //
|
||||
basic_time_no_millis, //
|
||||
basic_t_time, //
|
||||
basic_t_time_no_millis, //
|
||||
basic_week_date, //
|
||||
basic_week_date_time, //
|
||||
basic_week_date_time_no_millis, //
|
||||
date, //
|
||||
date_hour, //
|
||||
date_hour_minute, //
|
||||
date_hour_minute_second, //
|
||||
date_hour_minute_second_fraction, //
|
||||
date_hour_minute_second_millis, //
|
||||
date_optional_time, //
|
||||
date_time, //
|
||||
date_time_no_millis, //
|
||||
epoch_millis, //
|
||||
epoch_second, //
|
||||
hour, //
|
||||
hour_minute, //
|
||||
hour_minute_second, //
|
||||
hour_minute_second_fraction, //
|
||||
hour_minute_second_millis, //
|
||||
ordinal_date, //
|
||||
ordinal_date_time, //
|
||||
ordinal_date_time_no_millis, //
|
||||
time, //
|
||||
time_no_millis, //
|
||||
t_time, //
|
||||
t_time_no_millis, //
|
||||
week_date, //
|
||||
week_date_time, //
|
||||
week_date_time_no_millis, //
|
||||
weekyear, //
|
||||
weekyear_week, //
|
||||
weekyear_week_day, //
|
||||
year, //
|
||||
year_month, //
|
||||
year_month_day //
|
||||
}
|
||||
|
||||
@@ -53,17 +53,6 @@ public @interface Document {
|
||||
*/
|
||||
String indexName();
|
||||
|
||||
/**
|
||||
* Mapping type name. <br/>
|
||||
* deprecated as Elasticsearch does not support this anymore
|
||||
* (@see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/7.3/removal-of-types.html">Elastisearch removal of types documentation</a>) and will remove it in
|
||||
* Elasticsearch 8.
|
||||
*
|
||||
* @deprecated since 4.0
|
||||
*/
|
||||
@Deprecated
|
||||
String type() default "";
|
||||
|
||||
/**
|
||||
* Use server-side settings when creating the index.
|
||||
*/
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ import org.springframework.data.annotation.Persistent;
|
||||
* Elasticsearch dynamic templates mapping.
|
||||
* This annotation is handy if you prefer apply dynamic templates on fields with annotation e.g. {@link Field}
|
||||
* with type = FieldType.Object etc. instead of static mapping on Document via {@link Mapping} annotation.
|
||||
* DynamicTemplates annotation is ommited if {@link Mapping} annotation is used.
|
||||
* DynamicTemplates annotation is omitted if {@link Mapping} annotation is used.
|
||||
*
|
||||
* @author Petr Kukral
|
||||
*/
|
||||
|
||||
+99
-59
@@ -27,8 +27,7 @@ import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.FluxSink;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.netty.http.client.HttpClient;
|
||||
import reactor.netty.tcp.ProxyProvider;
|
||||
import reactor.netty.tcp.TcpClient;
|
||||
import reactor.netty.transport.ProxyProvider;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
@@ -55,10 +54,14 @@ import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
|
||||
import org.elasticsearch.action.admin.indices.flush.FlushRequest;
|
||||
import org.elasticsearch.action.admin.indices.flush.FlushResponse;
|
||||
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
|
||||
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest;
|
||||
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse;
|
||||
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
|
||||
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
|
||||
import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
|
||||
import org.elasticsearch.action.admin.indices.refresh.RefreshResponse;
|
||||
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
|
||||
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse;
|
||||
import org.elasticsearch.action.bulk.BulkRequest;
|
||||
import org.elasticsearch.action.bulk.BulkResponse;
|
||||
import org.elasticsearch.action.delete.DeleteRequest;
|
||||
@@ -93,6 +96,7 @@ import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.search.SearchHit;
|
||||
import org.elasticsearch.search.SearchHits;
|
||||
import org.elasticsearch.search.aggregations.Aggregation;
|
||||
import org.elasticsearch.search.suggest.Suggest;
|
||||
import org.reactivestreams.Publisher;
|
||||
import org.springframework.data.elasticsearch.client.ClientConfiguration;
|
||||
import org.springframework.data.elasticsearch.client.ClientLogger;
|
||||
@@ -128,6 +132,7 @@ import org.springframework.web.reactive.function.client.WebClient.RequestBodySpe
|
||||
* @author Henrique Amaral
|
||||
* @author Roman Puchkovskiy
|
||||
* @author Russell Parry
|
||||
* @author Thomas Geese
|
||||
* @since 3.2
|
||||
* @see ClientConfiguration
|
||||
* @see ReactiveRestClients
|
||||
@@ -235,14 +240,14 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
|
||||
Duration connectTimeout = clientConfiguration.getConnectTimeout();
|
||||
Duration soTimeout = clientConfiguration.getSocketTimeout();
|
||||
|
||||
TcpClient tcpClient = TcpClient.create();
|
||||
HttpClient httpClient = HttpClient.create().compress(true);
|
||||
|
||||
if (!connectTimeout.isNegative()) {
|
||||
tcpClient = tcpClient.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, Math.toIntExact(connectTimeout.toMillis()));
|
||||
httpClient = httpClient.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, Math.toIntExact(connectTimeout.toMillis()));
|
||||
}
|
||||
|
||||
if (!soTimeout.isNegative()) {
|
||||
tcpClient = tcpClient.doOnConnected(connection -> connection //
|
||||
httpClient = httpClient.doOnConnected(connection -> connection //
|
||||
.addHandlerLast(new ReadTimeoutHandler(soTimeout.toMillis(), TimeUnit.MILLISECONDS))
|
||||
.addHandlerLast(new WriteTimeoutHandler(soTimeout.toMillis(), TimeUnit.MILLISECONDS)));
|
||||
}
|
||||
@@ -254,12 +259,11 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
|
||||
if (hostPort.length != 2) {
|
||||
throw new IllegalArgumentException("invalid proxy configuration " + proxy + ", should be \"host:port\"");
|
||||
}
|
||||
tcpClient = tcpClient.proxy(proxyOptions -> proxyOptions.type(ProxyProvider.Proxy.HTTP).host(hostPort[0])
|
||||
httpClient = httpClient.proxy(proxyOptions -> proxyOptions.type(ProxyProvider.Proxy.HTTP).host(hostPort[0])
|
||||
.port(Integer.parseInt(hostPort[1])));
|
||||
}
|
||||
|
||||
String scheme = "http";
|
||||
HttpClient httpClient = HttpClient.from(tcpClient);
|
||||
|
||||
if (clientConfiguration.useSsl()) {
|
||||
|
||||
@@ -297,7 +301,7 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
|
||||
public Mono<Boolean> ping(HttpHeaders headers) {
|
||||
|
||||
return sendRequest(new MainRequest(), requestCreator.ping(), RawActionResponse.class, headers) //
|
||||
.map(response -> response.statusCode().is2xxSuccessful()) //
|
||||
.flatMap(response -> response.releaseBody().thenReturn(response.statusCode().is2xxSuccessful())) //
|
||||
.onErrorResume(NoReachableHostException.class, error -> Mono.just(false)).next();
|
||||
}
|
||||
|
||||
@@ -347,7 +351,7 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
|
||||
public Mono<Boolean> exists(HttpHeaders headers, GetRequest getRequest) {
|
||||
|
||||
return sendRequest(getRequest, requestCreator.exists(), RawActionResponse.class, headers) //
|
||||
.map(response -> response.statusCode().is2xxSuccessful()) //
|
||||
.flatMap(response -> response.releaseBody().thenReturn(response.statusCode().is2xxSuccessful())) //
|
||||
.next();
|
||||
}
|
||||
|
||||
@@ -547,30 +551,24 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
|
||||
public Mono<Boolean> existsIndex(HttpHeaders headers, GetIndexRequest request) {
|
||||
|
||||
return sendRequest(request, requestCreator.indexExists(), RawActionResponse.class, headers) //
|
||||
.map(response -> response.statusCode().is2xxSuccessful()) //
|
||||
.flatMap(response -> response.releaseBody().thenReturn(response.statusCode().is2xxSuccessful())) //
|
||||
.next();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient.Indices#deleteIndex(org.springframework.http.HttpHeaders, org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest)
|
||||
*/
|
||||
@Override
|
||||
public Mono<Void> deleteIndex(HttpHeaders headers, DeleteIndexRequest request) {
|
||||
public Mono<Boolean> deleteIndex(HttpHeaders headers, DeleteIndexRequest request) {
|
||||
|
||||
return sendRequest(request, requestCreator.indexDelete(), AcknowledgedResponse.class, headers) //
|
||||
.then();
|
||||
.map(AcknowledgedResponse::isAcknowledged) //
|
||||
.next();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient.Indices#createIndex(org.springframework.http.HttpHeaders, org.elasticsearch.action.admin.indices.create.CreateIndexRequest)
|
||||
*/
|
||||
@Override
|
||||
public Mono<Void> createIndex(HttpHeaders headers, CreateIndexRequest createIndexRequest) {
|
||||
public Mono<Boolean> createIndex(HttpHeaders headers, CreateIndexRequest createIndexRequest) {
|
||||
|
||||
return sendRequest(createIndexRequest, requestCreator.indexCreate(), AcknowledgedResponse.class, headers) //
|
||||
.then();
|
||||
.map(AcknowledgedResponse::isAcknowledged) //
|
||||
.next();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -606,15 +604,12 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
|
||||
.then();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient.Indices#updateMapping(org.springframework.http.HttpHeaders, org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest)
|
||||
*/
|
||||
@Override
|
||||
public Mono<Void> updateMapping(HttpHeaders headers, PutMappingRequest putMappingRequest) {
|
||||
public Mono<Boolean> putMapping(HttpHeaders headers, PutMappingRequest putMappingRequest) {
|
||||
|
||||
return sendRequest(putMappingRequest, requestCreator.putMapping(), AcknowledgedResponse.class, headers) //
|
||||
.then();
|
||||
.map(AcknowledgedResponse::isAcknowledged) //
|
||||
.next();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -628,6 +623,16 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
|
||||
.then();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<GetMappingsResponse> getMapping(HttpHeaders headers, GetMappingsRequest getMappingsRequest) {
|
||||
return sendRequest(getMappingsRequest, requestCreator.getMapping(), GetMappingsResponse.class, headers).next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<GetSettingsResponse> getSettings(HttpHeaders headers, GetSettingsRequest getSettingsRequest) {
|
||||
return sendRequest(getSettingsRequest, requestCreator.getSettings(), GetSettingsResponse.class, headers).next();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient#ping(org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient.ReactiveElasticsearchClientCallback)
|
||||
@@ -804,53 +809,88 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
|
||||
|
||||
private <T> Publisher<? extends T> handleServerError(Request request, ClientResponse response) {
|
||||
|
||||
RestStatus status = RestStatus.fromCode(response.statusCode().value());
|
||||
int statusCode = response.statusCode().value();
|
||||
RestStatus status = RestStatus.fromCode(statusCode);
|
||||
String mediaType = response.headers().contentType().map(MediaType::toString).orElse(XContentType.JSON.mediaType());
|
||||
|
||||
return Mono.error(new ElasticsearchStatusException(String.format("%s request to %s returned error code %s.",
|
||||
request.getMethod(), request.getEndpoint(), response.statusCode().value()), status));
|
||||
return response.body(BodyExtractors.toMono(byte[].class)) //
|
||||
.map(bytes -> new String(bytes, StandardCharsets.UTF_8)) //
|
||||
.flatMap(content -> contentOrError(content, mediaType, status))
|
||||
.flatMap(unused -> Mono
|
||||
.error(new ElasticsearchStatusException(String.format("%s request to %s returned error code %s.",
|
||||
request.getMethod(), request.getEndpoint(), statusCode), status)));
|
||||
}
|
||||
|
||||
private <T> Publisher<? extends T> handleClientError(String logId, Request request, ClientResponse response,
|
||||
Class<T> responseType) {
|
||||
|
||||
int statusCode = response.statusCode().value();
|
||||
RestStatus status = RestStatus.fromCode(statusCode);
|
||||
String mediaType = response.headers().contentType().map(MediaType::toString).orElse(XContentType.JSON.mediaType());
|
||||
|
||||
return response.body(BodyExtractors.toMono(byte[].class)) //
|
||||
.map(bytes -> new String(bytes, StandardCharsets.UTF_8)) //
|
||||
.flatMap(content -> {
|
||||
String mediaType = response.headers().contentType().map(MediaType::toString)
|
||||
.orElse(XContentType.JSON.mediaType());
|
||||
RestStatus status = RestStatus.fromCode(response.statusCode().value());
|
||||
try {
|
||||
ElasticsearchException exception = getElasticsearchException(response, content, mediaType);
|
||||
if (exception != null) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
buildExceptionMessages(sb, exception);
|
||||
return Mono.error(new ElasticsearchStatusException(sb.toString(), status, exception));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return Mono.error(new ElasticsearchStatusException(content, status));
|
||||
}
|
||||
return Mono.just(content);
|
||||
}).doOnNext(it -> ClientLogger.logResponse(logId, response.statusCode(), it)) //
|
||||
.flatMap(content -> contentOrError(content, mediaType, status)) //
|
||||
.doOnNext(content -> ClientLogger.logResponse(logId, response.statusCode(), content)) //
|
||||
.flatMap(content -> doDecode(response, responseType, content));
|
||||
}
|
||||
|
||||
// region ElasticsearchException helper
|
||||
/**
|
||||
* checks if the given content body contains an {@link ElasticsearchException}, if yes it is returned in a Mono.error.
|
||||
* Otherwise the content is returned in the Mono
|
||||
*
|
||||
* @param content the content to analyze
|
||||
* @param mediaType the returned media type
|
||||
* @param status the response status
|
||||
* @return a Mono with the content or an Mono.error
|
||||
*/
|
||||
private static Mono<String> contentOrError(String content, String mediaType, RestStatus status) {
|
||||
|
||||
ElasticsearchException exception = getElasticsearchException(content, mediaType, status);
|
||||
|
||||
if (exception != null) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
buildExceptionMessages(sb, exception);
|
||||
return Mono.error(new ElasticsearchStatusException(sb.toString(), status, exception));
|
||||
}
|
||||
|
||||
return Mono.just(content);
|
||||
}
|
||||
|
||||
/**
|
||||
* tries to parse an {@link ElasticsearchException} from the given body content
|
||||
*
|
||||
* @param content the content to analyse
|
||||
* @param mediaType the type of the body content
|
||||
* @return an {@link ElasticsearchException} or {@literal null}.
|
||||
*/
|
||||
@Nullable
|
||||
private ElasticsearchException getElasticsearchException(ClientResponse response, String content, String mediaType)
|
||||
throws IOException {
|
||||
private static ElasticsearchException getElasticsearchException(String content, String mediaType, RestStatus status) {
|
||||
|
||||
XContentParser parser = createParser(mediaType, content);
|
||||
// we have a JSON object with an error and a status field
|
||||
XContentParser.Token token = parser.nextToken(); // Skip START_OBJECT
|
||||
try {
|
||||
XContentParser parser = createParser(mediaType, content);
|
||||
// we have a JSON object with an error and a status field
|
||||
XContentParser.Token token = parser.nextToken(); // Skip START_OBJECT
|
||||
|
||||
do {
|
||||
token = parser.nextToken();
|
||||
do {
|
||||
token = parser.nextToken();
|
||||
|
||||
if (parser.currentName().equals("error")) {
|
||||
return ElasticsearchException.failureFromXContent(parser);
|
||||
}
|
||||
} while (token == XContentParser.Token.FIELD_NAME);
|
||||
return null;
|
||||
if (parser.currentName().equals("error")) {
|
||||
return ElasticsearchException.failureFromXContent(parser);
|
||||
}
|
||||
} while (token == XContentParser.Token.FIELD_NAME);
|
||||
|
||||
return null;
|
||||
} catch (IOException e) {
|
||||
return new ElasticsearchStatusException(content, status);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<Suggest> suggest(HttpHeaders headers, SearchRequest searchRequest) {
|
||||
return sendRequest(searchRequest, requestCreator.search(), SearchResponse.class, headers) //
|
||||
.map(SearchResponse::getSuggest);
|
||||
}
|
||||
|
||||
private static void buildExceptionMessages(StringBuilder sb, Throwable t) {
|
||||
|
||||
+6
-5
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.client.reactive;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.util.function.Tuple2;
|
||||
@@ -33,6 +32,7 @@ import java.util.function.Supplier;
|
||||
import org.springframework.data.elasticsearch.client.ElasticsearchHost;
|
||||
import org.springframework.data.elasticsearch.client.ElasticsearchHost.State;
|
||||
import org.springframework.data.elasticsearch.client.NoReachableHostException;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.web.reactive.function.client.ClientResponse;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
@@ -121,15 +121,15 @@ class MultiNodeHostProvider implements HostProvider {
|
||||
.map(ElasticsearchHost::getEndpoint).next();
|
||||
}
|
||||
|
||||
private ElasticsearchHost updateNodeState(Tuple2<InetSocketAddress, ClientResponse> tuple2) {
|
||||
private ElasticsearchHost updateNodeState(Tuple2<InetSocketAddress, State> tuple2) {
|
||||
|
||||
State state = tuple2.getT2().statusCode().isError() ? State.OFFLINE : State.ONLINE;
|
||||
State state = tuple2.getT2();
|
||||
ElasticsearchHost elasticsearchHost = new ElasticsearchHost(tuple2.getT1(), state);
|
||||
hosts.put(tuple2.getT1(), elasticsearchHost);
|
||||
return elasticsearchHost;
|
||||
}
|
||||
|
||||
private Flux<Tuple2<InetSocketAddress, ClientResponse>> nodes(@Nullable State state) {
|
||||
private Flux<Tuple2<InetSocketAddress, State>> nodes(@Nullable State state) {
|
||||
|
||||
return Flux.fromIterable(hosts()) //
|
||||
.filter(entry -> state == null || entry.getState().equals(state)) //
|
||||
@@ -144,7 +144,8 @@ class MultiNodeHostProvider implements HostProvider {
|
||||
clientProvider.getErrorListener().accept(throwable);
|
||||
});
|
||||
|
||||
return Mono.just(host).zipWith(exchange);
|
||||
return Mono.just(host).zipWith(exchange
|
||||
.flatMap(it -> it.releaseBody().thenReturn(it.statusCode().isError() ? State.OFFLINE : State.ONLINE)));
|
||||
}) //
|
||||
.onErrorContinue((throwable, o) -> clientProvider.getErrorListener().accept(throwable));
|
||||
}
|
||||
|
||||
+11
-1
@@ -15,11 +15,12 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.client.reactive;
|
||||
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.elasticsearch.action.ActionResponse;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.client.reactive.ClientHttpResponse;
|
||||
@@ -73,4 +74,13 @@ class RawActionResponse extends ActionResponse {
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the response body is released to properly release the underlying connection.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Mono<Void> releaseBody() {
|
||||
return delegate.releaseBody();
|
||||
}
|
||||
}
|
||||
|
||||
+194
-20
@@ -27,9 +27,13 @@ import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
|
||||
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
|
||||
import org.elasticsearch.action.admin.indices.flush.FlushRequest;
|
||||
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
|
||||
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest;
|
||||
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse;
|
||||
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
|
||||
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
|
||||
import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
|
||||
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
|
||||
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse;
|
||||
import org.elasticsearch.action.bulk.BulkRequest;
|
||||
import org.elasticsearch.action.bulk.BulkResponse;
|
||||
import org.elasticsearch.action.delete.DeleteRequest;
|
||||
@@ -48,6 +52,7 @@ import org.elasticsearch.index.reindex.BulkByScrollResponse;
|
||||
import org.elasticsearch.index.reindex.DeleteByQueryRequest;
|
||||
import org.elasticsearch.search.SearchHit;
|
||||
import org.elasticsearch.search.aggregations.Aggregation;
|
||||
import org.elasticsearch.search.suggest.Suggest;
|
||||
import org.springframework.data.elasticsearch.client.ClientConfiguration;
|
||||
import org.springframework.data.elasticsearch.client.ElasticsearchHost;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
@@ -63,6 +68,7 @@ import org.springframework.web.reactive.function.client.WebClient;
|
||||
* @author Mark Paluch
|
||||
* @author Peter-Josef Meisch
|
||||
* @author Henrique Amaral
|
||||
* @author Thomas Geese
|
||||
* @since 3.2
|
||||
* @see ClientConfiguration
|
||||
* @see ReactiveRestClients
|
||||
@@ -413,14 +419,48 @@ public interface ReactiveElasticsearchClient {
|
||||
*/
|
||||
Flux<SearchHit> search(HttpHeaders headers, SearchRequest searchRequest);
|
||||
|
||||
/**
|
||||
* Execute the given {@link SearchRequest} against the {@literal search} API.
|
||||
*
|
||||
* @param consumer never {@literal null}.
|
||||
* @return the {@link Flux} emitting {@link Suggest suggestions} one by one.
|
||||
* @since 4.1
|
||||
*/
|
||||
default Flux<Suggest> suggest(Consumer<SearchRequest> consumer) {
|
||||
|
||||
SearchRequest request = new SearchRequest();
|
||||
consumer.accept(request);
|
||||
return suggest(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the given {@link SearchRequest} against the {@literal search} API.
|
||||
*
|
||||
* @param searchRequest must not be {@literal null}.
|
||||
* @return the {@link Flux} emitting {@link Suggest suggestions} one by one.
|
||||
* @since 4.1
|
||||
*/
|
||||
default Flux<Suggest> suggest(SearchRequest searchRequest) {
|
||||
return suggest(HttpHeaders.EMPTY, searchRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the given {@link SearchRequest} against the {@literal search} API.
|
||||
*
|
||||
* @param headers Use {@link HttpHeaders} to provide eg. authentication data. Must not be {@literal null}.
|
||||
* @param searchRequest must not be {@literal null}.
|
||||
* @return the {@link Flux} emitting {@link Suggest suggestions} one by one.
|
||||
* @since 4.1
|
||||
*/
|
||||
Flux<Suggest> suggest(HttpHeaders headers, SearchRequest searchRequest);
|
||||
|
||||
/**
|
||||
* Execute the given {@link SearchRequest} with aggregations against the {@literal search} API.
|
||||
*
|
||||
* @param consumer
|
||||
* never {@literal null}.
|
||||
* @param consumer never {@literal null}.
|
||||
* @return the {@link Flux} emitting {@link Aggregation} one by one.
|
||||
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/search-search.html">Search API on
|
||||
* elastic.co</a>
|
||||
* elastic.co</a>
|
||||
* @since 4.0
|
||||
*/
|
||||
default Flux<Aggregation> aggregate(Consumer<SearchRequest> consumer) {
|
||||
@@ -674,7 +714,7 @@ public interface ReactiveElasticsearchClient {
|
||||
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-delete-index.html"> Indices
|
||||
* Delete API on elastic.co</a>
|
||||
*/
|
||||
default Mono<Void> deleteIndex(Consumer<DeleteIndexRequest> consumer) {
|
||||
default Mono<Boolean> deleteIndex(Consumer<DeleteIndexRequest> consumer) {
|
||||
|
||||
DeleteIndexRequest request = new DeleteIndexRequest();
|
||||
consumer.accept(request);
|
||||
@@ -690,7 +730,7 @@ public interface ReactiveElasticsearchClient {
|
||||
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-delete-index.html"> Indices
|
||||
* Delete API on elastic.co</a>
|
||||
*/
|
||||
default Mono<Void> deleteIndex(DeleteIndexRequest deleteIndexRequest) {
|
||||
default Mono<Boolean> deleteIndex(DeleteIndexRequest deleteIndexRequest) {
|
||||
return deleteIndex(HttpHeaders.EMPTY, deleteIndexRequest);
|
||||
}
|
||||
|
||||
@@ -704,18 +744,18 @@ public interface ReactiveElasticsearchClient {
|
||||
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-delete-index.html"> Indices
|
||||
* Delete API on elastic.co</a>
|
||||
*/
|
||||
Mono<Void> deleteIndex(HttpHeaders headers, DeleteIndexRequest deleteIndexRequest);
|
||||
Mono<Boolean> deleteIndex(HttpHeaders headers, DeleteIndexRequest deleteIndexRequest);
|
||||
|
||||
/**
|
||||
* Execute the given {@link CreateIndexRequest} against the {@literal indices} API.
|
||||
*
|
||||
* @param consumer never {@literal null}.
|
||||
* @return a {@link Mono} signalling operation completion or an {@link Mono#error(Throwable) error} if eg. the index
|
||||
* already exist.
|
||||
* @return a {@link Mono} signalling successful operation completion or an {@link Mono#error(Throwable) error} if
|
||||
* eg. the index already exist.
|
||||
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-create-index.html"> Indices
|
||||
* Create API on elastic.co</a>
|
||||
*/
|
||||
default Mono<Void> createIndex(Consumer<CreateIndexRequest> consumer) {
|
||||
default Mono<Boolean> createIndex(Consumer<CreateIndexRequest> consumer) {
|
||||
|
||||
CreateIndexRequest request = new CreateIndexRequest();
|
||||
consumer.accept(request);
|
||||
@@ -726,12 +766,12 @@ public interface ReactiveElasticsearchClient {
|
||||
* Execute the given {@link CreateIndexRequest} against the {@literal indices} API.
|
||||
*
|
||||
* @param createIndexRequest must not be {@literal null}.
|
||||
* @return a {@link Mono} signalling operation completion or an {@link Mono#error(Throwable) error} if eg. the index
|
||||
* already exist.
|
||||
* @return a {@link Mono} signalling successful operation completion or an {@link Mono#error(Throwable) error} if
|
||||
* eg. the index already exist.
|
||||
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-create-index.html"> Indices
|
||||
* Create API on elastic.co</a>
|
||||
*/
|
||||
default Mono<Void> createIndex(CreateIndexRequest createIndexRequest) {
|
||||
default Mono<Boolean> createIndex(CreateIndexRequest createIndexRequest) {
|
||||
return createIndex(HttpHeaders.EMPTY, createIndexRequest);
|
||||
}
|
||||
|
||||
@@ -740,12 +780,12 @@ public interface ReactiveElasticsearchClient {
|
||||
*
|
||||
* @param headers Use {@link HttpHeaders} to provide eg. authentication data. Must not be {@literal null}.
|
||||
* @param createIndexRequest must not be {@literal null}.
|
||||
* @return a {@link Mono} signalling operation completion or an {@link Mono#error(Throwable) error} if eg. the index
|
||||
* already exist.
|
||||
* @return a {@link Mono} signalling successful operation completion or an {@link Mono#error(Throwable) error} if
|
||||
* eg. the index already exist.
|
||||
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-create-index.html"> Indices
|
||||
* Create API on elastic.co</a>
|
||||
*/
|
||||
Mono<Void> createIndex(HttpHeaders headers, CreateIndexRequest createIndexRequest);
|
||||
Mono<Boolean> createIndex(HttpHeaders headers, CreateIndexRequest createIndexRequest);
|
||||
|
||||
/**
|
||||
* Execute the given {@link OpenIndexRequest} against the {@literal indices} API.
|
||||
@@ -878,12 +918,58 @@ public interface ReactiveElasticsearchClient {
|
||||
* does not exist.
|
||||
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-put-mapping.html"> Indices
|
||||
* Put Mapping API on elastic.co</a>
|
||||
* @deprecated since 4.1, use {@link #putMapping(Consumer)}
|
||||
*/
|
||||
default Mono<Void> updateMapping(Consumer<PutMappingRequest> consumer) {
|
||||
@Deprecated
|
||||
default Mono<Boolean> updateMapping(Consumer<PutMappingRequest> consumer) {
|
||||
return putMapping(consumer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the given {@link PutMappingRequest} against the {@literal indices} API.
|
||||
*
|
||||
* @param putMappingRequest must not be {@literal null}.
|
||||
* @return a {@link Mono} signalling operation completion or an {@link Mono#error(Throwable) error} if eg. the index
|
||||
* does not exist.
|
||||
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-put-mapping.html"> Indices
|
||||
* Put Mapping API on elastic.co</a>
|
||||
* @deprecated since 4.1, use {@link #putMapping(PutMappingRequest)}
|
||||
*/
|
||||
@Deprecated
|
||||
default Mono<Boolean> updateMapping(PutMappingRequest putMappingRequest) {
|
||||
return putMapping(putMappingRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the given {@link PutMappingRequest} against the {@literal indices} API.
|
||||
*
|
||||
* @param headers Use {@link HttpHeaders} to provide eg. authentication data. Must not be {@literal null}.
|
||||
* @param putMappingRequest must not be {@literal null}.
|
||||
* @return a {@link Mono} signalling operation completion or an {@link Mono#error(Throwable) error} if eg. the index
|
||||
* does not exist.
|
||||
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-put-mapping.html"> Indices
|
||||
* Put Mapping API on elastic.co</a>
|
||||
* @deprecated since 4.1, use {@link #putMapping(HttpHeaders, PutMappingRequest)}
|
||||
*/
|
||||
@Deprecated
|
||||
default Mono<Boolean> updateMapping(HttpHeaders headers, PutMappingRequest putMappingRequest) {
|
||||
return putMapping(headers, putMappingRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the given {@link PutMappingRequest} against the {@literal indices} API.
|
||||
*
|
||||
* @param consumer never {@literal null}.
|
||||
* @return a {@link Mono} signalling operation completion or an {@link Mono#error(Throwable) error} if eg. the index
|
||||
* does not exist.
|
||||
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-put-mapping.html"> Indices
|
||||
* Put Mapping API on elastic.co</a>
|
||||
*/
|
||||
default Mono<Boolean> putMapping(Consumer<PutMappingRequest> consumer) {
|
||||
|
||||
PutMappingRequest request = new PutMappingRequest();
|
||||
consumer.accept(request);
|
||||
return updateMapping(request);
|
||||
return putMapping(request);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -895,8 +981,8 @@ public interface ReactiveElasticsearchClient {
|
||||
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-put-mapping.html"> Indices
|
||||
* Put Mapping API on elastic.co</a>
|
||||
*/
|
||||
default Mono<Void> updateMapping(PutMappingRequest putMappingRequest) {
|
||||
return updateMapping(HttpHeaders.EMPTY, putMappingRequest);
|
||||
default Mono<Boolean> putMapping(PutMappingRequest putMappingRequest) {
|
||||
return putMapping(HttpHeaders.EMPTY, putMappingRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -909,7 +995,7 @@ public interface ReactiveElasticsearchClient {
|
||||
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-put-mapping.html"> Indices
|
||||
* Put Mapping API on elastic.co</a>
|
||||
*/
|
||||
Mono<Void> updateMapping(HttpHeaders headers, PutMappingRequest putMappingRequest);
|
||||
Mono<Boolean> putMapping(HttpHeaders headers, PutMappingRequest putMappingRequest);
|
||||
|
||||
/**
|
||||
* Execute the given {@link FlushRequest} against the {@literal indices} API.
|
||||
@@ -951,5 +1037,93 @@ public interface ReactiveElasticsearchClient {
|
||||
* API on elastic.co</a>
|
||||
*/
|
||||
Mono<Void> flushIndex(HttpHeaders headers, FlushRequest flushRequest);
|
||||
|
||||
/**
|
||||
* Execute the given {@link GetSettingsRequest} against the {@literal indices} API.
|
||||
*
|
||||
* @param consumer never {@literal null}.
|
||||
* @return a {@link Mono} signalling operation completion or an {@link Mono#error(Throwable) error} if eg. the index
|
||||
* does not exist.
|
||||
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-get-settings.html"> Indices
|
||||
* Flush API on elastic.co</a>
|
||||
* @since 4.1
|
||||
*/
|
||||
default Mono<GetSettingsResponse> getSettings(Consumer<GetSettingsRequest> consumer) {
|
||||
|
||||
GetSettingsRequest request = new GetSettingsRequest();
|
||||
consumer.accept(request);
|
||||
return getSettings(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the given {@link GetSettingsRequest} against the {@literal indices} API.
|
||||
*
|
||||
* @param getSettingsRequest must not be {@literal null}.
|
||||
* @return a {@link Mono} signalling operation completion or an {@link Mono#error(Throwable) error} if eg. the index
|
||||
* does not exist.
|
||||
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-get-settings.html"> Indices
|
||||
* Flush API on elastic.co</a>
|
||||
* @since 4.1
|
||||
*/
|
||||
default Mono<GetSettingsResponse> getSettings(GetSettingsRequest getSettingsRequest) {
|
||||
return getSettings(HttpHeaders.EMPTY, getSettingsRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the given {@link GetSettingsRequest} against the {@literal indices} API.
|
||||
*
|
||||
* @param headers Use {@link HttpHeaders} to provide eg. authentication data. Must not be {@literal null}.
|
||||
* @param getSettingsRequest must not be {@literal null}.
|
||||
* @return a {@link Mono} signalling operation completion or an {@link Mono#error(Throwable) error} if eg. the index
|
||||
* does not exist.
|
||||
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-get-settings.html"> Indices
|
||||
* Flush API on elastic.co</a>
|
||||
* @since 4.1
|
||||
*/
|
||||
Mono<GetSettingsResponse> getSettings(HttpHeaders headers, GetSettingsRequest getSettingsRequest);
|
||||
|
||||
/**
|
||||
* Execute the given {@link GetMappingsRequest} against the {@literal indices} API.
|
||||
*
|
||||
* @param consumer never {@literal null}.
|
||||
* @return a {@link Mono} signalling operation completion or an {@link Mono#error(Throwable) error} if eg. the index
|
||||
* does not exist.
|
||||
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-get-mapping.html"> Indices
|
||||
* Flush API on elastic.co</a>
|
||||
* @since 4.1
|
||||
*/
|
||||
default Mono<GetMappingsResponse> getMapping(Consumer<GetMappingsRequest> consumer) {
|
||||
|
||||
GetMappingsRequest request = new GetMappingsRequest();
|
||||
consumer.accept(request);
|
||||
return getMapping(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the given {@link GetMappingsRequest} against the {@literal indices} API.
|
||||
*
|
||||
* @param getMappingsRequest must not be {@literal null}.
|
||||
* @return a {@link Mono} signalling operation completion or an {@link Mono#error(Throwable) error} if eg. the index
|
||||
* does not exist.
|
||||
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-get-mapping.html"> Indices
|
||||
* Flush API on elastic.co</a>
|
||||
* @since 4.1
|
||||
*/
|
||||
default Mono<GetMappingsResponse> getMapping(GetMappingsRequest getMappingsRequest) {
|
||||
return getMapping(HttpHeaders.EMPTY, getMappingsRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the given {@link GetMappingsRequest} against the {@literal indices} API.
|
||||
*
|
||||
* @param headers Use {@link HttpHeaders} to provide eg. authentication data. Must not be {@literal null}.
|
||||
* @param getMappingsRequest must not be {@literal null}.
|
||||
* @return a {@link Mono} signalling operation completion or an {@link Mono#error(Throwable) error} if eg. the index
|
||||
* does not exist.
|
||||
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-get-mapping.html"> Indices
|
||||
* Flush API on elastic.co</a>
|
||||
* @since 4.1
|
||||
*/
|
||||
Mono<GetMappingsResponse> getMapping(HttpHeaders headers, GetMappingsRequest getMappingsRequest);
|
||||
}
|
||||
}
|
||||
|
||||
+18
-2
@@ -8,9 +8,11 @@ import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
|
||||
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
|
||||
import org.elasticsearch.action.admin.indices.flush.FlushRequest;
|
||||
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
|
||||
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest;
|
||||
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
|
||||
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
|
||||
import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
|
||||
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
|
||||
import org.elasticsearch.action.bulk.BulkRequest;
|
||||
import org.elasticsearch.action.delete.DeleteRequest;
|
||||
import org.elasticsearch.action.get.GetRequest;
|
||||
@@ -24,7 +26,7 @@ import org.elasticsearch.action.update.UpdateRequest;
|
||||
import org.elasticsearch.client.Request;
|
||||
import org.elasticsearch.client.core.CountRequest;
|
||||
import org.elasticsearch.index.reindex.DeleteByQueryRequest;
|
||||
import org.springframework.data.elasticsearch.ElasticsearchException;
|
||||
import org.springframework.data.elasticsearch.UncategorizedElasticsearchException;
|
||||
import org.springframework.data.elasticsearch.client.util.RequestConverters;
|
||||
|
||||
/**
|
||||
@@ -88,7 +90,7 @@ public interface RequestCreator {
|
||||
try {
|
||||
return RequestConverters.bulk(request);
|
||||
} catch (IOException e) {
|
||||
throw new ElasticsearchException("Could not parse request", e);
|
||||
throw new UncategorizedElasticsearchException("Could not parse request", e);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -131,4 +133,18 @@ public interface RequestCreator {
|
||||
return RequestConverters::count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.1
|
||||
*/
|
||||
default Function<GetSettingsRequest, Request> getSettings() {
|
||||
return RequestConverters::getSettings;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.1
|
||||
*/
|
||||
default Function<GetMappingsRequest, Request> getMapping() {
|
||||
return RequestConverters::getMapping;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+9
-7
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.client.reactive;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
@@ -25,6 +24,7 @@ import java.util.function.Supplier;
|
||||
import org.springframework.data.elasticsearch.client.ElasticsearchHost;
|
||||
import org.springframework.data.elasticsearch.client.ElasticsearchHost.State;
|
||||
import org.springframework.data.elasticsearch.client.NoReachableHostException;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
/**
|
||||
@@ -66,14 +66,14 @@ class SingleNodeHostProvider implements HostProvider {
|
||||
} else {
|
||||
state = ElasticsearchHost.online(endpoint);
|
||||
}
|
||||
return Mono.just(state);
|
||||
return it.releaseBody().thenReturn(state);
|
||||
}).onErrorResume(throwable -> {
|
||||
|
||||
state = ElasticsearchHost.offline(endpoint);
|
||||
clientProvider.getErrorListener().accept(throwable);
|
||||
return Mono.just(state);
|
||||
}) //
|
||||
.flatMap(it -> Mono.just(new ClusterInformation(Collections.singleton(it))));
|
||||
.map(it -> new ClusterInformation(Collections.singleton(it)));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -96,14 +96,16 @@ class SingleNodeHostProvider implements HostProvider {
|
||||
return Mono.just(endpoint);
|
||||
}
|
||||
|
||||
return clusterInfo().flatMap(it -> {
|
||||
return clusterInfo().handle((information, sink) -> {
|
||||
|
||||
ElasticsearchHost host = it.getNodes().iterator().next();
|
||||
ElasticsearchHost host = information.getNodes().iterator().next();
|
||||
if (host.isOnline()) {
|
||||
return Mono.just(host.getEndpoint());
|
||||
|
||||
sink.next(host.getEndpoint());
|
||||
return;
|
||||
}
|
||||
|
||||
return Mono.error(() -> new NoReachableHostException(Collections.singleton(host)));
|
||||
sink.error(new NoReachableHostException(Collections.singleton(host)));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+32
-2
@@ -38,9 +38,11 @@ import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
|
||||
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
|
||||
import org.elasticsearch.action.admin.indices.flush.FlushRequest;
|
||||
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
|
||||
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest;
|
||||
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
|
||||
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
|
||||
import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
|
||||
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
|
||||
import org.elasticsearch.action.bulk.BulkRequest;
|
||||
import org.elasticsearch.action.delete.DeleteRequest;
|
||||
import org.elasticsearch.action.explain.ExplainRequest;
|
||||
@@ -751,12 +753,12 @@ public class RequestConverters {
|
||||
}
|
||||
|
||||
Request request = new Request(HttpMethod.PUT.name(),
|
||||
RequestConverters.endpoint(putMappingRequest.indices(), "_mapping", putMappingRequest.type()));
|
||||
RequestConverters.endpoint(putMappingRequest.indices(), "_mapping"));
|
||||
|
||||
RequestConverters.Params parameters = new RequestConverters.Params(request) //
|
||||
.withTimeout(putMappingRequest.timeout()) //
|
||||
.withMasterTimeout(putMappingRequest.masterNodeTimeout()) //
|
||||
.withIncludeTypeName(true);
|
||||
.withIncludeTypeName(false);
|
||||
request.setEntity(RequestConverters.createEntity(putMappingRequest, RequestConverters.REQUEST_BODY_CONTENT_TYPE));
|
||||
return request;
|
||||
}
|
||||
@@ -772,6 +774,34 @@ public class RequestConverters {
|
||||
return request;
|
||||
}
|
||||
|
||||
public static Request getMapping(GetMappingsRequest getMappingsRequest) {
|
||||
String[] indices = getMappingsRequest.indices() == null ? Strings.EMPTY_ARRAY : getMappingsRequest.indices();
|
||||
String[] types = getMappingsRequest.types() == null ? Strings.EMPTY_ARRAY : getMappingsRequest.types();
|
||||
|
||||
Request request = new Request(HttpMethod.GET.name(), RequestConverters.endpoint(indices, "_mapping", types));
|
||||
|
||||
RequestConverters.Params parameters = new RequestConverters.Params(request);
|
||||
parameters.withMasterTimeout(getMappingsRequest.masterNodeTimeout());
|
||||
parameters.withIndicesOptions(getMappingsRequest.indicesOptions());
|
||||
parameters.withLocal(getMappingsRequest.local());
|
||||
parameters.withIncludeTypeName(false);
|
||||
return request;
|
||||
}
|
||||
|
||||
public static Request getSettings(GetSettingsRequest getSettingsRequest) {
|
||||
String[] indices = getSettingsRequest.indices() == null ? Strings.EMPTY_ARRAY : getSettingsRequest.indices();
|
||||
String[] names = getSettingsRequest.names() == null ? Strings.EMPTY_ARRAY : getSettingsRequest.names();
|
||||
|
||||
Request request = new Request(HttpMethod.GET.name(), RequestConverters.endpoint(indices, "_settings", names));
|
||||
|
||||
RequestConverters.Params parameters = new RequestConverters.Params(request);
|
||||
parameters.withIndicesOptions(getSettingsRequest.indicesOptions());
|
||||
parameters.withLocal(getSettingsRequest.local());
|
||||
parameters.withIncludeDefaults(getSettingsRequest.includeDefaults());
|
||||
parameters.withMasterTimeout(getSettingsRequest.masterNodeTimeout());
|
||||
return request;
|
||||
}
|
||||
|
||||
static HttpEntity createEntity(ToXContent toXContent, XContentType xContentType) {
|
||||
|
||||
try {
|
||||
|
||||
+44
-45
@@ -17,13 +17,11 @@ package org.springframework.data.elasticsearch.core;
|
||||
|
||||
import static org.springframework.util.StringUtils.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse;
|
||||
import org.elasticsearch.cluster.metadata.AliasMetaData;
|
||||
import org.elasticsearch.common.collect.MapBuilder;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -38,6 +36,7 @@ import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersiste
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
import org.springframework.data.elasticsearch.core.query.AliasQuery;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -55,20 +54,24 @@ abstract class AbstractDefaultIndexOperations implements IndexOperations {
|
||||
protected final RequestFactory requestFactory;
|
||||
|
||||
@Nullable protected final Class<?> boundClass;
|
||||
private final IndexCoordinates boundIndex;
|
||||
@Nullable private final IndexCoordinates boundIndex;
|
||||
|
||||
public AbstractDefaultIndexOperations(ElasticsearchConverter elasticsearchConverter, Class<?> boundClass) {
|
||||
|
||||
Assert.notNull(boundClass, "boundClass may not be null");
|
||||
|
||||
this.elasticsearchConverter = elasticsearchConverter;
|
||||
requestFactory = new RequestFactory(elasticsearchConverter);
|
||||
|
||||
this.boundClass = boundClass;
|
||||
this.boundIndex = getIndexCoordinatesFor(boundClass);
|
||||
this.boundIndex = null;
|
||||
}
|
||||
|
||||
public AbstractDefaultIndexOperations(ElasticsearchConverter elasticsearchConverter, IndexCoordinates boundIndex) {
|
||||
|
||||
Assert.notNull(boundIndex, "boundIndex may not be null");
|
||||
|
||||
this.elasticsearchConverter = elasticsearchConverter;
|
||||
requestFactory = new RequestFactory(elasticsearchConverter);
|
||||
|
||||
this.boundClass = null;
|
||||
this.boundIndex = boundIndex;
|
||||
}
|
||||
@@ -85,48 +88,44 @@ abstract class AbstractDefaultIndexOperations implements IndexOperations {
|
||||
@Override
|
||||
public boolean create() {
|
||||
|
||||
Document settings = null;
|
||||
|
||||
if (boundClass != null) {
|
||||
Class<?> clazz = boundClass;
|
||||
String indexName = getIndexCoordinates().getIndexName();
|
||||
|
||||
if (clazz.isAnnotationPresent(Setting.class)) {
|
||||
String settingPath = clazz.getAnnotation(Setting.class).settingPath();
|
||||
|
||||
if (hasText(settingPath)) {
|
||||
String settings = ResourceUtil.readFileFromClasspath(settingPath);
|
||||
|
||||
if (hasText(settings)) {
|
||||
return doCreate(indexName, Document.parse(settings));
|
||||
}
|
||||
} else {
|
||||
LOGGER.info("settingPath in @Setting has to be defined. Using default instead.");
|
||||
}
|
||||
settings = loadSettings(settingPath);
|
||||
}
|
||||
|
||||
if (settings == null) {
|
||||
settings = getRequiredPersistentEntity(clazz).getDefaultSettings();
|
||||
}
|
||||
return doCreate(indexName, getDefaultSettings(getRequiredPersistentEntity(clazz)));
|
||||
}
|
||||
return doCreate(getIndexCoordinates().getIndexName(), null);
|
||||
|
||||
return doCreate(getIndexCoordinates(), settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean create(Document settings) {
|
||||
return doCreate(getIndexCoordinates().getIndexName(), settings);
|
||||
return doCreate(getIndexCoordinates(), settings);
|
||||
}
|
||||
|
||||
protected abstract boolean doCreate(String indexName, @Nullable Document settings);
|
||||
protected abstract boolean doCreate(IndexCoordinates index, @Nullable Document settings);
|
||||
|
||||
@Override
|
||||
public boolean delete() {
|
||||
return doDelete(getIndexCoordinates().getIndexName());
|
||||
return doDelete(getIndexCoordinates());
|
||||
}
|
||||
|
||||
protected abstract boolean doDelete(String indexName);
|
||||
protected abstract boolean doDelete(IndexCoordinates index);
|
||||
|
||||
@Override
|
||||
public boolean exists() {
|
||||
return doExists(getIndexCoordinates().getIndexName());
|
||||
return doExists(getIndexCoordinates());
|
||||
}
|
||||
|
||||
protected abstract boolean doExists(String indexName);
|
||||
protected abstract boolean doExists(IndexCoordinates index);
|
||||
|
||||
@Override
|
||||
public boolean putMapping(Document mapping) {
|
||||
@@ -149,10 +148,10 @@ abstract class AbstractDefaultIndexOperations implements IndexOperations {
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getSettings(boolean includeDefaults) {
|
||||
return doGetSettings(getIndexCoordinates().getIndexName(), includeDefaults);
|
||||
return doGetSettings(getIndexCoordinates(), includeDefaults);
|
||||
}
|
||||
|
||||
protected abstract Map<String, Object> doGetSettings(String indexName, boolean includeDefaults);
|
||||
protected abstract Map<String, Object> doGetSettings(IndexCoordinates index, boolean includeDefaults);
|
||||
|
||||
@Override
|
||||
public void refresh() {
|
||||
@@ -170,10 +169,10 @@ abstract class AbstractDefaultIndexOperations implements IndexOperations {
|
||||
|
||||
@Override
|
||||
public List<AliasMetaData> queryForAlias() {
|
||||
return doQueryForAlias(getIndexCoordinates().getIndexName());
|
||||
return doQueryForAlias(getIndexCoordinates());
|
||||
}
|
||||
|
||||
protected abstract List<AliasMetaData> doQueryForAlias(String indexName);
|
||||
protected abstract List<AliasMetaData> doQueryForAlias(IndexCoordinates index);
|
||||
|
||||
@Override
|
||||
public boolean removeAlias(AliasQuery query) {
|
||||
@@ -220,20 +219,6 @@ abstract class AbstractDefaultIndexOperations implements IndexOperations {
|
||||
// endregion
|
||||
|
||||
// region Helper functions
|
||||
private <T> Document getDefaultSettings(ElasticsearchPersistentEntity<T> persistentEntity) {
|
||||
|
||||
if (persistentEntity.isUseServerConfiguration()) {
|
||||
return Document.create();
|
||||
}
|
||||
|
||||
Map<String, String> map = new MapBuilder<String, String>()
|
||||
.put("index.number_of_shards", String.valueOf(persistentEntity.getShards()))
|
||||
.put("index.number_of_replicas", String.valueOf(persistentEntity.getReplicas()))
|
||||
.put("index.refresh_interval", persistentEntity.getRefreshInterval())
|
||||
.put("index.store.type", persistentEntity.getIndexStoreType()).map();
|
||||
return Document.from(map);
|
||||
}
|
||||
|
||||
ElasticsearchPersistentEntity<?> getRequiredPersistentEntity(Class<?> clazz) {
|
||||
return elasticsearchConverter.getMappingContext().getRequiredPersistentEntity(clazz);
|
||||
}
|
||||
@@ -252,9 +237,23 @@ abstract class AbstractDefaultIndexOperations implements IndexOperations {
|
||||
return getRequiredPersistentEntity(clazz).getIndexCoordinates();
|
||||
}
|
||||
|
||||
protected Map<String, Object> convertSettingsResponseToMap(GetSettingsResponse response, String indexName) {
|
||||
@Nullable
|
||||
private Document loadSettings(String settingPath) {
|
||||
if (hasText(settingPath)) {
|
||||
String settingsFile = ResourceUtil.readFileFromClasspath(settingPath);
|
||||
|
||||
Map<String, Object> settings = new HashMap<>();
|
||||
if (hasText(settingsFile)) {
|
||||
return Document.parse(settingsFile);
|
||||
}
|
||||
} else {
|
||||
LOGGER.info("settingPath in @Setting has to be defined. Using default instead.");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected Document convertSettingsResponseToMap(GetSettingsResponse response, String indexName) {
|
||||
|
||||
Document settings = Document.create();
|
||||
|
||||
if (!response.getIndexToDefaultSettings().isEmpty()) {
|
||||
Settings defaultSettings = response.getIndexToDefaultSettings().get(indexName);
|
||||
|
||||
+79
-3
@@ -32,6 +32,7 @@ import org.elasticsearch.action.search.MultiSearchResponse;
|
||||
import org.elasticsearch.action.search.SearchResponse;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.index.query.MoreLikeThisQueryBuilder;
|
||||
import org.elasticsearch.search.suggest.SuggestBuilder;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
@@ -48,6 +49,7 @@ import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersiste
|
||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
|
||||
import org.springframework.data.elasticsearch.core.query.BulkOptions;
|
||||
import org.springframework.data.elasticsearch.core.query.GetQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.IndexQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.IndexQueryBuilder;
|
||||
@@ -55,6 +57,7 @@ import org.springframework.data.elasticsearch.core.query.MoreLikeThisQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
|
||||
import org.springframework.data.elasticsearch.core.query.Query;
|
||||
import org.springframework.data.elasticsearch.core.query.SeqNoPrimaryTerm;
|
||||
import org.springframework.data.elasticsearch.core.query.UpdateQuery;
|
||||
import org.springframework.data.elasticsearch.support.VersionInfo;
|
||||
import org.springframework.data.mapping.callback.EntityCallbacks;
|
||||
import org.springframework.data.util.CloseableIterator;
|
||||
@@ -199,6 +202,11 @@ public abstract class AbstractElasticsearchTemplate implements ElasticsearchOper
|
||||
return get(query.getId(), clazz, index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<T> multiGet(Query query, Class<T> clazz) {
|
||||
return multiGet(query, clazz, getIndexCoordinatesFor(clazz));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public <T> T queryForObject(GetQuery query, Class<T> clazz) {
|
||||
@@ -226,6 +234,11 @@ public abstract class AbstractElasticsearchTemplate implements ElasticsearchOper
|
||||
return this.delete(id, getIndexCoordinatesFor(entityType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(Query query, Class<?> clazz) {
|
||||
delete(query, getIndexCoordinatesFor(clazz));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String delete(Object entity) {
|
||||
return delete(entity, getIndexCoordinatesFor(entity.getClass()));
|
||||
@@ -235,6 +248,22 @@ public abstract class AbstractElasticsearchTemplate implements ElasticsearchOper
|
||||
public String delete(Object entity, IndexCoordinates index) {
|
||||
return this.delete(getEntityId(entity), index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> bulkIndex(List<IndexQuery> queries, Class<?> clazz) {
|
||||
return bulkIndex(queries, getIndexCoordinatesFor(clazz));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> bulkIndex(List<IndexQuery> queries, BulkOptions bulkOptions, Class<?> clazz) {
|
||||
return bulkIndex(queries, bulkOptions, getIndexCoordinatesFor(clazz));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bulkUpdate(List<UpdateQuery> queries, Class<?> clazz) {
|
||||
bulkUpdate(queries, getIndexCoordinatesFor(clazz));
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region SearchOperations
|
||||
@@ -282,6 +311,11 @@ public abstract class AbstractElasticsearchTemplate implements ElasticsearchOper
|
||||
return search(new NativeSearchQueryBuilder().withQuery(moreLikeThisQueryBuilder).build(), clazz, index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<SearchHits<T>> multiSearch(List<? extends Query> queries, Class<T> clazz) {
|
||||
return multiSearch(queries, clazz, getIndexCoordinatesFor(clazz));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<SearchHits<T>> multiSearch(List<? extends Query> queries, Class<T> clazz, IndexCoordinates index) {
|
||||
MultiSearchRequest request = new MultiSearchRequest();
|
||||
@@ -300,9 +334,46 @@ public abstract class AbstractElasticsearchTemplate implements ElasticsearchOper
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SearchHits<?>> multiSearch(List<? extends Query> queries, List<Class<?>> classes) {
|
||||
|
||||
Assert.notNull(queries, "queries must not be null");
|
||||
Assert.notNull(classes, "classes must not be null");
|
||||
Assert.isTrue(queries.size() == classes.size(), "queries and classes must have the same size");
|
||||
|
||||
MultiSearchRequest request = new MultiSearchRequest();
|
||||
Iterator<Class<?>> it = classes.iterator();
|
||||
for (Query query : queries) {
|
||||
Class<?> clazz = it.next();
|
||||
request.add(requestFactory.searchRequest(query, clazz, getIndexCoordinatesFor(clazz)));
|
||||
}
|
||||
|
||||
MultiSearchResponse.Item[] items = getMultiSearchResult(request);
|
||||
|
||||
List<SearchHits<?>> res = new ArrayList<>(queries.size());
|
||||
int c = 0;
|
||||
Iterator<Class<?>> it1 = classes.iterator();
|
||||
for (Query query : queries) {
|
||||
Class entityClass = it1.next();
|
||||
|
||||
SearchDocumentResponseCallback<SearchHits<?>> callback = new ReadSearchDocumentResponseCallback<>(entityClass,
|
||||
getIndexCoordinatesFor(entityClass));
|
||||
|
||||
SearchResponse response = items[c++].getResponse();
|
||||
res.add(callback.doWith(SearchDocumentResponse.from(response)));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SearchHits<?>> multiSearch(List<? extends Query> queries, List<Class<?>> classes,
|
||||
IndexCoordinates index) {
|
||||
|
||||
Assert.notNull(queries, "queries must not be null");
|
||||
Assert.notNull(classes, "classes must not be null");
|
||||
Assert.notNull(index, "index must not be null");
|
||||
Assert.isTrue(queries.size() == classes.size(), "queries and classes must have the same size");
|
||||
|
||||
MultiSearchRequest request = new MultiSearchRequest();
|
||||
Iterator<Class<?>> it = classes.iterator();
|
||||
for (Query query : queries) {
|
||||
@@ -356,6 +427,12 @@ public abstract class AbstractElasticsearchTemplate implements ElasticsearchOper
|
||||
abstract protected void searchScrollClear(List<String> scrollIds);
|
||||
|
||||
abstract protected MultiSearchResponse.Item[] getMultiSearchResult(MultiSearchRequest request);
|
||||
|
||||
@Override
|
||||
public SearchResponse suggest(SuggestBuilder suggestion, Class<?> clazz) {
|
||||
return suggest(suggestion, getIndexCoordinatesFor(clazz));
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Helper methods
|
||||
@@ -624,7 +701,7 @@ public abstract class AbstractElasticsearchTemplate implements ElasticsearchOper
|
||||
@Override
|
||||
public SearchHits<T> doWith(SearchDocumentResponse response) {
|
||||
List<T> entities = response.getSearchDocuments().stream().map(delegate::doWith).collect(Collectors.toList());
|
||||
return SearchHitMapping.mappingFor(type, elasticsearchConverter.getMappingContext()).mapHits(response, entities);
|
||||
return SearchHitMapping.mappingFor(type, elasticsearchConverter).mapHits(response, entities);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -644,8 +721,7 @@ public abstract class AbstractElasticsearchTemplate implements ElasticsearchOper
|
||||
@Override
|
||||
public SearchScrollHits<T> doWith(SearchDocumentResponse response) {
|
||||
List<T> entities = response.getSearchDocuments().stream().map(delegate::doWith).collect(Collectors.toList());
|
||||
return SearchHitMapping.mappingFor(type, elasticsearchConverter.getMappingContext()).mapScrollHits(response,
|
||||
entities);
|
||||
return SearchHitMapping.mappingFor(type, elasticsearchConverter).mapScrollHits(response, entities);
|
||||
}
|
||||
}
|
||||
// endregion
|
||||
|
||||
+42
-103
@@ -15,40 +15,31 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.core;
|
||||
|
||||
import static org.elasticsearch.client.Requests.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
|
||||
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
|
||||
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
|
||||
import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
|
||||
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
|
||||
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse;
|
||||
import org.elasticsearch.client.Request;
|
||||
import org.elasticsearch.client.GetAliasesResponse;
|
||||
import org.elasticsearch.client.RequestOptions;
|
||||
import org.elasticsearch.client.Response;
|
||||
import org.elasticsearch.client.RestClient;
|
||||
import org.elasticsearch.client.indices.CreateIndexRequest;
|
||||
import org.elasticsearch.client.indices.GetIndexRequest;
|
||||
import org.elasticsearch.client.indices.GetMappingsRequest;
|
||||
import org.elasticsearch.client.indices.GetMappingsResponse;
|
||||
import org.elasticsearch.client.indices.PutMappingRequest;
|
||||
import org.elasticsearch.cluster.metadata.AliasMetaData;
|
||||
import org.springframework.data.elasticsearch.UncategorizedElasticsearchException;
|
||||
import org.springframework.data.elasticsearch.core.client.support.AliasData;
|
||||
import org.springframework.data.elasticsearch.core.document.Document;
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
import org.springframework.data.elasticsearch.core.query.AliasQuery;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
/**
|
||||
* {@link IndexOperations} implementation using the RestClient.
|
||||
*
|
||||
@@ -58,7 +49,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
*/
|
||||
class DefaultIndexOperations extends AbstractDefaultIndexOperations implements IndexOperations {
|
||||
|
||||
private ElasticsearchRestTemplate restTemplate;
|
||||
private final ElasticsearchRestTemplate restTemplate;
|
||||
|
||||
public DefaultIndexOperations(ElasticsearchRestTemplate restTemplate, Class<?> boundClass) {
|
||||
super(restTemplate.getElasticsearchConverter(), boundClass);
|
||||
@@ -71,27 +62,29 @@ class DefaultIndexOperations extends AbstractDefaultIndexOperations implements I
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean doCreate(String indexName, @Nullable Document settings) {
|
||||
CreateIndexRequest request = requestFactory.createIndexRequest(indexName, settings);
|
||||
protected boolean doCreate(IndexCoordinates index, @Nullable Document settings) {
|
||||
CreateIndexRequest request = requestFactory.createIndexRequest(index, settings);
|
||||
return restTemplate.execute(client -> client.indices().create(request, RequestOptions.DEFAULT).isAcknowledged());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean doDelete(String indexName) {
|
||||
protected boolean doDelete(IndexCoordinates index) {
|
||||
|
||||
Assert.notNull(indexName, "No index defined for delete operation");
|
||||
Assert.notNull(index, "index must not be null");
|
||||
|
||||
if (doExists(indexName)) {
|
||||
DeleteIndexRequest request = new DeleteIndexRequest(indexName);
|
||||
return restTemplate.execute(client -> client.indices().delete(request, RequestOptions.DEFAULT).isAcknowledged());
|
||||
if (doExists(index)) {
|
||||
DeleteIndexRequest deleteIndexRequest = requestFactory.deleteIndexRequest(index);
|
||||
return restTemplate
|
||||
.execute(client -> client.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT).isAcknowledged());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean doExists(String indexName) {
|
||||
GetIndexRequest request = new GetIndexRequest(indexName);
|
||||
return restTemplate.execute(client -> client.indices().exists(request, RequestOptions.DEFAULT));
|
||||
protected boolean doExists(IndexCoordinates index) {
|
||||
|
||||
GetIndexRequest getIndexRequest = requestFactory.getIndexRequest(index);
|
||||
return restTemplate.execute(client -> client.indices().exists(getIndexRequest, RequestOptions.DEFAULT));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -109,16 +102,20 @@ class DefaultIndexOperations extends AbstractDefaultIndexOperations implements I
|
||||
|
||||
Assert.notNull(index, "No index defined for getMapping()");
|
||||
|
||||
GetMappingsRequest mappingsRequest = requestFactory.getMappingsRequest(index);
|
||||
|
||||
return restTemplate.execute(client -> {
|
||||
RestClient restClient = client.getLowLevelClient();
|
||||
Request request = new Request("GET", '/' + index.getIndexName() + "/_mapping");
|
||||
Response response = restClient.performRequest(request);
|
||||
return convertMappingResponse(EntityUtils.toString(response.getEntity()));
|
||||
GetMappingsResponse mapping = client.indices().getMapping(mappingsRequest, RequestOptions.DEFAULT);
|
||||
// we only return data for the first index name that was requested (always have done so)
|
||||
String index1 = mappingsRequest.indices()[0];
|
||||
Map<String, Object> result = new LinkedHashMap<>();
|
||||
return mapping.mappings().get(index1).getSourceAsMap();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean doAddAlias(AliasQuery query, IndexCoordinates index) {
|
||||
|
||||
IndicesAliasesRequest request = requestFactory.indicesAddAliasesRequest(query, index);
|
||||
return restTemplate
|
||||
.execute(client -> client.indices().updateAliases(request, RequestOptions.DEFAULT).isAcknowledged());
|
||||
@@ -136,34 +133,28 @@ class DefaultIndexOperations extends AbstractDefaultIndexOperations implements I
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<AliasMetaData> doQueryForAlias(String indexName) {
|
||||
List<AliasMetaData> aliases = null;
|
||||
protected List<AliasMetaData> doQueryForAlias(IndexCoordinates index) {
|
||||
|
||||
GetAliasesRequest getAliasesRequest = requestFactory.getAliasesRequest(index);
|
||||
|
||||
return restTemplate.execute(client -> {
|
||||
RestClient restClient = client.getLowLevelClient();
|
||||
Response response;
|
||||
String aliasResponse;
|
||||
|
||||
response = restClient.performRequest(new Request("GET", '/' + indexName + "/_alias/*"));
|
||||
aliasResponse = EntityUtils.toString(response.getEntity());
|
||||
|
||||
return convertAliasResponse(aliasResponse);
|
||||
GetAliasesResponse alias = client.indices().getAlias(getAliasesRequest, RequestOptions.DEFAULT);
|
||||
// we only return data for the first index name that was requested (always have done so)
|
||||
String index1 = getAliasesRequest.indices()[0];
|
||||
return new ArrayList<>(alias.getAliases().get(index1));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, Object> doGetSettings(String indexName, boolean includeDefaults) {
|
||||
protected Map<String, Object> doGetSettings(IndexCoordinates index, boolean includeDefaults) {
|
||||
|
||||
Assert.notNull(indexName, "No index defined for getSettings");
|
||||
Assert.notNull(index, "index must not be null");
|
||||
|
||||
GetSettingsRequest request = new GetSettingsRequest() //
|
||||
.indices(indexName) //
|
||||
.includeDefaults(includeDefaults);
|
||||
|
||||
//
|
||||
GetSettingsRequest getSettingsRequest = requestFactory.getSettingsRequest(index, includeDefaults);
|
||||
GetSettingsResponse response = restTemplate.execute(client -> client.indices() //
|
||||
.getSettings(request, RequestOptions.DEFAULT));
|
||||
.getSettings(getSettingsRequest, RequestOptions.DEFAULT));
|
||||
|
||||
return convertSettingsResponseToMap(response, indexName);
|
||||
return convertSettingsResponseToMap(response, getSettingsRequest.indices()[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -171,61 +162,9 @@ class DefaultIndexOperations extends AbstractDefaultIndexOperations implements I
|
||||
|
||||
Assert.notNull(index, "No index defined for refresh()");
|
||||
|
||||
restTemplate
|
||||
.execute(client -> client.indices().refresh(refreshRequest(index.getIndexNames()), RequestOptions.DEFAULT));
|
||||
RefreshRequest refreshRequest = requestFactory.refreshRequest(index);
|
||||
restTemplate.execute(client -> client.indices().refresh(refreshRequest, RequestOptions.DEFAULT));
|
||||
}
|
||||
|
||||
// region Helper methods
|
||||
private Map<String, Object> convertMappingResponse(String mappingResponse) {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
try {
|
||||
Map<String, Object> result = null;
|
||||
JsonNode node = mapper.readTree(mappingResponse);
|
||||
|
||||
node = node.findValue("mappings");
|
||||
result = mapper.readValue(mapper.writeValueAsString(node), HashMap.class);
|
||||
|
||||
return result;
|
||||
} catch (IOException e) {
|
||||
throw new UncategorizedElasticsearchException("Could not map alias response : " + mappingResponse, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* It takes two steps to create a List<AliasMetadata> from the elasticsearch http response because the aliases field
|
||||
* is actually a Map by alias name, but the alias name is on the AliasMetadata.
|
||||
*
|
||||
* @param aliasResponse
|
||||
* @return
|
||||
*/
|
||||
private List<AliasMetaData> convertAliasResponse(String aliasResponse) {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
try {
|
||||
JsonNode node = mapper.readTree(aliasResponse);
|
||||
node = node.findValue("aliases");
|
||||
|
||||
if (node == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
Map<String, AliasData> aliasData = mapper.readValue(mapper.writeValueAsString(node),
|
||||
new TypeReference<Map<String, AliasData>>() {});
|
||||
|
||||
Iterable<Map.Entry<String, AliasData>> aliasIter = aliasData.entrySet();
|
||||
List<AliasMetaData> aliasMetaDataList = new ArrayList<>();
|
||||
|
||||
for (Map.Entry<String, AliasData> aliasentry : aliasIter) {
|
||||
AliasData data = aliasentry.getValue();
|
||||
aliasMetaDataList.add(AliasMetaData.newAliasMetaDataBuilder(aliasentry.getKey()).filter(data.getFilter())
|
||||
.routing(data.getRouting()).searchRouting(data.getSearch_routing()).indexRouting(data.getIndex_routing())
|
||||
.build());
|
||||
}
|
||||
return aliasMetaDataList;
|
||||
} catch (IOException e) {
|
||||
throw new UncategorizedElasticsearchException("Could not map alias response : " + aliasResponse, e);
|
||||
}
|
||||
}
|
||||
// endregion
|
||||
}
|
||||
|
||||
+238
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
* Copyright 2020 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;
|
||||
|
||||
import static org.elasticsearch.client.Requests.*;
|
||||
import static org.springframework.util.StringUtils.*;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
|
||||
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
|
||||
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
|
||||
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest;
|
||||
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.elasticsearch.NoSuchIndexException;
|
||||
import org.springframework.data.elasticsearch.annotations.Mapping;
|
||||
import org.springframework.data.elasticsearch.annotations.Setting;
|
||||
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
||||
import org.springframework.data.elasticsearch.core.document.Document;
|
||||
import org.springframework.data.elasticsearch.core.index.MappingBuilder;
|
||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Peter-Josef Meisch
|
||||
* @since 4.1
|
||||
*/
|
||||
class DefaultReactiveIndexOperations implements ReactiveIndexOperations {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultReactiveIndexOperations.class);
|
||||
|
||||
@Nullable private final Class<?> boundClass;
|
||||
private final IndexCoordinates boundIndex;
|
||||
private final RequestFactory requestFactory;
|
||||
private final ReactiveElasticsearchOperations operations;
|
||||
private final ElasticsearchConverter converter;
|
||||
|
||||
public DefaultReactiveIndexOperations(ReactiveElasticsearchOperations operations, IndexCoordinates index) {
|
||||
|
||||
Assert.notNull(operations, "operations must not be null");
|
||||
Assert.notNull(index, "index must not be null");
|
||||
|
||||
this.operations = operations;
|
||||
this.converter = operations.getElasticsearchConverter();
|
||||
this.requestFactory = new RequestFactory(operations.getElasticsearchConverter());
|
||||
this.boundClass = null;
|
||||
this.boundIndex = index;
|
||||
}
|
||||
|
||||
public DefaultReactiveIndexOperations(ReactiveElasticsearchOperations operations, Class<?> clazz) {
|
||||
|
||||
Assert.notNull(operations, "operations must not be null");
|
||||
Assert.notNull(clazz, "clazz must not be null");
|
||||
|
||||
this.operations = operations;
|
||||
this.converter = operations.getElasticsearchConverter();
|
||||
this.requestFactory = new RequestFactory(operations.getElasticsearchConverter());
|
||||
this.boundClass = clazz;
|
||||
this.boundIndex = getIndexCoordinatesFor(clazz);
|
||||
}
|
||||
|
||||
// region index management
|
||||
@Override
|
||||
public Mono<Boolean> create() {
|
||||
|
||||
String indexName = getIndexCoordinates().getIndexName();
|
||||
Document settings = null;
|
||||
|
||||
if (boundClass != null) {
|
||||
Class<?> clazz = boundClass;
|
||||
|
||||
if (clazz.isAnnotationPresent(Setting.class)) {
|
||||
String settingPath = clazz.getAnnotation(Setting.class).settingPath();
|
||||
|
||||
return loadDocument(settingPath, "@Setting").flatMap(document -> doCreate(indexName, document));
|
||||
}
|
||||
|
||||
settings = getRequiredPersistentEntity(clazz).getDefaultSettings();
|
||||
}
|
||||
|
||||
return doCreate(indexName, settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Boolean> create(Document settings) {
|
||||
return doCreate(getIndexCoordinates().getIndexName(), settings);
|
||||
}
|
||||
|
||||
private Mono<Boolean> doCreate(String indexName, @Nullable Document settings) {
|
||||
CreateIndexRequest request = requestFactory.createIndexRequestReactive(getIndexCoordinates().getIndexName(),
|
||||
settings);
|
||||
return Mono.from(operations.executeWithIndicesClient(client -> client.createIndex(request)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Boolean> delete() {
|
||||
|
||||
return exists() //
|
||||
.flatMap(exists -> {
|
||||
|
||||
if (exists) {
|
||||
DeleteIndexRequest request = requestFactory.deleteIndexRequest(getIndexCoordinates());
|
||||
return Mono.from(operations.executeWithIndicesClient(client -> client.deleteIndex(request)))
|
||||
.onErrorResume(NoSuchIndexException.class, e -> Mono.just(false));
|
||||
} else {
|
||||
return Mono.just(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Boolean> exists() {
|
||||
|
||||
GetIndexRequest request = requestFactory.getIndexRequestReactive(getIndexCoordinates().getIndexName());
|
||||
return Mono.from(operations.executeWithIndicesClient(client -> client.existsIndex(request)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> refresh() {
|
||||
return Mono.from(operations.executeWithIndicesClient(
|
||||
client -> client.refreshIndex(refreshRequest(getIndexCoordinates().getIndexNames()))));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Document> createMapping() {
|
||||
return createMapping(checkForBoundClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Document> createMapping(Class<?> clazz) {
|
||||
|
||||
if (clazz.isAnnotationPresent(Mapping.class)) {
|
||||
String mappingPath = clazz.getAnnotation(Mapping.class).mappingPath();
|
||||
return loadDocument(mappingPath, "@Mapping");
|
||||
}
|
||||
|
||||
String mapping = new MappingBuilder(converter).buildPropertyMapping(clazz);
|
||||
return Mono.just(Document.parse(mapping));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Boolean> putMapping(Mono<Document> mapping) {
|
||||
return mapping.map(document -> requestFactory.putMappingRequestReactive(getIndexCoordinates(), document)) //
|
||||
.flatMap(request -> Mono.from(operations.executeWithIndicesClient(client -> client.putMapping(request))));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Document> getMapping() {
|
||||
|
||||
IndexCoordinates indexCoordinates = getIndexCoordinates();
|
||||
GetMappingsRequest request = requestFactory.getMappingRequestReactive(indexCoordinates);
|
||||
|
||||
return Mono.from(operations.executeWithIndicesClient(client -> client.getMapping(request)))
|
||||
.flatMap(getMappingsResponse -> {
|
||||
Document document = Document.create();
|
||||
document.put("properties",
|
||||
getMappingsResponse.mappings().get(indexCoordinates.getIndexName()).get("properties").getSourceAsMap());
|
||||
return Mono.just(document);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Document> getSettings(boolean includeDefaults) {
|
||||
|
||||
String indexName = getIndexCoordinates().getIndexName();
|
||||
GetSettingsRequest request = requestFactory.getSettingsRequest(indexName, includeDefaults);
|
||||
|
||||
return Mono.from(operations.executeWithIndicesClient(client -> client.getSettings(request)))
|
||||
.map(getSettingsResponse -> requestFactory.fromSettingsResponse(getSettingsResponse, indexName));
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region helper functions
|
||||
/**
|
||||
* get the current {@link IndexCoordinates}. These may change over time when the entity class has a SpEL constructed
|
||||
* index name. When this IndexOperations is not bound to a class, the bound IndexCoordinates are returned.
|
||||
*
|
||||
* @return IndexCoordinates
|
||||
*/
|
||||
private IndexCoordinates getIndexCoordinates() {
|
||||
return (boundClass != null) ? getIndexCoordinatesFor(boundClass) : boundIndex;
|
||||
}
|
||||
|
||||
private IndexCoordinates getIndexCoordinatesFor(Class<?> clazz) {
|
||||
return operations.getElasticsearchConverter().getMappingContext().getRequiredPersistentEntity(clazz)
|
||||
.getIndexCoordinates();
|
||||
}
|
||||
|
||||
private ElasticsearchPersistentEntity<?> getRequiredPersistentEntity(Class<?> clazz) {
|
||||
return converter.getMappingContext().getRequiredPersistentEntity(clazz);
|
||||
}
|
||||
|
||||
private Mono<Document> loadDocument(String path, String annotation) {
|
||||
|
||||
if (hasText(path)) {
|
||||
return ReactiveResourceUtil.readFileFromClasspath(path).flatMap(s -> {
|
||||
if (hasText(s)) {
|
||||
return Mono.just(Document.parse(s));
|
||||
} else {
|
||||
return Mono.just(Document.create());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
LOGGER.info("path in {} has to be defined. Using default instead.", annotation);
|
||||
}
|
||||
|
||||
return Mono.just(Document.create());
|
||||
}
|
||||
|
||||
private Class<?> checkForBoundClass() {
|
||||
if (boundClass == null) {
|
||||
throw new InvalidDataAccessApiUsageException("IndexOperations are not bound");
|
||||
}
|
||||
return boundClass;
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
}
|
||||
+35
-32
@@ -21,16 +21,18 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
|
||||
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequestBuilder;
|
||||
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
|
||||
import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
|
||||
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
|
||||
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequest;
|
||||
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest;
|
||||
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequestBuilder;
|
||||
import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
|
||||
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
|
||||
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.cluster.metadata.AliasMetaData;
|
||||
import org.springframework.data.elasticsearch.ElasticsearchException;
|
||||
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
||||
import org.springframework.data.elasticsearch.core.document.Document;
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
@@ -62,26 +64,29 @@ class DefaultTransportIndexOperations extends AbstractDefaultIndexOperations imp
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean doCreate(String indexName, @Nullable Document settings) {
|
||||
CreateIndexRequestBuilder createIndexRequestBuilder = requestFactory.createIndexRequestBuilder(client, indexName,
|
||||
protected boolean doCreate(IndexCoordinates index, @Nullable Document settings) {
|
||||
CreateIndexRequestBuilder createIndexRequestBuilder = requestFactory.createIndexRequestBuilder(client, index,
|
||||
settings);
|
||||
return createIndexRequestBuilder.execute().actionGet().isAcknowledged();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean doDelete(String indexName) {
|
||||
protected boolean doDelete(IndexCoordinates index) {
|
||||
|
||||
Assert.notNull(indexName, "No index defined for delete operation");
|
||||
Assert.notNull(index, "No index defined for delete operation");
|
||||
|
||||
if (doExists(indexName)) {
|
||||
return client.admin().indices().delete(new DeleteIndexRequest(indexName)).actionGet().isAcknowledged();
|
||||
if (doExists(index)) {
|
||||
DeleteIndexRequest deleteIndexRequest = requestFactory.deleteIndexRequest(index);
|
||||
return client.admin().indices().delete(deleteIndexRequest).actionGet().isAcknowledged();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean doExists(String indexName) {
|
||||
return client.admin().indices().exists(indicesExistsRequest(indexName)).actionGet().isExists();
|
||||
protected boolean doExists(IndexCoordinates index) {
|
||||
|
||||
IndicesExistsRequest indicesExistsRequest = requestFactory.indicesExistsRequest(index);
|
||||
return client.admin().indices().exists(indicesExistsRequest).actionGet().isExists();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -98,14 +103,12 @@ class DefaultTransportIndexOperations extends AbstractDefaultIndexOperations imp
|
||||
|
||||
Assert.notNull(index, "No index defined for getMapping()");
|
||||
|
||||
try {
|
||||
return client.admin().indices().getMappings( //
|
||||
new GetMappingsRequest().indices(index.getIndexNames())).actionGet() //
|
||||
.getMappings().get(index.getIndexName()).get(IndexCoordinates.TYPE) //
|
||||
.getSourceAsMap();
|
||||
} catch (Exception e) {
|
||||
throw new ElasticsearchException("Error while getting mapping for indexName : " + index.getIndexName(), e);
|
||||
}
|
||||
GetMappingsRequest mappingsRequest = requestFactory.getMappingsRequest(client, index);
|
||||
|
||||
return client.admin().indices().getMappings( //
|
||||
mappingsRequest).actionGet() //
|
||||
.getMappings().get(mappingsRequest.indices()[0]).get(IndexCoordinates.TYPE) //
|
||||
.getSourceAsMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -120,39 +123,39 @@ class DefaultTransportIndexOperations extends AbstractDefaultIndexOperations imp
|
||||
Assert.notNull(index, "No index defined for Alias");
|
||||
Assert.notNull(query.getAliasName(), "No alias defined");
|
||||
|
||||
return client.admin().indices().prepareAliases().removeAlias(index.getIndexName(), query.getAliasName()).execute()
|
||||
.actionGet().isAcknowledged();
|
||||
IndicesAliasesRequestBuilder indicesAliasesRequestBuilder = requestFactory
|
||||
.indicesRemoveAliasesRequestBuilder(client, query, index);
|
||||
return indicesAliasesRequestBuilder.execute().actionGet().isAcknowledged();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<AliasMetaData> doQueryForAlias(String indexName) {
|
||||
return client.admin().indices().getAliases(new GetAliasesRequest().indices(indexName)).actionGet().getAliases()
|
||||
.get(indexName);
|
||||
protected List<AliasMetaData> doQueryForAlias(IndexCoordinates index) {
|
||||
|
||||
GetAliasesRequest getAliasesRequest = requestFactory.getAliasesRequest(index);
|
||||
return client.admin().indices().getAliases(getAliasesRequest).actionGet().getAliases().get(index.getIndexName());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, Object> doGetSettings(String indexName, boolean includeDefaults) {
|
||||
protected Map<String, Object> doGetSettings(IndexCoordinates index, boolean includeDefaults) {
|
||||
|
||||
Assert.notNull(indexName, "No index defined for getSettings");
|
||||
|
||||
GetSettingsRequest request = new GetSettingsRequest() //
|
||||
.indices(indexName) //
|
||||
.includeDefaults(includeDefaults);
|
||||
Assert.notNull(index, "index must not be null");
|
||||
|
||||
GetSettingsRequest getSettingsRequest = requestFactory.getSettingsRequest(index, includeDefaults);
|
||||
GetSettingsResponse response = client.admin() //
|
||||
.indices() //
|
||||
.getSettings(request) //
|
||||
.getSettings(getSettingsRequest) //
|
||||
.actionGet();
|
||||
|
||||
return convertSettingsResponseToMap(response, indexName);
|
||||
return requestFactory.fromSettingsResponse(response, index.getIndexName());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doRefresh(IndexCoordinates index) {
|
||||
|
||||
Assert.notNull(index, "No index defined for refresh()");
|
||||
Assert.notNull(index, "index must not be null");
|
||||
|
||||
client.admin().indices().refresh(refreshRequest(index.getIndexNames())).actionGet();
|
||||
RefreshRequest request = requestFactory.refreshRequest(index);
|
||||
client.admin().indices().refresh(request).actionGet();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -114,6 +114,16 @@ public interface DocumentOperations {
|
||||
@Nullable
|
||||
<T> T get(String id, Class<T> clazz, IndexCoordinates index);
|
||||
|
||||
/**
|
||||
* Execute a multiGet against elasticsearch for the given ids.
|
||||
*
|
||||
* @param query the query defining the ids of the objects to get
|
||||
* @param clazz the type of the object to be returned
|
||||
* @return list of objects, contains null values for ids that are not found
|
||||
* @since 4.1
|
||||
*/
|
||||
<T> List<T> multiGet(Query query, Class<T> clazz);
|
||||
|
||||
/**
|
||||
* Execute a multiGet against elasticsearch for the given ids.
|
||||
*
|
||||
@@ -142,6 +152,18 @@ public interface DocumentOperations {
|
||||
*/
|
||||
boolean exists(String id, IndexCoordinates index);
|
||||
|
||||
/**
|
||||
* Bulk index all objects. Will do save or update.
|
||||
*
|
||||
* @param queries the queries to execute in bulk
|
||||
* @param clazz the entity class
|
||||
* @return the ids of the indexed objects
|
||||
* @since 4.1
|
||||
*/
|
||||
default List<String> bulkIndex(List<IndexQuery> queries, Class<?> clazz) {
|
||||
return bulkIndex(queries, BulkOptions.defaultOptions(), clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bulk index all objects. Will do save or update.
|
||||
*
|
||||
@@ -152,6 +174,17 @@ public interface DocumentOperations {
|
||||
return bulkIndex(queries, BulkOptions.defaultOptions(), index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bulk index all objects. Will do save or update.
|
||||
*
|
||||
* @param queries the queries to execute in bulk
|
||||
* @param bulkOptions options to be added to the bulk request
|
||||
* @param clazz the entity class
|
||||
* @return the ids of the indexed objects
|
||||
* @since 4.1
|
||||
*/
|
||||
List<String> bulkIndex(List<IndexQuery> queries, BulkOptions bulkOptions, Class<?> clazz);
|
||||
|
||||
/**
|
||||
* Bulk index all objects. Will do save or update.
|
||||
*
|
||||
@@ -170,6 +203,14 @@ public interface DocumentOperations {
|
||||
bulkUpdate(queries, BulkOptions.defaultOptions(), index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bulk update all objects. Will do update.
|
||||
* @param clazz the entity class
|
||||
* @param queries the queries to execute in bulk
|
||||
* @since 4.1
|
||||
*/
|
||||
void bulkUpdate(List<UpdateQuery> queries, Class<?> clazz);
|
||||
|
||||
/**
|
||||
* Bulk update all objects. Will do update.
|
||||
*
|
||||
@@ -213,6 +254,16 @@ public interface DocumentOperations {
|
||||
*/
|
||||
String delete(Object entity, IndexCoordinates index);
|
||||
|
||||
/**
|
||||
* Delete all records matching the query.
|
||||
*
|
||||
* @param query query defining the objects
|
||||
* @param clazz The entity class, must be annotated with
|
||||
* {@link org.springframework.data.elasticsearch.annotations.Document}
|
||||
* @since 4.1
|
||||
*/
|
||||
void delete(Query query, Class<?> clazz);
|
||||
|
||||
/**
|
||||
* Delete all records matching the query.
|
||||
*
|
||||
|
||||
+6
-2
@@ -23,7 +23,6 @@ import org.elasticsearch.ElasticsearchStatusException;
|
||||
import org.elasticsearch.common.ValidationException;
|
||||
import org.elasticsearch.index.engine.VersionConflictEngineException;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
@@ -105,10 +104,15 @@ public class ElasticsearchExceptionTranslator implements PersistenceExceptionTra
|
||||
|
||||
List<String> metadata = ex.getMetadata("es.index_uuid");
|
||||
if (metadata == null) {
|
||||
|
||||
if (ex.getCause() instanceof ElasticsearchException) {
|
||||
return indexAvailable((ElasticsearchException) ex.getCause());
|
||||
}
|
||||
|
||||
if (ex instanceof ElasticsearchStatusException) {
|
||||
return StringUtils.hasText(ObjectUtils.nullSafeToString(ex.getIndex()));
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
return !CollectionUtils.contains(metadata.iterator(), "_na_");
|
||||
}
|
||||
|
||||
+14
-14
@@ -49,7 +49,7 @@ public interface ElasticsearchOperations extends DocumentOperations, SearchOpera
|
||||
IndexOperations indexOps(Class<?> clazz);
|
||||
|
||||
/**
|
||||
* get an {@link IndexOperations} that is bound to the given class
|
||||
* get an {@link IndexOperations} that is bound to the given index
|
||||
*
|
||||
* @return IndexOperations
|
||||
*/
|
||||
@@ -60,17 +60,17 @@ public interface ElasticsearchOperations extends DocumentOperations, SearchOpera
|
||||
IndexCoordinates getIndexCoordinatesFor(Class<?> clazz);
|
||||
|
||||
// region IndexOperations
|
||||
/**
|
||||
* Create an index for given indexName .
|
||||
*
|
||||
* @param indexName the name of the index
|
||||
* @return {@literal true} if the index was created
|
||||
* @deprecated since 4.0, use {@link IndexOperations#create()}
|
||||
*/
|
||||
@Deprecated
|
||||
default boolean createIndex(String indexName) {
|
||||
return indexOps(IndexCoordinates.of(indexName)).create();
|
||||
}
|
||||
/**
|
||||
* Create an index for given indexName .
|
||||
*
|
||||
* @param indexName the name of the index
|
||||
* @return {@literal true} if the index was created
|
||||
* @deprecated since 4.0, use {@link IndexOperations#create()}
|
||||
*/
|
||||
@Deprecated
|
||||
default boolean createIndex(String indexName) {
|
||||
return indexOps(IndexCoordinates.of(indexName)).create();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an index for given indexName and Settings.
|
||||
@@ -186,7 +186,7 @@ default boolean createIndex(String indexName) {
|
||||
@Deprecated
|
||||
default boolean putMapping(Class<?> clazz) {
|
||||
IndexOperations indexOps = indexOps(clazz);
|
||||
return indexOps.putMapping(indexOps.createMapping(clazz));
|
||||
return indexOps.putMapping(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -202,7 +202,7 @@ default boolean createIndex(String indexName) {
|
||||
@Deprecated
|
||||
default boolean putMapping(IndexCoordinates index, Class<?> clazz) {
|
||||
IndexOperations indexOps = indexOps(index);
|
||||
return indexOps.putMapping(indexOps.createMapping(clazz));
|
||||
return indexOps.putMapping(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-5
@@ -37,7 +37,6 @@ import org.elasticsearch.client.RequestOptions;
|
||||
import org.elasticsearch.client.RestHighLevelClient;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.index.reindex.DeleteByQueryRequest;
|
||||
import org.elasticsearch.search.builder.SearchSourceBuilder;
|
||||
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
|
||||
import org.elasticsearch.search.suggest.SuggestBuilder;
|
||||
import org.slf4j.Logger;
|
||||
@@ -315,10 +314,7 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate {
|
||||
|
||||
@Override
|
||||
public SearchResponse suggest(SuggestBuilder suggestion, IndexCoordinates index) {
|
||||
SearchRequest searchRequest = new SearchRequest(index.getIndexNames());
|
||||
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
|
||||
sourceBuilder.suggest(suggestion);
|
||||
searchRequest.source(sourceBuilder);
|
||||
SearchRequest searchRequest = requestFactory.searchRequest(suggestion, index);
|
||||
return execute(client -> client.search(searchRequest, RequestOptions.DEFAULT));
|
||||
}
|
||||
|
||||
|
||||
+7
-5
@@ -23,6 +23,7 @@ import org.elasticsearch.action.admin.cluster.node.info.NodesInfoAction;
|
||||
import org.elasticsearch.action.admin.cluster.node.info.NodesInfoRequestBuilder;
|
||||
import org.elasticsearch.action.admin.cluster.node.info.NodesInfoResponse;
|
||||
import org.elasticsearch.action.bulk.BulkRequestBuilder;
|
||||
import org.elasticsearch.action.delete.DeleteRequestBuilder;
|
||||
import org.elasticsearch.action.get.GetRequestBuilder;
|
||||
import org.elasticsearch.action.get.GetResponse;
|
||||
import org.elasticsearch.action.get.MultiGetRequestBuilder;
|
||||
@@ -227,8 +228,9 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate {
|
||||
Assert.notNull(id, "id must not be null");
|
||||
Assert.notNull(index, "index must not be null");
|
||||
|
||||
return client.prepareDelete(index.getIndexName(), IndexCoordinates.TYPE, elasticsearchConverter.convertId(id))
|
||||
.execute().actionGet().getId();
|
||||
DeleteRequestBuilder deleteRequestBuilder = requestFactory.deleteRequestBuilder(client,
|
||||
elasticsearchConverter.convertId(id), index);
|
||||
return deleteRequestBuilder.execute().actionGet().getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -293,8 +295,7 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate {
|
||||
|
||||
Assert.notNull(query.getPageable(), "pageable of query must not be null.");
|
||||
|
||||
ActionFuture<SearchResponse> action = requestFactory //
|
||||
.searchRequestBuilder(client, query, clazz, index) //
|
||||
ActionFuture<SearchResponse> action = requestFactory.searchRequestBuilder(client, query, clazz, index) //
|
||||
.setScroll(TimeValue.timeValueMillis(scrollTimeInMillis)) //
|
||||
.execute();
|
||||
|
||||
@@ -332,7 +333,8 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate {
|
||||
|
||||
@Override
|
||||
public SearchResponse suggest(SuggestBuilder suggestion, IndexCoordinates index) {
|
||||
return client.prepareSearch(index.getIndexNames()).suggest(suggestion).get();
|
||||
SearchRequestBuilder searchRequestBuilder = requestFactory.searchRequestBuilder(client, suggestion, index);
|
||||
return searchRequestBuilder.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -28,7 +28,6 @@ import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Common operations performed on an entity in the context of it's mapping metadata.
|
||||
@@ -43,6 +42,8 @@ class EntityOperations {
|
||||
|
||||
private static final String ID_FIELD = "id";
|
||||
|
||||
private final MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> context;
|
||||
|
||||
public EntityOperations(
|
||||
MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> context) {
|
||||
|
||||
@@ -51,8 +52,6 @@ class EntityOperations {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
private final MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> context;
|
||||
|
||||
/**
|
||||
* Creates a new {@link Entity} for the given bean.
|
||||
*
|
||||
@@ -100,11 +99,26 @@ class EntityOperations {
|
||||
* @param index index name override can be {@literal null}.
|
||||
* @param type index type override can be {@literal null}.
|
||||
* @return the {@link IndexCoordinates} containing index name and index type.
|
||||
* @deprecated since 4.1, use {@link EntityOperations#determineIndex(Entity, String)}
|
||||
*/
|
||||
@Deprecated
|
||||
IndexCoordinates determineIndex(Entity<?> entity, @Nullable String index, @Nullable String type) {
|
||||
return determineIndex(entity.getPersistentEntity(), index, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine index name and type name from {@link Entity} with {@code index} and {@code type} overrides. Allows using
|
||||
* preferred values for index and type if provided, otherwise fall back to index and type defined on entity level.
|
||||
*
|
||||
* @param entity the entity to determine the index name. Can be {@literal null} if {@code index} and {@literal type}
|
||||
* are provided.
|
||||
* @param index index name override can be {@literal null}.
|
||||
* @return the {@link IndexCoordinates} containing index name and index type.
|
||||
*/
|
||||
IndexCoordinates determineIndex(Entity<?> entity, @Nullable String index) {
|
||||
return determineIndex(entity.getPersistentEntity(), index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine index name and type name from {@link ElasticsearchPersistentEntity} with {@code index} and {@code type}
|
||||
* overrides. Allows using preferred values for index and type if provided, otherwise fall back to index and type
|
||||
@@ -115,20 +129,27 @@ class EntityOperations {
|
||||
* @param index index name override can be {@literal null}.
|
||||
* @param type index type override can be {@literal null}.
|
||||
* @return the {@link IndexCoordinates} containing index name and index type.
|
||||
* @deprecated since 4.1, use {@link EntityOperations#determineIndex(ElasticsearchPersistentEntity, String)}
|
||||
*/
|
||||
@Deprecated
|
||||
IndexCoordinates determineIndex(ElasticsearchPersistentEntity<?> persistentEntity, @Nullable String index,
|
||||
@Nullable String type) {
|
||||
return persistentEntity.getIndexCoordinates();
|
||||
return determineIndex(persistentEntity, index);
|
||||
}
|
||||
|
||||
private static String indexName(@Nullable ElasticsearchPersistentEntity<?> entity, @Nullable String index) {
|
||||
|
||||
if (StringUtils.isEmpty(index)) {
|
||||
Assert.notNull(entity, "Cannot determine index name");
|
||||
return entity.getIndexCoordinates().getIndexName();
|
||||
}
|
||||
|
||||
return index;
|
||||
/**
|
||||
* Determine index name and type name from {@link ElasticsearchPersistentEntity} with {@code index} and {@code type}
|
||||
* overrides. Allows using preferred values for index and type if provided, otherwise fall back to index and type
|
||||
* defined on entity level.
|
||||
*
|
||||
* @param persistentEntity the entity to determine the index name. Can be {@literal null} if {@code index} and
|
||||
* {@literal type} are provided.
|
||||
* @param index index name override can be {@literal null}.
|
||||
* @return the {@link IndexCoordinates} containing index name and index type.
|
||||
* @since 4.1
|
||||
*/
|
||||
IndexCoordinates determineIndex(ElasticsearchPersistentEntity<?> persistentEntity, @Nullable String index) {
|
||||
return index != null ? IndexCoordinates.of(index) : persistentEntity.getIndexCoordinates();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -85,6 +85,14 @@ public interface IndexOperations {
|
||||
*/
|
||||
Document createMapping(Class<?> clazz);
|
||||
|
||||
/**
|
||||
* Writes the mapping to the index for the class this IndexOperations is bound to.
|
||||
* @return {@literal true} if the mapping could be stored
|
||||
* @since 4.1
|
||||
*/
|
||||
default boolean putMapping() {
|
||||
return putMapping(createMapping());}
|
||||
|
||||
/**
|
||||
* writes a mapping to the index
|
||||
*
|
||||
@@ -93,6 +101,16 @@ public interface IndexOperations {
|
||||
*/
|
||||
boolean putMapping(Document mapping);
|
||||
|
||||
/**
|
||||
* Creates the index mapping for the given class and writes it to the index.
|
||||
* @param clazz the clazz to create a mapping for
|
||||
* @return {@literal true} if the mapping could be stored
|
||||
* @since 4.1
|
||||
*/
|
||||
default boolean putMapping(Class<?> clazz) {
|
||||
return putMapping(createMapping(clazz));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get mapping for an index defined by a class.
|
||||
*
|
||||
@@ -131,9 +149,9 @@ public interface IndexOperations {
|
||||
Map<String, Object> getSettings();
|
||||
|
||||
/**
|
||||
* Get settings for a given indexName.
|
||||
* Get the index settings.
|
||||
*
|
||||
* @param includeDefaults wehther or not to include all the default settings
|
||||
* @param includeDefaults whether or not to include all the default settings
|
||||
* @return the settings
|
||||
*/
|
||||
Map<String, Object> getSettings(boolean includeDefaults);
|
||||
|
||||
+52
-18
@@ -38,7 +38,7 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public interface ReactiveDocumentOperations {
|
||||
/**
|
||||
* Index the given entity, once available, extracting index and type from entity metadata.
|
||||
* Index the given entity, once available, extracting index from entity metadata.
|
||||
*
|
||||
* @param entityPublisher must not be {@literal null}.
|
||||
* @param <T>
|
||||
@@ -50,15 +50,6 @@ public interface ReactiveDocumentOperations {
|
||||
return entityPublisher.flatMap(this::save);
|
||||
}
|
||||
|
||||
/**
|
||||
* Index the given entity extracting index and type from entity metadata.
|
||||
*
|
||||
* @param entity must not be {@literal null}.
|
||||
* @param <T>
|
||||
* @return a {@link Mono} emitting the saved entity.
|
||||
*/
|
||||
<T> Mono<T> save(T entity);
|
||||
|
||||
/**
|
||||
* Index the entity, once available, under the given {@literal type} in the given {@literal index}. If the
|
||||
* {@literal index} is {@literal null} or empty the index name provided via entity metadata is used. Same for the
|
||||
@@ -75,6 +66,15 @@ public interface ReactiveDocumentOperations {
|
||||
return entityPublisher.flatMap(it -> save(it, index));
|
||||
}
|
||||
|
||||
/**
|
||||
* Index the given entity extracting index from entity metadata.
|
||||
*
|
||||
* @param entity must not be {@literal null}.
|
||||
* @param <T>
|
||||
* @return a {@link Mono} emitting the saved entity.
|
||||
*/
|
||||
<T> Mono<T> save(T entity);
|
||||
|
||||
/**
|
||||
* Index the entity under the given {@literal type} in the given {@literal index}. If the {@literal index} is
|
||||
* {@literal null} or empty the index name provided via entity metadata is used. Same for the {@literal type}.
|
||||
@@ -87,7 +87,21 @@ public interface ReactiveDocumentOperations {
|
||||
<T> Mono<T> save(T entity, IndexCoordinates index);
|
||||
|
||||
/**
|
||||
* Index entities under the given {@literal type} in the given {@literal index}. If the {@literal index} is
|
||||
* Index entities the index extracted from entity metadata.
|
||||
*
|
||||
* @param entities must not be {@literal null}.
|
||||
* @param clazz the entity class, used to determine the index
|
||||
* @return a {@link Flux} emitting saved entities.
|
||||
* @since 4.1
|
||||
*/
|
||||
default <T> Flux<T> saveAll(Iterable<T> entities, Class<T> clazz) {
|
||||
List<T> entityList = new ArrayList<>();
|
||||
entities.forEach(entityList::add);
|
||||
return saveAll(Mono.just(entityList), clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Index entities in the given {@literal index}. If the {@literal index} is
|
||||
* {@literal null} or empty the index name provided via entity metadata is used.
|
||||
*
|
||||
* @param entities must not be {@literal null}.
|
||||
@@ -103,7 +117,17 @@ public interface ReactiveDocumentOperations {
|
||||
}
|
||||
|
||||
/**
|
||||
* Index entities under the given {@literal type} in the given {@literal index}. If the {@literal index} is
|
||||
* Index entities in the index extracted from entity metadata.
|
||||
*
|
||||
* @param entities must not be {@literal null}.
|
||||
* @param clazz the entity class, used to determine the index
|
||||
* @return a {@link Flux} emitting saved entities.
|
||||
* @since 4.1
|
||||
*/
|
||||
<T> Flux<T> saveAll(Mono<? extends Collection<? extends T>> entities, Class<T> clazz);
|
||||
|
||||
/**
|
||||
* Index entities in the given {@literal index}. If the {@literal index} is
|
||||
* {@literal null} or empty the index name provided via entity metadata is used.
|
||||
*
|
||||
* @param entities must not be {@literal null}.
|
||||
@@ -114,6 +138,16 @@ public interface ReactiveDocumentOperations {
|
||||
*/
|
||||
<T> Flux<T> saveAll(Mono<? extends Collection<? extends T>> entities, IndexCoordinates index);
|
||||
|
||||
/**
|
||||
* Execute a multiGet against elasticsearch for the given ids.
|
||||
*
|
||||
* @param query the query defining the ids of the objects to get
|
||||
* @param clazz the type of the object to be returned, used to determine the index
|
||||
* @return flux with list of nullable objects
|
||||
* @since 4.1
|
||||
*/
|
||||
<T> Flux<T> multiGet(Query query, Class<T> clazz);
|
||||
|
||||
/**
|
||||
* Execute a multiGet against elasticsearch for the given ids.
|
||||
*
|
||||
@@ -223,7 +257,7 @@ public interface ReactiveDocumentOperations {
|
||||
Mono<Boolean> exists(String id, Class<?> entityType, IndexCoordinates index);
|
||||
|
||||
/**
|
||||
* Delete the given entity extracting index and type from entity metadata.
|
||||
* Delete the given entity extracting index from entity metadata.
|
||||
*
|
||||
* @param entity must not be {@literal null}.
|
||||
* @return a {@link Mono} emitting the {@literal id} of the removed document.
|
||||
@@ -231,7 +265,7 @@ public interface ReactiveDocumentOperations {
|
||||
Mono<String> delete(Object entity);
|
||||
|
||||
/**
|
||||
* Delete the given entity extracting index and type from entity metadata.
|
||||
* Delete the given entity extracting index from entity metadata.
|
||||
*
|
||||
* @param entity must not be {@literal null}.
|
||||
* @param index the target index, must not be {@literal null}
|
||||
@@ -249,7 +283,7 @@ public interface ReactiveDocumentOperations {
|
||||
Mono<String> delete(String id, IndexCoordinates index);
|
||||
|
||||
/**
|
||||
* Delete the entity with given {@literal id} extracting index and type from entity metadata.
|
||||
* Delete the entity with given {@literal id} extracting index from entity metadata.
|
||||
*
|
||||
* @param id must not be {@literal null}.
|
||||
* @param entityType must not be {@literal null}.
|
||||
@@ -259,7 +293,7 @@ public interface ReactiveDocumentOperations {
|
||||
Mono<String> delete(String id, Class<?> entityType);
|
||||
|
||||
/**
|
||||
* Delete the entity with given {@literal id} extracting index and type from entity metadata.
|
||||
* Delete the entity with given {@literal id} extracting index from entity metadata.
|
||||
*
|
||||
* @param id must not be {@literal null}.
|
||||
* @param entityType must not be {@literal null}.
|
||||
@@ -273,7 +307,7 @@ public interface ReactiveDocumentOperations {
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the documents matching the given {@link Query} extracting index and type from entity metadata.
|
||||
* Delete the documents matching the given {@link Query} extracting index from entity metadata.
|
||||
*
|
||||
* @param query must not be {@literal null}.
|
||||
* @param entityType must not be {@literal null}.
|
||||
@@ -282,7 +316,7 @@ public interface ReactiveDocumentOperations {
|
||||
Mono<Long> delete(Query query, Class<?> entityType);
|
||||
|
||||
/**
|
||||
* Delete the documents matching the given {@link Query} extracting index and type from entity metadata.
|
||||
* Delete the documents matching the given {@link Query} extracting index from entity metadata.
|
||||
*
|
||||
* @param query must not be {@literal null}.
|
||||
* @param entityType must not be {@literal null}.
|
||||
|
||||
+38
-1
@@ -40,11 +40,21 @@ public interface ReactiveElasticsearchOperations extends ReactiveDocumentOperati
|
||||
* Execute within a {@link ClientCallback} managing resources and translating errors.
|
||||
*
|
||||
* @param callback must not be {@literal null}.
|
||||
* @param <T>
|
||||
* @param <T> the type the Publisher emits
|
||||
* @return the {@link Publisher} emitting results.
|
||||
*/
|
||||
<T> Publisher<T> execute(ClientCallback<Publisher<T>> callback);
|
||||
|
||||
/**
|
||||
* Execute within a {@link IndicesClientCallback} managing resources and translating errors.
|
||||
*
|
||||
* @param callback must not be {@literal null}.
|
||||
* @param <T> the type the Publisher emits
|
||||
* @return the {@link Publisher} emitting results.
|
||||
* @since 4.1
|
||||
*/
|
||||
<T> Publisher<T> executeWithIndicesClient(IndicesClientCallback<Publisher<T>> callback);
|
||||
|
||||
/**
|
||||
* Get the {@link ElasticsearchConverter} used.
|
||||
*
|
||||
@@ -62,6 +72,22 @@ public interface ReactiveElasticsearchOperations extends ReactiveDocumentOperati
|
||||
*/
|
||||
IndexCoordinates getIndexCoordinatesFor(Class<?> clazz);
|
||||
|
||||
/**
|
||||
* Creates a {@link ReactiveIndexOperations} that is bound to the given index
|
||||
* @param index IndexCoordinates specifying the index
|
||||
* @return ReactiveIndexOperations implementation
|
||||
* @since 4.1
|
||||
*/
|
||||
ReactiveIndexOperations indexOps(IndexCoordinates index);
|
||||
|
||||
/**
|
||||
* Creates a {@link ReactiveIndexOperations} that is bound to the given class
|
||||
* @param clazz the entity clazz specifiying the index information
|
||||
* @return ReactiveIndexOperations implementation
|
||||
* @since 4.1
|
||||
*/
|
||||
ReactiveIndexOperations indexOps(Class<?> clazz);
|
||||
|
||||
/**
|
||||
* Callback interface to be used with {@link #execute(ClientCallback)} for operating directly on
|
||||
* {@link ReactiveElasticsearchClient}.
|
||||
@@ -74,4 +100,15 @@ public interface ReactiveElasticsearchOperations extends ReactiveDocumentOperati
|
||||
|
||||
T doWithClient(ReactiveElasticsearchClient client);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback interface to be used with {@link #executeWithIndicesClient(IndicesClientCallback)} for operating directly on
|
||||
* {@link ReactiveElasticsearchClient.Indices}.
|
||||
*
|
||||
* @param <T> the return type
|
||||
* @since 4.1
|
||||
*/
|
||||
interface IndicesClientCallback<T extends Publisher<?>> {
|
||||
T doWithClient(ReactiveElasticsearchClient.Indices client);
|
||||
}
|
||||
}
|
||||
|
||||
+106
-46
@@ -41,6 +41,8 @@ import org.elasticsearch.index.get.GetResult;
|
||||
import org.elasticsearch.index.reindex.BulkByScrollResponse;
|
||||
import org.elasticsearch.index.reindex.DeleteByQueryRequest;
|
||||
import org.elasticsearch.search.aggregations.Aggregation;
|
||||
import org.elasticsearch.search.suggest.Suggest;
|
||||
import org.elasticsearch.search.suggest.SuggestBuilder;
|
||||
import org.reactivestreams.Publisher;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -90,6 +92,7 @@ import org.springframework.util.Assert;
|
||||
* @author Aleksei Arsenev
|
||||
* @author Roman Puchkovskiy
|
||||
* @author Russell Parry
|
||||
* @author Thomas Geese
|
||||
* @since 3.2
|
||||
*/
|
||||
public class ReactiveElasticsearchTemplate implements ReactiveElasticsearchOperations, ApplicationContextAware {
|
||||
@@ -144,6 +147,32 @@ public class ReactiveElasticsearchTemplate implements ReactiveElasticsearchOpera
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default {@link RefreshPolicy} to apply when writing to Elasticsearch.
|
||||
*
|
||||
* @param refreshPolicy can be {@literal null}.
|
||||
*/
|
||||
public void setRefreshPolicy(@Nullable RefreshPolicy refreshPolicy) {
|
||||
this.refreshPolicy = refreshPolicy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the current {@link RefreshPolicy}.
|
||||
*/
|
||||
@Nullable
|
||||
public RefreshPolicy getRefreshPolicy() {
|
||||
return refreshPolicy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default {@link IndicesOptions} for {@link SearchRequest search requests}.
|
||||
*
|
||||
* @param indicesOptions can be {@literal null}.
|
||||
*/
|
||||
public void setIndicesOptions(@Nullable IndicesOptions indicesOptions) {
|
||||
this.indicesOptions = indicesOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link ReactiveEntityCallbacks} instance to use when invoking {@link ReactiveEntityCallbacks callbacks}
|
||||
* like the {@link ReactiveBeforeConvertCallback}.
|
||||
@@ -160,7 +189,6 @@ public class ReactiveElasticsearchTemplate implements ReactiveElasticsearchOpera
|
||||
|
||||
this.entityCallbacks = entityCallbacks;
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region DocumentOperations
|
||||
@@ -189,30 +217,44 @@ public class ReactiveElasticsearchTemplate implements ReactiveElasticsearchOpera
|
||||
return save(entity, getIndexCoordinatesFor(entity.getClass()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Flux<T> saveAll(Mono<? extends Collection<? extends T>> entities, Class<T> clazz) {
|
||||
return saveAll(entities, getIndexCoordinatesFor(clazz));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Flux<T> saveAll(Mono<? extends Collection<? extends T>> entitiesPublisher, IndexCoordinates index) {
|
||||
|
||||
Assert.notNull(entitiesPublisher, "Entities must not be null!");
|
||||
|
||||
return entitiesPublisher.flatMapMany(entities -> {
|
||||
return Flux.fromIterable(entities) //
|
||||
.concatMap(entity -> maybeCallBeforeConvert(entity, index));
|
||||
}).collectList().map(Entities::new).flatMapMany(entities -> {
|
||||
if (entities.isEmpty()) {
|
||||
return Flux.empty();
|
||||
}
|
||||
return entitiesPublisher //
|
||||
.flatMapMany(entities -> Flux.fromIterable(entities) //
|
||||
.concatMap(entity -> maybeCallBeforeConvert(entity, index)) //
|
||||
).collectList() //
|
||||
.map(Entities::new) //
|
||||
.flatMapMany(entities -> {
|
||||
|
||||
return doBulkOperation(entities.indexQueries(), BulkOptions.defaultOptions(), index) //
|
||||
.index().flatMap(indexAndResponse -> {
|
||||
T savedEntity = entities.entityAt(indexAndResponse.getT1());
|
||||
BulkItemResponse bulkItemResponse = indexAndResponse.getT2();
|
||||
if (entities.isEmpty()) {
|
||||
return Flux.empty();
|
||||
}
|
||||
|
||||
AdaptibleEntity<T> adaptibleEntity = operations.forEntity(savedEntity, converter.getConversionService());
|
||||
adaptibleEntity.populateIdIfNecessary(bulkItemResponse.getResponse().getId());
|
||||
return doBulkOperation(entities.indexQueries(), BulkOptions.defaultOptions(), index) //
|
||||
.index().flatMap(indexAndResponse -> {
|
||||
T savedEntity = entities.entityAt(indexAndResponse.getT1());
|
||||
BulkItemResponse bulkItemResponse = indexAndResponse.getT2();
|
||||
|
||||
return maybeCallAfterSave(savedEntity, index);
|
||||
});
|
||||
});
|
||||
AdaptibleEntity<T> adaptibleEntity = operations.forEntity(savedEntity,
|
||||
converter.getConversionService());
|
||||
adaptibleEntity.populateIdIfNecessary(bulkItemResponse.getResponse().getId());
|
||||
|
||||
return maybeCallAfterSave(savedEntity, index);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Flux<T> multiGet(Query query, Class<T> clazz) {
|
||||
return multiGet(query, clazz, getIndexCoordinatesFor(clazz));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -601,6 +643,23 @@ public class ReactiveElasticsearchTemplate implements ReactiveElasticsearchOpera
|
||||
return doAggregate(query, entityType, index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<Suggest> suggest(SuggestBuilder suggestion, Class<?> entityType) {
|
||||
return doSuggest(suggestion, getIndexCoordinatesFor(entityType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<Suggest> suggest(SuggestBuilder suggestion, IndexCoordinates index) {
|
||||
return doSuggest(suggestion, index);
|
||||
}
|
||||
|
||||
private Flux<Suggest> doSuggest(SuggestBuilder suggestion, IndexCoordinates index) {
|
||||
return Flux.defer(() -> {
|
||||
SearchRequest request = requestFactory.searchRequest(suggestion, index);
|
||||
return Flux.from(execute(client -> client.suggest(request)));
|
||||
});
|
||||
}
|
||||
|
||||
private Flux<Aggregation> doAggregate(Query query, Class<?> entityType, IndexCoordinates index) {
|
||||
return Flux.defer(() -> {
|
||||
SearchRequest request = requestFactory.searchRequest(query, entityType, index);
|
||||
@@ -720,44 +779,31 @@ public class ReactiveElasticsearchTemplate implements ReactiveElasticsearchOpera
|
||||
|
||||
// endregion
|
||||
|
||||
// Property Setters / Getters
|
||||
|
||||
/**
|
||||
* Set the default {@link RefreshPolicy} to apply when writing to Elasticsearch.
|
||||
*
|
||||
* @param refreshPolicy can be {@literal null}.
|
||||
*/
|
||||
public void setRefreshPolicy(@Nullable RefreshPolicy refreshPolicy) {
|
||||
this.refreshPolicy = refreshPolicy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default {@link IndicesOptions} for {@link SearchRequest search requests}.
|
||||
*
|
||||
* @param indicesOptions can be {@literal null}.
|
||||
*/
|
||||
public void setIndicesOptions(@Nullable IndicesOptions indicesOptions) {
|
||||
this.indicesOptions = indicesOptions;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations#exctute(ClientCallback)
|
||||
*/
|
||||
@Override
|
||||
public <T> Publisher<T> execute(ClientCallback<Publisher<T>> callback) {
|
||||
return Flux.defer(() -> callback.doWithClient(getClient())).onErrorMap(this::translateException);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations#getElasticsearchConverter()
|
||||
*/
|
||||
@Override
|
||||
public <T> Publisher<T> executeWithIndicesClient(IndicesClientCallback<Publisher<T>> callback) {
|
||||
return Flux.defer(() -> callback.doWithClient(getIndicesClient())).onErrorMap(this::translateException);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ElasticsearchConverter getElasticsearchConverter() {
|
||||
return converter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReactiveIndexOperations indexOps(IndexCoordinates index) {
|
||||
return new DefaultReactiveIndexOperations(this, index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReactiveIndexOperations indexOps(Class<?> clazz) {
|
||||
return new DefaultReactiveIndexOperations(this, clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IndexCoordinates getIndexCoordinatesFor(Class<?> clazz) {
|
||||
return getPersistentEntityFor(clazz).getIndexCoordinates();
|
||||
@@ -778,6 +824,20 @@ public class ReactiveElasticsearchTemplate implements ReactiveElasticsearchOpera
|
||||
return this.client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the {@link ReactiveElasticsearchClient.Indices} to operate upon.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
*/
|
||||
protected ReactiveElasticsearchClient.Indices getIndicesClient() {
|
||||
|
||||
if (client instanceof ReactiveElasticsearchClient.Indices) {
|
||||
return (ReactiveElasticsearchClient.Indices) client;
|
||||
}
|
||||
|
||||
throw new UncategorizedElasticsearchException("No ReactiveElasticsearchClient.Indices implementation available");
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
/**
|
||||
@@ -878,7 +938,7 @@ public class ReactiveElasticsearchTemplate implements ReactiveElasticsearchOpera
|
||||
@Override
|
||||
public Mono<SearchHit<T>> doWith(SearchDocument response) {
|
||||
return delegate.doWith(response)
|
||||
.map(entity -> SearchHitMapping.mappingFor(type, converter.getMappingContext()).mapHit(response, entity));
|
||||
.map(entity -> SearchHitMapping.mappingFor(type, converter).mapHit(response, entity));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright 2020 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;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.data.elasticsearch.core.document.Document;
|
||||
|
||||
/**
|
||||
* Interface defining operations on indexes for the reactive stack.
|
||||
*
|
||||
* @author Peter-Josef Meisch
|
||||
* @since 4.1
|
||||
*/
|
||||
public interface ReactiveIndexOperations {
|
||||
|
||||
/**
|
||||
* Create an index.
|
||||
*
|
||||
* @return a {@link Mono} signalling successful operation completion or an {@link Mono#error(Throwable) error} if eg.
|
||||
* the index already exist.
|
||||
*/
|
||||
Mono<Boolean> create();
|
||||
|
||||
/**
|
||||
* Create an index with the specified settings.
|
||||
*
|
||||
* @param settings index settings
|
||||
* @return a {@link Mono} signalling successful operation completion or an {@link Mono#error(Throwable) error} if eg.
|
||||
* the index already exist.
|
||||
*/
|
||||
Mono<Boolean> create(Document settings);
|
||||
|
||||
/**
|
||||
* Delete an index.
|
||||
*
|
||||
* @return a {@link Mono} signalling operation completion or an {@link Mono#error(Throwable) error}. If the index does
|
||||
* not exist, a value of {@literal false is emitted}.
|
||||
*/
|
||||
Mono<Boolean> delete();
|
||||
|
||||
/**
|
||||
* checks if an index exists
|
||||
*
|
||||
* @return a {@link Mono} with the result of exist check
|
||||
*/
|
||||
Mono<Boolean> exists();
|
||||
|
||||
/**
|
||||
* Refresh the index(es) this IndexOperations is bound to
|
||||
*
|
||||
* @return a {@link Mono} signalling operation completion.
|
||||
*/
|
||||
Mono<Void> refresh();
|
||||
|
||||
/**
|
||||
* Creates the index mapping for the entity this IndexOperations is bound to.
|
||||
*
|
||||
* @return mapping object
|
||||
*/
|
||||
Mono<Document> createMapping();
|
||||
|
||||
/**
|
||||
* Creates the index mapping for the given class
|
||||
*
|
||||
* @param clazz the clazz to create a mapping for
|
||||
* @return a {@link Mono} with the mapping document
|
||||
*/
|
||||
Mono<Document> createMapping(Class<?> clazz);
|
||||
|
||||
/**
|
||||
* Writes the mapping to the index for the class this IndexOperations is bound to.
|
||||
*
|
||||
* @return {@literal true} if the mapping could be stored
|
||||
*/
|
||||
default Mono<Boolean> putMapping() {
|
||||
return putMapping(createMapping());
|
||||
}
|
||||
|
||||
/**
|
||||
* writes a mapping to the index
|
||||
*
|
||||
* @param mapping the Document with the mapping definitions
|
||||
* @return {@literal true} if the mapping could be stored
|
||||
*/
|
||||
Mono<Boolean> putMapping(Mono<Document> mapping);
|
||||
|
||||
/**
|
||||
* Creates the index mapping for the given class and writes it to the index.
|
||||
*
|
||||
* @param clazz the clazz to create a mapping for
|
||||
* @return {@literal true} if the mapping could be stored
|
||||
*/
|
||||
default Mono<Boolean> putMapping(Class<?> clazz) {
|
||||
return putMapping(createMapping(clazz));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get mapping for the index targeted defined by this {@link ReactiveIndexOperations}
|
||||
*
|
||||
* @return the mapping
|
||||
*/
|
||||
Mono<Document> getMapping();
|
||||
|
||||
/**
|
||||
* get the settings for the index
|
||||
*
|
||||
* @return a {@link Mono} with a {@link Document} containing the index settings
|
||||
*/
|
||||
default Mono<Document> getSettings() {
|
||||
return getSettings(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* get the settings for the index
|
||||
*
|
||||
* @param includeDefaults whether or not to include all the default settings
|
||||
* @return a {@link Mono} with a {@link Document} containing the index settings
|
||||
*/
|
||||
Mono<Document> getSettings(boolean includeDefaults);
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2020 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;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.buffer.DataBufferUtils;
|
||||
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
|
||||
|
||||
/**
|
||||
* Utility to reactively read {@link org.springframework.core.io.Resource}s.
|
||||
*
|
||||
* @author Peter-Josef Meisch
|
||||
* @since 4.1
|
||||
*/
|
||||
public abstract class ReactiveResourceUtil {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ReactiveResourceUtil.class);
|
||||
private static final int BUFFER_SIZE = 8_192;
|
||||
|
||||
/**
|
||||
* Read a {@link ClassPathResource} into a {@link reactor.core.publisher.Mono<String>}.
|
||||
*
|
||||
* @param url the resource to read
|
||||
* @return a {@link reactor.core.publisher.Mono} emitting the resources content or an empty Mono on error
|
||||
*/
|
||||
public static Mono<String> readFileFromClasspath(String url) {
|
||||
|
||||
return DataBufferUtils
|
||||
.join(DataBufferUtils.read(new ClassPathResource(url), new DefaultDataBufferFactory(), BUFFER_SIZE))
|
||||
.<String> handle((it, sink) -> {
|
||||
|
||||
try (InputStream is = it.asInputStream();
|
||||
InputStreamReader in = new InputStreamReader(is, Charset.defaultCharset());
|
||||
BufferedReader br = new BufferedReader(in)) {
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
sb.append(line);
|
||||
}
|
||||
|
||||
sink.next(sb.toString());
|
||||
sink.complete();
|
||||
} catch (Exception e) {
|
||||
LOGGER.debug(String.format("Failed to load file from url: %s: %s", url, e.getMessage()));
|
||||
sink.complete();
|
||||
} finally {
|
||||
DataBufferUtils.release(it);
|
||||
}
|
||||
}).onErrorResume(throwable -> {
|
||||
LOGGER.debug(String.format("Failed to load file from url: %s: %s", url, throwable.getMessage()));
|
||||
return Mono.empty();
|
||||
});
|
||||
}
|
||||
|
||||
// Utility constructor
|
||||
private ReactiveResourceUtil() {}
|
||||
}
|
||||
+21
@@ -20,6 +20,8 @@ import reactor.core.publisher.Mono;
|
||||
|
||||
import org.elasticsearch.index.query.QueryBuilders;
|
||||
import org.elasticsearch.search.aggregations.Aggregation;
|
||||
import org.elasticsearch.search.suggest.Suggest;
|
||||
import org.elasticsearch.search.suggest.SuggestBuilder;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
import org.springframework.data.elasticsearch.core.query.Query;
|
||||
@@ -32,6 +34,7 @@ import org.springframework.data.elasticsearch.core.query.StringQuery;
|
||||
*
|
||||
* @author Peter-Josef Meisch
|
||||
* @author Russell Parry
|
||||
* @author Thomas Geese
|
||||
* @since 4.0
|
||||
*/
|
||||
public interface ReactiveSearchOperations {
|
||||
@@ -206,4 +209,22 @@ public interface ReactiveSearchOperations {
|
||||
* @since 4.0
|
||||
*/
|
||||
Flux<Aggregation> aggregate(Query query, Class<?> entityType, IndexCoordinates index);
|
||||
|
||||
/**
|
||||
* Does a suggest query
|
||||
*
|
||||
* @param suggestion the query
|
||||
* @param entityType must not be {@literal null}.
|
||||
* @return the suggest response
|
||||
*/
|
||||
Flux<Suggest> suggest(SuggestBuilder suggestion, Class<?> entityType);
|
||||
|
||||
/**
|
||||
* Does a suggest query
|
||||
*
|
||||
* @param suggestion the query
|
||||
* @param index the index to run the query against
|
||||
* @return the suggest response
|
||||
*/
|
||||
Flux<Suggest> suggest(SuggestBuilder suggestion, IndexCoordinates index);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -23,6 +23,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.data.elasticsearch.core.document.NestedMetaData;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -35,24 +36,50 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class SearchHit<T> {
|
||||
|
||||
private final String id;
|
||||
@Nullable private final String index;
|
||||
@Nullable private final String id;
|
||||
private final float score;
|
||||
private final List<Object> sortValues;
|
||||
private final T content;
|
||||
private final Map<String, List<String>> highlightFields = new LinkedHashMap<>();
|
||||
private final Map<String, SearchHits<?>> innerHits = new LinkedHashMap<>();
|
||||
@Nullable private final NestedMetaData nestedMetaData;
|
||||
|
||||
public SearchHit(@Nullable String id, float score, @Nullable Object[] sortValues,
|
||||
public SearchHit(@Nullable String index, @Nullable String id, float score, @Nullable Object[] sortValues,
|
||||
@Nullable Map<String, List<String>> highlightFields, T content) {
|
||||
this(index, id, score, sortValues, highlightFields, null, null, content);
|
||||
}
|
||||
|
||||
public SearchHit(@Nullable String index, @Nullable String id, float score, @Nullable Object[] sortValues,
|
||||
@Nullable Map<String, List<String>> highlightFields, @Nullable Map<String, SearchHits<?>> innerHits,
|
||||
@Nullable NestedMetaData nestedMetaData, T content) {
|
||||
this.index = index;
|
||||
this.id = id;
|
||||
this.score = score;
|
||||
this.sortValues = (sortValues != null) ? Arrays.asList(sortValues) : new ArrayList<>();
|
||||
|
||||
if (highlightFields != null) {
|
||||
this.highlightFields.putAll(highlightFields);
|
||||
}
|
||||
|
||||
if (innerHits != null) {
|
||||
this.innerHits.putAll(innerHits);
|
||||
}
|
||||
|
||||
this.nestedMetaData = nestedMetaData;
|
||||
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the index name where the hit's document was found
|
||||
* @since 4.1
|
||||
*/
|
||||
@Nullable
|
||||
public String getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getId() {
|
||||
return id;
|
||||
@@ -79,6 +106,9 @@ public class SearchHit<T> {
|
||||
return Collections.unmodifiableList(sortValues);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the map from field names to highlight values, never {@literal null}
|
||||
*/
|
||||
public Map<String, List<String>> getHighlightFields() {
|
||||
return Collections.unmodifiableMap(highlightFields.entrySet().stream()
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, entry -> Collections.unmodifiableList(entry.getValue()))));
|
||||
@@ -97,6 +127,39 @@ public class SearchHit<T> {
|
||||
return Collections.unmodifiableList(highlightFields.getOrDefault(field, Collections.emptyList()));
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the {@link SearchHits} for the inner hits with the given name. If the inner hits could be mapped to a
|
||||
* nested entity class, the returned data will be of this type, otherwise
|
||||
* {{@link org.springframework.data.elasticsearch.core.document.SearchDocument}} instances are returned in this
|
||||
* {@link SearchHits} object.
|
||||
*
|
||||
* @param name the inner hits name
|
||||
* @return {@link SearchHits} if available, otherwise {@literal null}
|
||||
*/
|
||||
@Nullable
|
||||
public SearchHits<?> getInnerHits(String name) {
|
||||
return innerHits.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the map from inner_hits names to inner hits, in a {@link SearchHits} object, never {@literal null}
|
||||
* @since 4.1
|
||||
*/
|
||||
public Map<String, SearchHits<?>> getInnerHits() {
|
||||
return innerHits;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this is a nested inner hit, return the nested metadata information
|
||||
*
|
||||
* @return {{@link NestedMetaData}
|
||||
* @since 4.1
|
||||
*/
|
||||
@Nullable
|
||||
public NestedMetaData getNestedMetaData() {
|
||||
return nestedMetaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SearchHit{" + "id='" + id + '\'' + ", score=" + score + ", sortValues=" + sortValues + ", content="
|
||||
|
||||
@@ -16,11 +16,18 @@
|
||||
package org.springframework.data.elasticsearch.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.elasticsearch.search.aggregations.Aggregations;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
||||
import org.springframework.data.elasticsearch.core.document.Document;
|
||||
import org.springframework.data.elasticsearch.core.document.NestedMetaData;
|
||||
import org.springframework.data.elasticsearch.core.document.SearchDocument;
|
||||
import org.springframework.data.elasticsearch.core.document.SearchDocumentResponse;
|
||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
|
||||
@@ -39,35 +46,24 @@ import org.springframework.util.Assert;
|
||||
* @since 4.0
|
||||
*/
|
||||
class SearchHitMapping<T> {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(SearchHitMapping.class);
|
||||
|
||||
private final Class<T> type;
|
||||
private final ElasticsearchConverter converter;
|
||||
private final MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext;
|
||||
|
||||
private SearchHitMapping(Class<T> type,
|
||||
MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> context) {
|
||||
|
||||
private SearchHitMapping(Class<T> type, ElasticsearchConverter converter) {
|
||||
Assert.notNull(type, "type is null");
|
||||
Assert.notNull(context, "context is null");
|
||||
Assert.notNull(converter, "converter is null");
|
||||
|
||||
this.type = type;
|
||||
this.mappingContext = context;
|
||||
this.converter = converter;
|
||||
this.mappingContext = converter.getMappingContext();
|
||||
}
|
||||
|
||||
static <T> SearchHitMapping<T> mappingFor(Class<T> entityClass,
|
||||
MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> context) {
|
||||
return new SearchHitMapping<>(entityClass, context);
|
||||
}
|
||||
|
||||
SearchHit<T> mapHit(SearchDocument searchDocument, T content) {
|
||||
|
||||
Assert.notNull(searchDocument, "searchDocument is null");
|
||||
Assert.notNull(content, "content is null");
|
||||
|
||||
String id = searchDocument.hasId() ? searchDocument.getId() : null;
|
||||
float score = searchDocument.getScore();
|
||||
Object[] sortValues = searchDocument.getSortValues();
|
||||
Map<String, List<String>> highlightFields = getHighlightsAndRemapFieldNames(searchDocument);
|
||||
|
||||
return new SearchHit<>(id, score, sortValues, highlightFields, content);
|
||||
static <T> SearchHitMapping<T> mappingFor(Class<T> entityClass, ElasticsearchConverter converter) {
|
||||
return new SearchHitMapping<>(entityClass, converter);
|
||||
}
|
||||
|
||||
SearchHits<T> mapHits(SearchDocumentResponse searchDocumentResponse, List<T> contents) {
|
||||
@@ -104,6 +100,21 @@ class SearchHitMapping<T> {
|
||||
return new SearchHitsImpl<>(totalHits, totalHitsRelation, maxScore, scrollId, searchHits, aggregations);
|
||||
}
|
||||
|
||||
SearchHit<T> mapHit(SearchDocument searchDocument, T content) {
|
||||
|
||||
Assert.notNull(searchDocument, "searchDocument is null");
|
||||
Assert.notNull(content, "content is null");
|
||||
|
||||
return new SearchHit<T>(searchDocument.getIndex(), //
|
||||
searchDocument.hasId() ? searchDocument.getId() : null, //
|
||||
searchDocument.getScore(), //
|
||||
searchDocument.getSortValues(), //
|
||||
getHighlightsAndRemapFieldNames(searchDocument), //
|
||||
mapInnerHits(searchDocument), //
|
||||
searchDocument.getNestedMetaData(), //
|
||||
content); //
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Map<String, List<String>> getHighlightsAndRemapFieldNames(SearchDocument searchDocument) {
|
||||
Map<String, List<String>> highlightFields = searchDocument.getHighlightFields();
|
||||
@@ -122,4 +133,131 @@ class SearchHitMapping<T> {
|
||||
return property != null ? property.getName() : entry.getKey();
|
||||
}, Map.Entry::getValue));
|
||||
}
|
||||
|
||||
private Map<String, SearchHits<?>> mapInnerHits(SearchDocument searchDocument) {
|
||||
|
||||
Map<String, SearchHits<?>> innerHits = new LinkedHashMap<>();
|
||||
Map<String, SearchDocumentResponse> documentInnerHits = searchDocument.getInnerHits();
|
||||
|
||||
if (documentInnerHits != null && documentInnerHits.size() > 0) {
|
||||
|
||||
SearchHitMapping<SearchDocument> searchDocumentSearchHitMapping = SearchHitMapping
|
||||
.mappingFor(SearchDocument.class, converter);
|
||||
|
||||
for (Map.Entry<String, SearchDocumentResponse> entry : documentInnerHits.entrySet()) {
|
||||
SearchDocumentResponse searchDocumentResponse = entry.getValue();
|
||||
|
||||
SearchHits<SearchDocument> searchHits = searchDocumentSearchHitMapping
|
||||
.mapHitsFromResponse(searchDocumentResponse, searchDocumentResponse.getSearchDocuments());
|
||||
|
||||
// map Documents to real objects
|
||||
SearchHits<?> mappedSearchHits = mapInnerDocuments(searchHits, type);
|
||||
|
||||
innerHits.put(entry.getKey(), mappedSearchHits);
|
||||
}
|
||||
|
||||
}
|
||||
return innerHits;
|
||||
}
|
||||
|
||||
/**
|
||||
* try to convert the SearchDocument instances to instances of the inner property class.
|
||||
*
|
||||
* @param searchHits {@link SearchHits} containing {@link Document} instances
|
||||
* @param type the class of the containing class
|
||||
* @return a new {@link SearchHits} instance containing the mapped objects or the original inout if any error occurs
|
||||
*/
|
||||
private SearchHits<?> mapInnerDocuments(SearchHits<SearchDocument> searchHits, Class<T> type) {
|
||||
|
||||
if (searchHits.getTotalHits() == 0) {
|
||||
return searchHits;
|
||||
}
|
||||
|
||||
try {
|
||||
NestedMetaData nestedMetaData = searchHits.getSearchHit(0).getContent().getNestedMetaData();
|
||||
ElasticsearchPersistentEntityWithNestedMetaData persistentEntityWithNestedMetaData = getPersistentEntity(
|
||||
mappingContext.getPersistentEntity(type), nestedMetaData);
|
||||
|
||||
if (persistentEntityWithNestedMetaData.entity != null) {
|
||||
List<SearchHit<Object>> convertedSearchHits = new ArrayList<>();
|
||||
Class<?> targetType = persistentEntityWithNestedMetaData.entity.getType();
|
||||
|
||||
// convert the list of SearchHit<SearchDocument> to list of SearchHit<Object>
|
||||
searchHits.getSearchHits().forEach(searchHit -> {
|
||||
SearchDocument searchDocument = searchHit.getContent();
|
||||
|
||||
Object targetObject = converter.read(targetType, searchDocument);
|
||||
convertedSearchHits.add(new SearchHit<Object>(searchDocument.getIndex(), //
|
||||
searchDocument.getId(), //
|
||||
searchDocument.getScore(), //
|
||||
searchDocument.getSortValues(), //
|
||||
searchDocument.getHighlightFields(), //
|
||||
searchHit.getInnerHits(), //
|
||||
persistentEntityWithNestedMetaData.nestedMetaData, //
|
||||
targetObject));
|
||||
});
|
||||
|
||||
String scrollId = null;
|
||||
if (searchHits instanceof SearchHitsImpl) {
|
||||
scrollId = ((SearchHitsImpl<?>) searchHits).getScrollId();
|
||||
}
|
||||
|
||||
return new SearchHitsImpl<>(searchHits.getTotalHits(), //
|
||||
searchHits.getTotalHitsRelation(), //
|
||||
searchHits.getMaxScore(), //
|
||||
scrollId, //
|
||||
convertedSearchHits, //
|
||||
searchHits.getAggregations());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn("Could not map inner_hits", e);
|
||||
}
|
||||
|
||||
return searchHits;
|
||||
}
|
||||
|
||||
/**
|
||||
* find a {@link ElasticsearchPersistentEntity} following the property chain defined by the nested metadata
|
||||
*
|
||||
* @param persistentEntity base entity
|
||||
* @param nestedMetaData nested metadata
|
||||
* @return A {@link ElasticsearchPersistentEntityWithNestedMetaData} containing the found entity or null together with
|
||||
* the {@link NestedMetaData} that has mapped field names.
|
||||
*/
|
||||
private ElasticsearchPersistentEntityWithNestedMetaData getPersistentEntity(
|
||||
@Nullable ElasticsearchPersistentEntity<?> persistentEntity, @Nullable NestedMetaData nestedMetaData) {
|
||||
|
||||
NestedMetaData currentMetaData = nestedMetaData;
|
||||
List<NestedMetaData> mappedNestedMetaDatas = new LinkedList<>();
|
||||
|
||||
while (persistentEntity != null && currentMetaData != null) {
|
||||
ElasticsearchPersistentProperty persistentProperty = persistentEntity
|
||||
.getPersistentPropertyWithFieldName(currentMetaData.getField());
|
||||
|
||||
if (persistentProperty == null) {
|
||||
persistentEntity = null;
|
||||
} else {
|
||||
persistentEntity = mappingContext.getPersistentEntity(persistentProperty.getActualType());
|
||||
mappedNestedMetaDatas.add(0,
|
||||
NestedMetaData.of(persistentProperty.getName(), currentMetaData.getOffset(), null));
|
||||
currentMetaData = currentMetaData.getChild();
|
||||
}
|
||||
}
|
||||
|
||||
NestedMetaData mappedNestedMetaData = mappedNestedMetaDatas.stream().reduce(null,
|
||||
(result, nmd) -> NestedMetaData.of(nmd.getField(), nmd.getOffset(), result));
|
||||
|
||||
return new ElasticsearchPersistentEntityWithNestedMetaData(persistentEntity, mappedNestedMetaData);
|
||||
}
|
||||
|
||||
private static class ElasticsearchPersistentEntityWithNestedMetaData {
|
||||
@Nullable private ElasticsearchPersistentEntity<?> entity;
|
||||
private NestedMetaData nestedMetaData;
|
||||
|
||||
public ElasticsearchPersistentEntityWithNestedMetaData(@Nullable ElasticsearchPersistentEntity<?> entity,
|
||||
NestedMetaData nestedMetaData) {
|
||||
this.entity = entity;
|
||||
this.nestedMetaData = nestedMetaData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,6 +241,16 @@ public interface SearchOperations {
|
||||
|
||||
// endregion
|
||||
|
||||
/**
|
||||
* Does a suggest query
|
||||
*
|
||||
* @param suggestion the query
|
||||
* @param the entity class
|
||||
* @return the suggest response
|
||||
* @since 4.1
|
||||
*/
|
||||
SearchResponse suggest(SuggestBuilder suggestion, Class<?> clazz);
|
||||
|
||||
/**
|
||||
* Does a suggest query
|
||||
*
|
||||
@@ -277,6 +287,17 @@ public interface SearchOperations {
|
||||
return content.isEmpty() ? null : content.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the multi search query against elasticsearch and return result as {@link List} of {@link SearchHits}.
|
||||
*
|
||||
* @param queries the queries to execute
|
||||
* @param clazz the entity clazz
|
||||
* @param <T> element return type
|
||||
* @return list of SearchHits
|
||||
* @since 4.1
|
||||
*/
|
||||
<T> List<SearchHits<T>> multiSearch(List<? extends Query> queries, Class<T> clazz);
|
||||
|
||||
/**
|
||||
* Execute the multi search query against elasticsearch and return result as {@link List} of {@link SearchHits}.
|
||||
*
|
||||
@@ -288,6 +309,16 @@ public interface SearchOperations {
|
||||
*/
|
||||
<T> List<SearchHits<T>> multiSearch(List<? extends Query> queries, Class<T> clazz, IndexCoordinates index);
|
||||
|
||||
/**
|
||||
* Execute the multi search query against elasticsearch and return result as {@link List} of {@link SearchHits}.
|
||||
*
|
||||
* @param queries the queries to execute
|
||||
* @param classes the entity classes
|
||||
* @return list of SearchHits
|
||||
* @since 4.1
|
||||
*/
|
||||
List<SearchHits<?>> multiSearch(List<? extends Query> queries, List<Class<?>> classes);
|
||||
|
||||
/**
|
||||
* Execute the multi search query against elasticsearch and return result as {@link List} of {@link SearchHits}.
|
||||
*
|
||||
|
||||
+5
-1
@@ -73,8 +73,12 @@ public interface ElasticsearchConverter
|
||||
* @return will not be {@literal null}.
|
||||
*/
|
||||
default Document mapObject(@Nullable Object source) {
|
||||
|
||||
Document target = Document.create();
|
||||
write(source, target);
|
||||
|
||||
if (source != null) {
|
||||
write(source, target);
|
||||
}
|
||||
return target;
|
||||
}
|
||||
// endregion
|
||||
|
||||
+5
-3
@@ -87,9 +87,9 @@ public class MappingElasticsearchConverter
|
||||
private final GenericConversionService conversionService;
|
||||
|
||||
private CustomConversions conversions = new ElasticsearchCustomConversions(Collections.emptyList());
|
||||
private EntityInstantiators instantiators = new EntityInstantiators();
|
||||
private final EntityInstantiators instantiators = new EntityInstantiators();
|
||||
|
||||
private ElasticsearchTypeMapper typeMapper;
|
||||
private final ElasticsearchTypeMapper typeMapper;
|
||||
|
||||
private ConcurrentHashMap<String, Integer> propertyWarnings = new ConcurrentHashMap<>();
|
||||
|
||||
@@ -596,7 +596,9 @@ public class MappingElasticsearchConverter
|
||||
Map<Object, Object> target = new LinkedHashMap<>();
|
||||
Streamable<Entry<String, Object>> mapSource = Streamable.of(value.entrySet());
|
||||
|
||||
if (!typeHint.getActualType().getType().equals(Object.class)
|
||||
TypeInformation<?> actualType = typeHint.getActualType();
|
||||
|
||||
if (actualType != null && !actualType.getType().equals(Object.class)
|
||||
&& isSimpleType(typeHint.getMapValueType().getType())) {
|
||||
mapSource.forEach(it -> {
|
||||
|
||||
|
||||
@@ -111,6 +111,27 @@ public interface Document extends Map<String, Object> {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the index if this document was retrieved from an index
|
||||
* @since 4.1
|
||||
*/
|
||||
@Nullable
|
||||
default String getIndex() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the index name for this document
|
||||
*
|
||||
* @param index index name
|
||||
* <p>
|
||||
* The default implementation throws {@link UnsupportedOperationException}.
|
||||
* @since 4.1
|
||||
*/
|
||||
default void setIndex(@Nullable String index) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the identifier associated with this {@link Document}.
|
||||
* <p>
|
||||
@@ -461,4 +482,5 @@ public interface Document extends Map<String, Object> {
|
||||
* @return a JSON representation of this document.
|
||||
*/
|
||||
String toJson();
|
||||
|
||||
}
|
||||
|
||||
+74
-247
@@ -22,6 +22,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -37,6 +38,7 @@ import org.elasticsearch.common.document.DocumentField;
|
||||
import org.elasticsearch.common.text.Text;
|
||||
import org.elasticsearch.index.get.GetResult;
|
||||
import org.elasticsearch.search.SearchHit;
|
||||
import org.elasticsearch.search.SearchHits;
|
||||
import org.springframework.data.elasticsearch.ElasticsearchException;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -77,11 +79,12 @@ public class DocumentAdapters {
|
||||
}
|
||||
|
||||
if (source.isSourceEmpty()) {
|
||||
return fromDocumentFields(source, source.getId(), source.getVersion(), source.getSeqNo(),
|
||||
return fromDocumentFields(source, source.getIndex(), source.getId(), source.getVersion(), source.getSeqNo(),
|
||||
source.getPrimaryTerm());
|
||||
}
|
||||
|
||||
Document document = Document.from(source.getSourceAsMap());
|
||||
document.setIndex(source.getIndex());
|
||||
document.setId(source.getId());
|
||||
document.setVersion(source.getVersion());
|
||||
document.setSeqNo(source.getSeqNo());
|
||||
@@ -108,11 +111,12 @@ public class DocumentAdapters {
|
||||
}
|
||||
|
||||
if (source.isSourceEmpty()) {
|
||||
return fromDocumentFields(source, source.getId(), source.getVersion(), source.getSeqNo(),
|
||||
return fromDocumentFields(source, source.getIndex(), source.getId(), source.getVersion(), source.getSeqNo(),
|
||||
source.getPrimaryTerm());
|
||||
}
|
||||
|
||||
Document document = Document.from(source.getSource());
|
||||
document.setIndex(source.getIndex());
|
||||
document.setId(source.getId());
|
||||
document.setVersion(source.getVersion());
|
||||
document.setSeqNo(source.getSeqNo());
|
||||
@@ -153,14 +157,32 @@ public class DocumentAdapters {
|
||||
.collect(Collectors.toMap(Map.Entry::getKey,
|
||||
entry -> Arrays.stream(entry.getValue().getFragments()).map(Text::string).collect(Collectors.toList()))));
|
||||
|
||||
Map<String, SearchDocumentResponse> innerHits = new LinkedHashMap<>();
|
||||
Map<String, SearchHits> sourceInnerHits = source.getInnerHits();
|
||||
|
||||
if (sourceInnerHits != null) {
|
||||
sourceInnerHits.forEach((name, searchHits) -> {
|
||||
innerHits.put(name, SearchDocumentResponse.from(searchHits, null, null));
|
||||
});
|
||||
}
|
||||
|
||||
NestedMetaData nestedMetaData = null;
|
||||
|
||||
if (source.getNestedIdentity() != null) {
|
||||
nestedMetaData = from(source.getNestedIdentity());
|
||||
}
|
||||
|
||||
BytesReference sourceRef = source.getSourceRef();
|
||||
|
||||
if (sourceRef == null || sourceRef.length() == 0) {
|
||||
return new SearchDocumentAdapter(source.getScore(), source.getSortValues(), source.getFields(), highlightFields,
|
||||
fromDocumentFields(source, source.getId(), source.getVersion(), source.getSeqNo(), source.getPrimaryTerm()));
|
||||
return new SearchDocumentAdapter(
|
||||
source.getScore(), source.getSortValues(), source.getFields(), highlightFields, fromDocumentFields(source,
|
||||
source.getIndex(), source.getId(), source.getVersion(), source.getSeqNo(), source.getPrimaryTerm()),
|
||||
innerHits, nestedMetaData);
|
||||
}
|
||||
|
||||
Document document = Document.from(source.getSourceAsMap());
|
||||
document.setIndex(source.getIndex());
|
||||
document.setId(source.getId());
|
||||
|
||||
if (source.getVersion() >= 0) {
|
||||
@@ -170,20 +192,33 @@ public class DocumentAdapters {
|
||||
document.setPrimaryTerm(source.getPrimaryTerm());
|
||||
|
||||
return new SearchDocumentAdapter(source.getScore(), source.getSortValues(), source.getFields(), highlightFields,
|
||||
document);
|
||||
document, innerHits, nestedMetaData);
|
||||
}
|
||||
|
||||
private static NestedMetaData from(SearchHit.NestedIdentity nestedIdentity) {
|
||||
|
||||
NestedMetaData child = null;
|
||||
|
||||
if (nestedIdentity.getChild() != null) {
|
||||
child = from(nestedIdentity.getChild());
|
||||
}
|
||||
|
||||
return NestedMetaData.of(nestedIdentity.getField().string(), nestedIdentity.getOffset(), child);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an unmodifiable {@link Document} from {@link Iterable} of {@link DocumentField}s.
|
||||
*
|
||||
* @param documentFields the {@link DocumentField}s backing the {@link Document}.
|
||||
* @param index
|
||||
* @return the adapted {@link Document}.
|
||||
*/
|
||||
public static Document fromDocumentFields(Iterable<DocumentField> documentFields, String id, long version, long seqNo,
|
||||
long primaryTerm) {
|
||||
public static Document fromDocumentFields(Iterable<DocumentField> documentFields, String index, String id,
|
||||
long version, long seqNo, long primaryTerm) {
|
||||
|
||||
if (documentFields instanceof Collection) {
|
||||
return new DocumentFieldAdapter((Collection<DocumentField>) documentFields, id, version, seqNo, primaryTerm);
|
||||
return new DocumentFieldAdapter((Collection<DocumentField>) documentFields, index, id, version, seqNo,
|
||||
primaryTerm);
|
||||
}
|
||||
|
||||
List<DocumentField> fields = new ArrayList<>();
|
||||
@@ -191,58 +226,49 @@ public class DocumentAdapters {
|
||||
fields.add(documentField);
|
||||
}
|
||||
|
||||
return new DocumentFieldAdapter(fields, id, version, seqNo, primaryTerm);
|
||||
return new DocumentFieldAdapter(fields, index, id, version, seqNo, primaryTerm);
|
||||
}
|
||||
|
||||
// TODO: Performance regarding keys/values/entry-set
|
||||
static class DocumentFieldAdapter implements Document {
|
||||
|
||||
private final Collection<DocumentField> documentFields;
|
||||
private final String index;
|
||||
private final String id;
|
||||
private final long version;
|
||||
private final long seqNo;
|
||||
private final long primaryTerm;
|
||||
|
||||
DocumentFieldAdapter(Collection<DocumentField> documentFields, String id, long version, long seqNo,
|
||||
DocumentFieldAdapter(Collection<DocumentField> documentFields, String index, String id, long version, long seqNo,
|
||||
long primaryTerm) {
|
||||
this.documentFields = documentFields;
|
||||
this.index = index;
|
||||
this.id = id;
|
||||
this.version = version;
|
||||
this.seqNo = seqNo;
|
||||
this.primaryTerm = primaryTerm;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.core.document.Document#hasId()
|
||||
*/
|
||||
@Override
|
||||
public String getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasId() {
|
||||
return StringUtils.hasLength(id);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.core.document.Document#getId()
|
||||
*/
|
||||
@Override
|
||||
public String getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.core.document.Document#hasVersion()
|
||||
*/
|
||||
@Override
|
||||
public boolean hasVersion() {
|
||||
return this.version >= 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.core.document.Document#getVersion()
|
||||
*/
|
||||
@Override
|
||||
public long getVersion() {
|
||||
|
||||
@@ -253,19 +279,11 @@ public class DocumentAdapters {
|
||||
return this.version;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.core.document.Document#hasSeqNo()
|
||||
*/
|
||||
@Override
|
||||
public boolean hasSeqNo() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.core.document.Document#getSeqNo()
|
||||
*/
|
||||
@Override
|
||||
public long getSeqNo() {
|
||||
|
||||
@@ -276,19 +294,11 @@ public class DocumentAdapters {
|
||||
return this.seqNo;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.core.document.Document#hasPrimaryTerm()
|
||||
*/
|
||||
@Override
|
||||
public boolean hasPrimaryTerm() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.core.document.Document#getPrimaryTerm()
|
||||
*/
|
||||
@Override
|
||||
public long getPrimaryTerm() {
|
||||
|
||||
@@ -299,28 +309,16 @@ public class DocumentAdapters {
|
||||
return this.primaryTerm;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.Map#size()
|
||||
*/
|
||||
@Override
|
||||
public int size() {
|
||||
return documentFields.size();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.Map#isEmpty()
|
||||
*/
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return documentFields.isEmpty();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.Map#containsKey(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean containsKey(Object key) {
|
||||
|
||||
@@ -333,10 +331,6 @@ public class DocumentAdapters {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.Map#containsValue(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean containsValue(Object value) {
|
||||
|
||||
@@ -351,10 +345,6 @@ public class DocumentAdapters {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.Map#get(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
public Object get(Object key) {
|
||||
@@ -365,74 +355,42 @@ public class DocumentAdapters {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.Map#put(java.lang.Object, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Object put(String key, Object value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.Map#remove(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Object remove(Object key) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.Map#putAll(Map)
|
||||
*/
|
||||
@Override
|
||||
public void putAll(Map<? extends String, ?> m) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.Map#clear()
|
||||
*/
|
||||
@Override
|
||||
public void clear() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.Map#keySet()
|
||||
*/
|
||||
@Override
|
||||
public Set<String> keySet() {
|
||||
return documentFields.stream().map(DocumentField::getName).collect(Collectors.toCollection(LinkedHashSet::new));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.Map#values()
|
||||
*/
|
||||
@Override
|
||||
public Collection<Object> values() {
|
||||
return documentFields.stream().map(DocumentFieldAdapter::getValue).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.Map#entrySet()
|
||||
*/
|
||||
@Override
|
||||
public Set<Entry<String, Object>> entrySet() {
|
||||
return documentFields.stream().collect(Collectors.toMap(DocumentField::getName, DocumentFieldAdapter::getValue))
|
||||
.entrySet();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.Map#forEach(java.util.function.BiConsumer)
|
||||
*/
|
||||
@Override
|
||||
public void forEach(BiConsumer<? super String, ? super Object> action) {
|
||||
|
||||
@@ -441,10 +399,6 @@ public class DocumentAdapters {
|
||||
documentFields.forEach(field -> action.accept(field.getName(), getValue(field)));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.core.document.Document#toJson()
|
||||
*/
|
||||
@Override
|
||||
public String toJson() {
|
||||
|
||||
@@ -472,10 +426,6 @@ public class DocumentAdapters {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getSimpleName() + '@' + this.id + '#' + this.version + ' ' + toJson();
|
||||
@@ -506,21 +456,22 @@ public class DocumentAdapters {
|
||||
private final Map<String, List<Object>> fields = new HashMap<>();
|
||||
private final Document delegate;
|
||||
private final Map<String, List<String>> highlightFields = new HashMap<>();
|
||||
private final Map<String, SearchDocumentResponse> innerHits = new HashMap<>();
|
||||
@Nullable private final NestedMetaData nestedMetaData;
|
||||
|
||||
SearchDocumentAdapter(float score, Object[] sortValues, Map<String, DocumentField> fields,
|
||||
Map<String, List<String>> highlightFields, Document delegate) {
|
||||
Map<String, List<String>> highlightFields, Document delegate, Map<String, SearchDocumentResponse> innerHits,
|
||||
@Nullable NestedMetaData nestedMetaData) {
|
||||
|
||||
this.score = score;
|
||||
this.sortValues = sortValues;
|
||||
this.delegate = delegate;
|
||||
fields.forEach((name, documentField) -> this.fields.put(name, documentField.getValues()));
|
||||
this.highlightFields.putAll(highlightFields);
|
||||
this.innerHits.putAll(innerHits);
|
||||
this.nestedMetaData = nestedMetaData;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.core.document.Document#append(java.lang.String, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public SearchDocument append(String key, Object value) {
|
||||
delegate.append(key, value);
|
||||
@@ -528,281 +479,173 @@ public class DocumentAdapters {
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.core.document.SearchDocument#getScore()
|
||||
*/
|
||||
@Override
|
||||
public float getScore() {
|
||||
return score;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.core.document.SearchDocument#getFields()
|
||||
*/
|
||||
@Override
|
||||
public Map<String, List<Object>> getFields() {
|
||||
return fields;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.core.document.SearchDocument#getSortValues()
|
||||
*/
|
||||
@Override
|
||||
public Object[] getSortValues() {
|
||||
return sortValues;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.core.document.SearchDocument#getHighlightFields()
|
||||
*/
|
||||
@Override
|
||||
public Map<String, List<String>> getHighlightFields() {
|
||||
return highlightFields;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.core.document.Document#hasId()
|
||||
*/
|
||||
@Override
|
||||
public String getIndex() {
|
||||
return delegate.getIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasId() {
|
||||
return delegate.hasId();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.core.document.Document#getId()
|
||||
*/
|
||||
@Override
|
||||
public String getId() {
|
||||
return delegate.getId();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.core.document.Document#setId(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void setId(String id) {
|
||||
delegate.setId(id);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.core.document.Document#hasVersion()
|
||||
*/
|
||||
@Override
|
||||
public boolean hasVersion() {
|
||||
return delegate.hasVersion();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.core.document.Document#getVersion()
|
||||
*/
|
||||
@Override
|
||||
public long getVersion() {
|
||||
return delegate.getVersion();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.core.document.Document#setVersion(long)
|
||||
*/
|
||||
@Override
|
||||
public void setVersion(long version) {
|
||||
delegate.setVersion(version);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.core.document.Document#hasSeqNo()
|
||||
*/
|
||||
@Override
|
||||
public boolean hasSeqNo() {
|
||||
return delegate.hasSeqNo();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.core.document.Document#getSeqNo()
|
||||
*/
|
||||
@Override
|
||||
public long getSeqNo() {
|
||||
return delegate.getSeqNo();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.core.document.Document#setSeqNo(long)
|
||||
*/
|
||||
@Override
|
||||
public void setSeqNo(long seqNo) {
|
||||
delegate.setSeqNo(seqNo);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.core.document.Document#hasPrimaryTerm()
|
||||
*/
|
||||
@Override
|
||||
public boolean hasPrimaryTerm() {
|
||||
return delegate.hasPrimaryTerm();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.core.document.Document#getPrimaryTerm()
|
||||
*/
|
||||
@Override
|
||||
public long getPrimaryTerm() {
|
||||
return delegate.getPrimaryTerm();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.core.document.Document#setPrimaryTerm(long)
|
||||
*/
|
||||
@Override
|
||||
public void setPrimaryTerm(long primaryTerm) {
|
||||
delegate.setPrimaryTerm(primaryTerm);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.core.document.Document#get(java.lang.Object, java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
public Map<String, SearchDocumentResponse> getInnerHits() {
|
||||
return innerHits;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public NestedMetaData getNestedMetaData() {
|
||||
return nestedMetaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public <T> T get(Object key, Class<T> type) {
|
||||
return delegate.get(key, type);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.core.document.Document#toJson()
|
||||
*/
|
||||
@Override
|
||||
public String toJson() {
|
||||
return delegate.toJson();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.Map#size()
|
||||
*/
|
||||
@Override
|
||||
public int size() {
|
||||
return delegate.size();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.Map#isEmpty()
|
||||
*/
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return delegate.isEmpty();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.Map#containsKey(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean containsKey(Object key) {
|
||||
return delegate.containsKey(key);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.Map#containsValue(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean containsValue(Object value) {
|
||||
return delegate.containsValue(value);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.Map#get(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Object get(Object key) {
|
||||
return delegate.get(key);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.Map#put(java.lang.Object, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Object put(String key, Object value) {
|
||||
return delegate.put(key, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.Map#remove(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Object remove(Object key) {
|
||||
return delegate.remove(key);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.Map#putAll(Map)
|
||||
*/
|
||||
@Override
|
||||
public void putAll(Map<? extends String, ?> m) {
|
||||
delegate.putAll(m);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.Map#clear()
|
||||
*/
|
||||
@Override
|
||||
public void clear() {
|
||||
delegate.clear();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.Map#keySet()
|
||||
*/
|
||||
@Override
|
||||
public Set<String> keySet() {
|
||||
return delegate.keySet();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.Map#values()
|
||||
*/
|
||||
@Override
|
||||
public Collection<Object> values() {
|
||||
return delegate.values();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.Map#entrySet()
|
||||
*/
|
||||
@Override
|
||||
public Set<Entry<String, Object>> entrySet() {
|
||||
return delegate.entrySet();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
@@ -815,37 +658,21 @@ public class DocumentAdapters {
|
||||
return Float.compare(that.score, score) == 0 && delegate.equals(that.delegate);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return delegate.hashCode();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.Map#forEach(java.util.function.BiConsumer)
|
||||
*/
|
||||
@Override
|
||||
public void forEach(BiConsumer<? super String, ? super Object> action) {
|
||||
delegate.forEach(action);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.Map#remove(java.lang.Object, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean remove(Object key, Object value) {
|
||||
return delegate.remove(key, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ class MapDocument implements Document {
|
||||
|
||||
private final LinkedHashMap<String, Object> documentAsMap;
|
||||
|
||||
private @Nullable String index;
|
||||
private @Nullable String id;
|
||||
private @Nullable Long version;
|
||||
private @Nullable Long seqNo;
|
||||
@@ -53,6 +54,17 @@ class MapDocument implements Document {
|
||||
this.documentAsMap = new LinkedHashMap<>(documentAsMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIndex(@Nullable String index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.core.document.Document#hasId()
|
||||
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2020 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.document;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* meta data returned for nested inner hits.
|
||||
*
|
||||
* @author Peter-Josef Meisch
|
||||
*/
|
||||
public class NestedMetaData {
|
||||
|
||||
private final String field;
|
||||
private final int offset;
|
||||
@Nullable private final NestedMetaData child;
|
||||
|
||||
public static NestedMetaData of(String field, int offset, @Nullable NestedMetaData nested) {
|
||||
return new NestedMetaData(field, offset, nested);
|
||||
}
|
||||
|
||||
private NestedMetaData(String field, int offset, @Nullable NestedMetaData child) {
|
||||
this.field = field;
|
||||
this.offset = offset;
|
||||
this.child = child;
|
||||
}
|
||||
|
||||
public String getField() {
|
||||
return field;
|
||||
}
|
||||
|
||||
public int getOffset() {
|
||||
return offset;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public NestedMetaData getChild() {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
+20
-1
@@ -69,5 +69,24 @@ public interface SearchDocument extends Document {
|
||||
*/
|
||||
@Nullable
|
||||
default Map<String, List<String>> getHighlightFields() {
|
||||
return null;}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the innerHits for the SearchHit
|
||||
* @since 4.1
|
||||
*/
|
||||
@Nullable
|
||||
default Map<String, SearchDocumentResponse> getInnerHits() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the nested metadata in case this is a nested inner hit.
|
||||
* @since 4.1
|
||||
*/
|
||||
@Nullable
|
||||
default NestedMetaData getNestedMetaData() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
+29
-9
@@ -22,7 +22,9 @@ import java.util.stream.StreamSupport;
|
||||
|
||||
import org.apache.lucene.search.TotalHits;
|
||||
import org.elasticsearch.action.search.SearchResponse;
|
||||
import org.elasticsearch.search.SearchHits;
|
||||
import org.elasticsearch.search.aggregations.Aggregations;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -42,7 +44,7 @@ public class SearchDocumentResponse {
|
||||
private final Aggregations aggregations;
|
||||
|
||||
private SearchDocumentResponse(long totalHits, String totalHitsRelation, float maxScore, String scrollId,
|
||||
List<SearchDocument> searchDocuments, Aggregations aggregations) {
|
||||
List<SearchDocument> searchDocuments, Aggregations aggregations) {
|
||||
this.totalHits = totalHits;
|
||||
this.totalHitsRelation = totalHitsRelation;
|
||||
this.maxScore = maxScore;
|
||||
@@ -78,27 +80,45 @@ public class SearchDocumentResponse {
|
||||
/**
|
||||
* creates a SearchDocumentResponse from the {@link SearchResponse}
|
||||
*
|
||||
* @param searchResponse
|
||||
* must not be {@literal null}
|
||||
* @param searchResponse must not be {@literal null}
|
||||
* @return the SearchDocumentResponse
|
||||
*/
|
||||
public static SearchDocumentResponse from(SearchResponse searchResponse) {
|
||||
|
||||
Assert.notNull(searchResponse, "searchResponse must not be null");
|
||||
|
||||
TotalHits responseTotalHits = searchResponse.getHits().getTotalHits();
|
||||
Aggregations aggregations = searchResponse.getAggregations();
|
||||
String scrollId = searchResponse.getScrollId();
|
||||
|
||||
SearchHits searchHits = searchResponse.getHits();
|
||||
|
||||
SearchDocumentResponse searchDocumentResponse = from(searchHits, scrollId, aggregations);
|
||||
return searchDocumentResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
* creates a {@link SearchDocumentResponse} from {@link SearchHits} with the given scrollId and aggregations
|
||||
*
|
||||
* @param searchHits the {@link SearchHits} to process
|
||||
* @param scrollId scrollId
|
||||
* @param aggregations aggregations
|
||||
* @return the {@link SearchDocumentResponse}
|
||||
* @since 4.1
|
||||
*/
|
||||
public static SearchDocumentResponse from(SearchHits searchHits, @Nullable String scrollId,
|
||||
@Nullable Aggregations aggregations) {
|
||||
TotalHits responseTotalHits = searchHits.getTotalHits();
|
||||
long totalHits = responseTotalHits.value;
|
||||
String totalHitsRelation = responseTotalHits.relation.name();
|
||||
|
||||
float maxScore = searchResponse.getHits().getMaxScore();
|
||||
String scrollId = searchResponse.getScrollId();
|
||||
float maxScore = searchHits.getMaxScore();
|
||||
|
||||
List<SearchDocument> searchDocuments = StreamSupport.stream(searchResponse.getHits().spliterator(), false) //
|
||||
List<SearchDocument> searchDocuments = StreamSupport.stream(searchHits.spliterator(), false) //
|
||||
.filter(Objects::nonNull) //
|
||||
.map(DocumentAdapters::from) //
|
||||
.collect(Collectors.toList());
|
||||
|
||||
Aggregations aggregations = searchResponse.getAggregations();
|
||||
|
||||
return new SearchDocumentResponse(totalHits, totalHitsRelation, maxScore, scrollId, searchDocuments, aggregations);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+10
@@ -17,6 +17,7 @@ package org.springframework.data.elasticsearch.core.mapping;
|
||||
|
||||
import org.elasticsearch.index.VersionType;
|
||||
import org.springframework.data.elasticsearch.annotations.Field;
|
||||
import org.springframework.data.elasticsearch.core.document.Document;
|
||||
import org.springframework.data.elasticsearch.core.query.SeqNoPrimaryTerm;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.lang.Nullable;
|
||||
@@ -58,6 +59,7 @@ public interface ElasticsearchPersistentEntity<T> extends PersistentEntity<T, El
|
||||
@Nullable
|
||||
ElasticsearchPersistentProperty getParentIdProperty();
|
||||
|
||||
@Nullable
|
||||
String settingPath();
|
||||
|
||||
@Nullable
|
||||
@@ -136,4 +138,12 @@ public interface ElasticsearchPersistentEntity<T> extends PersistentEntity<T, El
|
||||
String.format("Required SeqNoPrimaryTerm property not found for %s!", this.getType()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the default settings for an index.
|
||||
*
|
||||
* @return settings as {@link Document}
|
||||
* @since 4.1
|
||||
*/
|
||||
Document getDefaultSettings();
|
||||
}
|
||||
|
||||
+3
-30
@@ -17,7 +17,6 @@ package org.springframework.data.elasticsearch.core.mapping;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -34,29 +33,15 @@ public class IndexCoordinates {
|
||||
public static final String TYPE = "_doc";
|
||||
|
||||
private final String[] indexNames;
|
||||
private final String[] typeNames;
|
||||
|
||||
public static IndexCoordinates of(String... indexNames) {
|
||||
Assert.notNull(indexNames, "indexNames must not be null");
|
||||
return new IndexCoordinates(indexNames, null);
|
||||
return new IndexCoordinates(indexNames);
|
||||
}
|
||||
|
||||
private IndexCoordinates(String[] indexNames, @Nullable String[] typeNames) {
|
||||
private IndexCoordinates(String[] indexNames) {
|
||||
Assert.notEmpty(indexNames, "indexNames may not be null or empty");
|
||||
this.indexNames = indexNames;
|
||||
this.typeNames = typeNames != null ? typeNames : new String[] {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Using Index types is deprecated in Elasticsearch.
|
||||
*
|
||||
* @param typeNames
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
public IndexCoordinates withTypes(String... typeNames) {
|
||||
Assert.notEmpty(typeNames, "typeNames must not be null");
|
||||
return new IndexCoordinates(this.indexNames, typeNames);
|
||||
}
|
||||
|
||||
public String getIndexName() {
|
||||
@@ -67,20 +52,8 @@ public class IndexCoordinates {
|
||||
return Arrays.copyOf(indexNames, indexNames.length);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Nullable
|
||||
public String getTypeName() {
|
||||
return typeNames.length > 0 ? typeNames[0] : null;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public String[] getTypeNames() {
|
||||
return Arrays.copyOf(typeNames, typeNames.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "IndexCoordinates{" + "indexNames=" + Arrays.toString(indexNames) + ", typeNames="
|
||||
+ Arrays.toString(typeNames) + '}';
|
||||
return "IndexCoordinates{" + "indexNames=" + Arrays.toString(indexNames) + '}';
|
||||
}
|
||||
}
|
||||
|
||||
+3
-19
@@ -15,14 +15,10 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.core.mapping;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.data.mapping.context.AbstractMappingContext;
|
||||
import org.springframework.data.mapping.model.Property;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* SimpleElasticsearchMappingContext
|
||||
@@ -30,21 +26,14 @@ import org.springframework.lang.Nullable;
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
* @author Mark Paluch
|
||||
* @author Peter-Josef Meisch
|
||||
*/
|
||||
public class SimpleElasticsearchMappingContext
|
||||
extends AbstractMappingContext<SimpleElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty>
|
||||
implements ApplicationContextAware {
|
||||
|
||||
private @Nullable ApplicationContext context;
|
||||
extends AbstractMappingContext<SimpleElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> {
|
||||
|
||||
@Override
|
||||
protected <T> SimpleElasticsearchPersistentEntity<?> createPersistentEntity(TypeInformation<T> typeInformation) {
|
||||
SimpleElasticsearchPersistentEntity<T> persistentEntity = new SimpleElasticsearchPersistentEntity<>(
|
||||
typeInformation);
|
||||
if (context != null) {
|
||||
persistentEntity.setApplicationContext(context);
|
||||
}
|
||||
return persistentEntity;
|
||||
return new SimpleElasticsearchPersistentEntity<>(typeInformation);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -52,9 +41,4 @@ public class SimpleElasticsearchMappingContext
|
||||
SimpleElasticsearchPersistentEntity<?> owner, SimpleTypeHolder simpleTypeHolder) {
|
||||
return new SimpleElasticsearchPersistentProperty(property, owner, simpleTypeHolder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext context) throws BeansException {
|
||||
this.context = context;
|
||||
}
|
||||
}
|
||||
|
||||
+70
-45
@@ -15,33 +15,27 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.core.mapping;
|
||||
|
||||
import static org.springframework.util.StringUtils.*;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.elasticsearch.common.collect.MapBuilder;
|
||||
import org.elasticsearch.index.VersionType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.expression.BeanFactoryAccessor;
|
||||
import org.springframework.context.expression.BeanFactoryResolver;
|
||||
import org.springframework.data.elasticsearch.annotations.Document;
|
||||
import org.springframework.data.elasticsearch.annotations.Parent;
|
||||
import org.springframework.data.elasticsearch.annotations.Setting;
|
||||
import org.springframework.data.elasticsearch.core.document.Document;
|
||||
import org.springframework.data.mapping.MappingException;
|
||||
import org.springframework.data.mapping.PropertyHandler;
|
||||
import org.springframework.data.mapping.model.BasicPersistentEntity;
|
||||
import org.springframework.data.mapping.model.PersistentPropertyAccessorFactory;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ParserContext;
|
||||
import org.springframework.expression.common.LiteralExpression;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -58,15 +52,12 @@ import org.springframework.util.Assert;
|
||||
* @author Roman Puchkovskiy
|
||||
*/
|
||||
public class SimpleElasticsearchPersistentEntity<T> extends BasicPersistentEntity<T, ElasticsearchPersistentProperty>
|
||||
implements ElasticsearchPersistentEntity<T>, ApplicationContextAware {
|
||||
implements ElasticsearchPersistentEntity<T> {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(SimpleElasticsearchPersistentEntity.class);
|
||||
|
||||
private final StandardEvaluationContext context;
|
||||
private final SpelExpressionParser parser;
|
||||
private static final SpelExpressionParser PARSER = new SpelExpressionParser();
|
||||
|
||||
private @Nullable String indexName;
|
||||
private @Nullable String indexType;
|
||||
private boolean useServerConfiguration;
|
||||
private short shards;
|
||||
private short replicas;
|
||||
@@ -80,20 +71,19 @@ public class SimpleElasticsearchPersistentEntity<T> extends BasicPersistentEntit
|
||||
private @Nullable VersionType versionType;
|
||||
private boolean createIndexAndMapping;
|
||||
private final Map<String, ElasticsearchPersistentProperty> fieldNamePropertyCache = new ConcurrentHashMap<>();
|
||||
private final ConcurrentHashMap<String, Expression> indexNameExpressions = new ConcurrentHashMap<>();
|
||||
|
||||
public SimpleElasticsearchPersistentEntity(TypeInformation<T> typeInformation) {
|
||||
|
||||
super(typeInformation);
|
||||
this.context = new StandardEvaluationContext();
|
||||
this.parser = new SpelExpressionParser();
|
||||
|
||||
Class<T> clazz = typeInformation.getType();
|
||||
if (clazz.isAnnotationPresent(Document.class)) {
|
||||
Document document = clazz.getAnnotation(Document.class);
|
||||
if (clazz.isAnnotationPresent(org.springframework.data.elasticsearch.annotations.Document.class)) {
|
||||
org.springframework.data.elasticsearch.annotations.Document document = clazz
|
||||
.getAnnotation(org.springframework.data.elasticsearch.annotations.Document.class);
|
||||
Assert.hasText(document.indexName(),
|
||||
" Unknown indexName. Make sure the indexName is defined. e.g @Document(indexName=\"foo\")");
|
||||
this.indexName = document.indexName();
|
||||
this.indexType = hasText(document.type()) ? document.type() : clazz.getSimpleName().toLowerCase(Locale.ENGLISH);
|
||||
this.useServerConfiguration = document.useServerConfiguration();
|
||||
this.shards = document.shards();
|
||||
this.replicas = document.replicas();
|
||||
@@ -107,36 +97,13 @@ public class SimpleElasticsearchPersistentEntity<T> extends BasicPersistentEntit
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
context.addPropertyAccessor(new BeanFactoryAccessor());
|
||||
context.setBeanResolver(new BeanFactoryResolver(applicationContext));
|
||||
context.setRootObject(applicationContext);
|
||||
}
|
||||
|
||||
private String getIndexName() {
|
||||
|
||||
if (indexName != null) {
|
||||
Expression expression = parser.parseExpression(indexName, ParserContext.TEMPLATE_EXPRESSION);
|
||||
return expression.getValue(context, String.class);
|
||||
}
|
||||
|
||||
return getTypeInformation().getType().getSimpleName();
|
||||
}
|
||||
|
||||
private String getIndexType() {
|
||||
|
||||
if (indexType != null) {
|
||||
Expression expression = parser.parseExpression(indexType, ParserContext.TEMPLATE_EXPRESSION);
|
||||
return expression.getValue(context, String.class);
|
||||
}
|
||||
|
||||
return "";
|
||||
return indexName != null ? indexName : getTypeInformation().getType().getSimpleName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IndexCoordinates getIndexCoordinates() {
|
||||
return IndexCoordinates.of(getIndexName()).withTypes(getIndexType());
|
||||
return resolve(IndexCoordinates.of(getIndexName()));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -309,4 +276,62 @@ public class SimpleElasticsearchPersistentEntity<T> extends BasicPersistentEntit
|
||||
public ElasticsearchPersistentProperty getSeqNoPrimaryTermProperty() {
|
||||
return seqNoPrimaryTermProperty;
|
||||
}
|
||||
|
||||
// region SpEL handling
|
||||
/**
|
||||
* resolves all the names in the IndexCoordinates object. If a name cannot be resolved, the original name is returned.
|
||||
*
|
||||
* @param indexCoordinates IndexCoordinates with names to resolve
|
||||
* @return IndexCoordinates with resolved names
|
||||
*/
|
||||
private IndexCoordinates resolve(IndexCoordinates indexCoordinates) {
|
||||
|
||||
EvaluationContext context = getEvaluationContext(null);
|
||||
|
||||
String[] indexNames = indexCoordinates.getIndexNames();
|
||||
String[] resolvedNames = new String[indexNames.length];
|
||||
|
||||
for (int i = 0; i < indexNames.length; i++) {
|
||||
String indexName = indexNames[i];
|
||||
resolvedNames[i] = resolve(context, indexName);
|
||||
}
|
||||
|
||||
return IndexCoordinates.of(resolvedNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* tries to resolve the given name. If this is not successful, the original value is returned
|
||||
*
|
||||
* @param context SpEL evaluation context
|
||||
* @param name name to resolve
|
||||
* @return the resolved name or the input name if it cannot be resolved
|
||||
*/
|
||||
private String resolve(EvaluationContext context, String name) {
|
||||
|
||||
Assert.notNull(name, "name must not be null");
|
||||
|
||||
Expression expression = indexNameExpressions.computeIfAbsent(name, s -> {
|
||||
Expression expr = PARSER.parseExpression(name, ParserContext.TEMPLATE_EXPRESSION);
|
||||
return expr instanceof LiteralExpression ? null : expr;
|
||||
});
|
||||
|
||||
String resolvedName = expression != null ? expression.getValue(context, String.class) : null;
|
||||
return resolvedName != null ? resolvedName : name;
|
||||
}
|
||||
// endregion
|
||||
|
||||
@Override
|
||||
public Document getDefaultSettings() {
|
||||
|
||||
if (isUseServerConfiguration()) {
|
||||
return Document.create();
|
||||
}
|
||||
|
||||
Map<String, String> map = new MapBuilder<String, String>()
|
||||
.put("index.number_of_shards", String.valueOf(getShards()))
|
||||
.put("index.number_of_replicas", String.valueOf(getReplicas()))
|
||||
.put("index.refresh_interval", getRefreshInterval()).put("index.store.type", getIndexStoreType()).map();
|
||||
return Document.from(map);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+14
@@ -20,6 +20,9 @@ import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.elasticsearch.annotations.DateFormat;
|
||||
import org.springframework.data.elasticsearch.annotations.Field;
|
||||
import org.springframework.data.elasticsearch.annotations.FieldType;
|
||||
@@ -50,6 +53,8 @@ import org.springframework.util.StringUtils;
|
||||
public class SimpleElasticsearchPersistentProperty extends
|
||||
AnnotationBasedPersistentProperty<ElasticsearchPersistentProperty> implements ElasticsearchPersistentProperty {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(SimpleElasticsearchPersistentProperty.class);
|
||||
|
||||
private static final List<String> SUPPORTED_ID_PROPERTY_NAMES = Arrays.asList("id", "document");
|
||||
|
||||
private final boolean isScore;
|
||||
@@ -66,6 +71,15 @@ public class SimpleElasticsearchPersistentProperty extends
|
||||
|
||||
this.annotatedFieldName = getAnnotatedFieldName();
|
||||
this.isId = super.isIdProperty() || SUPPORTED_ID_PROPERTY_NAMES.contains(getFieldName());
|
||||
|
||||
// deprecated since 4.1
|
||||
@Deprecated
|
||||
boolean isIdWithoutAnnotation = isId && !isAnnotationPresent(Id.class);
|
||||
if (isIdWithoutAnnotation) {
|
||||
LOGGER.warn("Using the property name of '{}' to identify the id property is deprecated."
|
||||
+ " Please annotate the id property with '@Id'", getName());
|
||||
}
|
||||
|
||||
this.isScore = isAnnotationPresent(Score.class);
|
||||
this.isParent = isAnnotationPresent(Parent.class);
|
||||
this.isSeqNoPrimaryTerm = SeqNoPrimaryTerm.class.isAssignableFrom(getRawType());
|
||||
|
||||
+1
-2
@@ -90,8 +90,7 @@ abstract class AbstractReactiveElasticsearchRepositoryQuery implements Repositor
|
||||
|
||||
Class<?> targetType = processor.getReturnedType().getTypeToRead();
|
||||
String indexName = queryMethod.getEntityInformation().getIndexName();
|
||||
String indexTypeName = queryMethod.getEntityInformation().getIndexTypeName();
|
||||
IndexCoordinates index = IndexCoordinates.of(indexName).withTypes(indexTypeName);
|
||||
IndexCoordinates index = IndexCoordinates.of(indexName);
|
||||
|
||||
ReactiveElasticsearchQueryExecution execution = getExecution(parameterAccessor,
|
||||
new ResultProcessingConverter(processor));
|
||||
|
||||
+5
-361
@@ -15,43 +15,7 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.repository.support;
|
||||
|
||||
import static org.elasticsearch.index.query.QueryBuilders.*;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.elasticsearch.index.query.IdsQueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
||||
import org.springframework.data.elasticsearch.core.IndexOperations;
|
||||
import org.springframework.data.elasticsearch.core.SearchHit;
|
||||
import org.springframework.data.elasticsearch.core.SearchHitSupport;
|
||||
import org.springframework.data.elasticsearch.core.SearchHits;
|
||||
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
|
||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
import org.springframework.data.elasticsearch.core.query.MoreLikeThisQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
|
||||
import org.springframework.data.elasticsearch.core.query.Query;
|
||||
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
|
||||
import org.springframework.data.util.Streamable;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Elasticsearch specific repository implementation. Likely to be used as target within
|
||||
@@ -60,335 +24,15 @@ import org.springframework.util.Assert;
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
* @author Ryan Henszey
|
||||
* @author Kevin Leturc
|
||||
* @author Mark Paluch
|
||||
* @author Christoph Strobl
|
||||
* @author Michael Wirth
|
||||
* @author Sascha Woo
|
||||
* @author Murali Chevuri
|
||||
* @author Peter-Josef Meisch
|
||||
* @author Aleksei Arsenev
|
||||
* @deprecated since 4.1, derive from {@link SimpleElasticsearchRepository} instead
|
||||
*/
|
||||
public abstract class AbstractElasticsearchRepository<T, ID> implements ElasticsearchRepository<T, ID> {
|
||||
|
||||
static final Logger LOGGER = LoggerFactory.getLogger(AbstractElasticsearchRepository.class);
|
||||
|
||||
protected ElasticsearchOperations operations;
|
||||
protected IndexOperations indexOperations;
|
||||
|
||||
protected Class<T> entityClass;
|
||||
protected @Nullable ElasticsearchEntityInformation<T, ID> entityInformation;
|
||||
@Deprecated
|
||||
public abstract class AbstractElasticsearchRepository<T, ID> extends SimpleElasticsearchRepository<T, ID> {
|
||||
|
||||
public AbstractElasticsearchRepository(ElasticsearchEntityInformation<T, ID> metadata,
|
||||
ElasticsearchOperations operations) {
|
||||
this.operations = operations;
|
||||
|
||||
Assert.notNull(metadata, "ElasticsearchEntityInformation must not be null!");
|
||||
|
||||
this.entityInformation = metadata;
|
||||
this.entityClass = this.entityInformation.getJavaType();
|
||||
this.indexOperations = operations.indexOps(this.entityClass);
|
||||
try {
|
||||
if (createIndexAndMapping() && !indexOperations.exists()) {
|
||||
createIndex();
|
||||
putMapping();
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
LOGGER.warn("Cannot create index: {}", exception.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void createIndex() {
|
||||
indexOperations.create();
|
||||
}
|
||||
|
||||
private void putMapping() {
|
||||
indexOperations.putMapping(indexOperations.createMapping(entityClass));
|
||||
}
|
||||
|
||||
private boolean createIndexAndMapping() {
|
||||
|
||||
final ElasticsearchPersistentEntity<?> entity = operations.getElasticsearchConverter().getMappingContext()
|
||||
.getRequiredPersistentEntity(getEntityClass());
|
||||
return entity.isCreateIndexAndMapping();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<T> findById(ID id) {
|
||||
return Optional.ofNullable(operations.get(stringIdRepresentation(id), getEntityClass(), getIndexCoordinates()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<T> findAll() {
|
||||
int itemCount = (int) this.count();
|
||||
|
||||
if (itemCount == 0) {
|
||||
return new PageImpl<>(Collections.emptyList());
|
||||
}
|
||||
return this.findAll(PageRequest.of(0, Math.max(1, itemCount)));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Page<T> findAll(Pageable pageable) {
|
||||
NativeSearchQuery query = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).withPageable(pageable).build();
|
||||
SearchHits<T> searchHits = operations.search(query, getEntityClass(), getIndexCoordinates());
|
||||
AggregatedPage<SearchHit<T>> page = SearchHitSupport.page(searchHits, query.getPageable());
|
||||
return (Page<T>) SearchHitSupport.unwrapSearchHits(page);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Iterable<T> findAll(Sort sort) {
|
||||
int itemCount = (int) this.count();
|
||||
|
||||
if (itemCount == 0) {
|
||||
return new PageImpl<>(Collections.emptyList());
|
||||
}
|
||||
NativeSearchQuery query = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
|
||||
.withPageable(PageRequest.of(0, itemCount, sort)).build();
|
||||
List<SearchHit<T>> searchHitList = operations.search(query, getEntityClass(), getIndexCoordinates())
|
||||
.getSearchHits();
|
||||
return (List<T>) SearchHitSupport.unwrapSearchHits(searchHitList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<T> findAllById(Iterable<ID> ids) {
|
||||
|
||||
Assert.notNull(ids, "ids can't be null.");
|
||||
|
||||
NativeSearchQuery query = new NativeSearchQueryBuilder().withIds(stringIdsRepresentation(ids)).build();
|
||||
List<T> result = new ArrayList<>();
|
||||
List<T> multiGetEntities = operations.multiGet(query, getEntityClass(), getIndexCoordinates());
|
||||
|
||||
multiGetEntities.forEach(entity -> {
|
||||
|
||||
if (entity != null) {
|
||||
result.add(entity);
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long count() {
|
||||
NativeSearchQuery query = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build();
|
||||
return operations.count(query, getEntityClass(), getIndexCoordinates());
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S extends T> S save(S entity) {
|
||||
|
||||
Assert.notNull(entity, "Cannot save 'null' entity.");
|
||||
|
||||
operations.save(entity, getIndexCoordinates());
|
||||
operations.indexOps(entity.getClass()).refresh();
|
||||
return entity;
|
||||
}
|
||||
|
||||
public <S extends T> List<S> save(List<S> entities) {
|
||||
|
||||
Assert.notNull(entities, "Cannot insert 'null' as a List.");
|
||||
|
||||
return Streamable.of(saveAll(entities)).stream().collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public <S extends T> S indexWithoutRefresh(S entity) {
|
||||
Assert.notNull(entity, "Cannot save 'null' entity.");
|
||||
operations.save(entity);
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S extends T> Iterable<S> saveAll(Iterable<S> entities) {
|
||||
|
||||
Assert.notNull(entities, "Cannot insert 'null' as a List.");
|
||||
|
||||
IndexCoordinates indexCoordinates = getIndexCoordinates();
|
||||
operations.save(entities, indexCoordinates);
|
||||
operations.indexOps(indexCoordinates).refresh();
|
||||
|
||||
return entities;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean existsById(ID id) {
|
||||
return operations.exists(stringIdRepresentation(id), getIndexCoordinates());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Iterable<T> search(QueryBuilder query) {
|
||||
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(query).build();
|
||||
int count = (int) operations.count(searchQuery, getEntityClass(), getIndexCoordinates());
|
||||
|
||||
if (count == 0) {
|
||||
return new PageImpl<>(Collections.emptyList());
|
||||
}
|
||||
searchQuery.setPageable(PageRequest.of(0, count));
|
||||
SearchHits<T> searchHits = operations.search(searchQuery, getEntityClass(), getIndexCoordinates());
|
||||
AggregatedPage<SearchHit<T>> page = SearchHitSupport.page(searchHits, searchQuery.getPageable());
|
||||
return (Page<T>) SearchHitSupport.unwrapSearchHits(page);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Page<T> search(QueryBuilder query, Pageable pageable) {
|
||||
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(query).withPageable(pageable).build();
|
||||
SearchHits<T> searchHits = operations.search(searchQuery, getEntityClass(), getIndexCoordinates());
|
||||
AggregatedPage<SearchHit<T>> page = SearchHitSupport.page(searchHits, searchQuery.getPageable());
|
||||
return (Page<T>) SearchHitSupport.unwrapSearchHits(page);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Page<T> search(Query query) {
|
||||
SearchHits<T> searchHits = operations.search(query, getEntityClass(), getIndexCoordinates());
|
||||
AggregatedPage<SearchHit<T>> page = SearchHitSupport.page(searchHits, query.getPageable());
|
||||
return (Page<T>) SearchHitSupport.unwrapSearchHits(page);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Page<T> searchSimilar(T entity, @Nullable String[] fields, Pageable pageable) {
|
||||
|
||||
Assert.notNull(entity, "Cannot search similar records for 'null'.");
|
||||
Assert.notNull(pageable, "'pageable' cannot be 'null'");
|
||||
|
||||
MoreLikeThisQuery query = new MoreLikeThisQuery();
|
||||
query.setId(stringIdRepresentation(extractIdFromBean(entity)));
|
||||
query.setPageable(pageable);
|
||||
|
||||
if (fields != null) {
|
||||
query.addFields(fields);
|
||||
}
|
||||
|
||||
SearchHits<T> searchHits = operations.search(query, getEntityClass(), getIndexCoordinates());
|
||||
AggregatedPage<SearchHit<T>> page = SearchHitSupport.page(searchHits, pageable);
|
||||
return (Page<T>) SearchHitSupport.unwrapSearchHits(page);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteById(ID id) {
|
||||
|
||||
Assert.notNull(id, "Cannot delete entity with id 'null'.");
|
||||
|
||||
IndexCoordinates indexCoordinates = getIndexCoordinates();
|
||||
doDelete(id, indexCoordinates);
|
||||
indexOperations.refresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(T entity) {
|
||||
|
||||
Assert.notNull(entity, "Cannot delete 'null' entity.");
|
||||
|
||||
IndexCoordinates indexCoordinates = getIndexCoordinates();
|
||||
doDelete(extractIdFromBean(entity), indexCoordinates);
|
||||
indexOperations.refresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteAll(Iterable<? extends T> entities) {
|
||||
|
||||
Assert.notNull(entities, "Cannot delete 'null' list.");
|
||||
|
||||
IndexCoordinates indexCoordinates = getIndexCoordinates();
|
||||
IdsQueryBuilder idsQueryBuilder = idsQuery();
|
||||
for (T entity : entities) {
|
||||
ID id = extractIdFromBean(entity);
|
||||
if (id != null) {
|
||||
idsQueryBuilder.addIds(stringIdRepresentation(id));
|
||||
}
|
||||
}
|
||||
|
||||
if (idsQueryBuilder.ids().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Query query = new NativeSearchQueryBuilder().withQuery(idsQueryBuilder).build();
|
||||
|
||||
operations.delete(query, getEntityClass(), indexCoordinates);
|
||||
indexOperations.refresh();
|
||||
}
|
||||
|
||||
private void doDelete(@Nullable ID id, IndexCoordinates indexCoordinates) {
|
||||
if (id != null) {
|
||||
operations.delete(stringIdRepresentation(id), indexCoordinates);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteAll() {
|
||||
IndexCoordinates indexCoordinates = getIndexCoordinates();
|
||||
Query query = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build();
|
||||
|
||||
operations.delete(query, getEntityClass(), indexCoordinates);
|
||||
indexOperations.refresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh() {
|
||||
indexOperations.refresh();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Class<T> resolveReturnedClassFromGenericType() {
|
||||
ParameterizedType parameterizedType = resolveReturnedClassFromGenericType(getClass());
|
||||
return (Class<T>) parameterizedType.getActualTypeArguments()[0];
|
||||
}
|
||||
|
||||
private ParameterizedType resolveReturnedClassFromGenericType(Class<?> clazz) {
|
||||
Object genericSuperclass = clazz.getGenericSuperclass();
|
||||
|
||||
if (genericSuperclass instanceof ParameterizedType) {
|
||||
ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
|
||||
Type rawtype = parameterizedType.getRawType();
|
||||
if (SimpleElasticsearchRepository.class.equals(rawtype)) {
|
||||
return parameterizedType;
|
||||
}
|
||||
}
|
||||
|
||||
return resolveReturnedClassFromGenericType(clazz.getSuperclass());
|
||||
}
|
||||
|
||||
protected Class<T> getEntityClass() {
|
||||
|
||||
if (!isEntityClassSet()) {
|
||||
try {
|
||||
this.entityClass = resolveReturnedClassFromGenericType();
|
||||
} catch (Exception e) {
|
||||
throw new InvalidDataAccessApiUsageException("Unable to resolve EntityClass. Please use according setter!", e);
|
||||
}
|
||||
}
|
||||
return entityClass;
|
||||
}
|
||||
|
||||
private boolean isEntityClassSet() {
|
||||
return entityClass != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected ID extractIdFromBean(T entity) {
|
||||
return entityInformation.getId(entity);
|
||||
}
|
||||
|
||||
private List<String> stringIdsRepresentation(Iterable<ID> ids) {
|
||||
Assert.notNull(ids, "ids can't be null.");
|
||||
List<String> stringIds = new ArrayList<>();
|
||||
for (ID id : ids) {
|
||||
stringIds.add(stringIdRepresentation(id));
|
||||
}
|
||||
|
||||
return stringIds;
|
||||
}
|
||||
|
||||
protected abstract @Nullable String stringIdRepresentation(@Nullable ID id);
|
||||
|
||||
private IndexCoordinates getIndexCoordinates() {
|
||||
return operations.getIndexCoordinatesFor(getEntityClass());
|
||||
ElasticsearchOperations elasticsearchOperations) {
|
||||
super(metadata, elasticsearchOperations);
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -39,6 +39,7 @@ public interface ElasticsearchEntityInformation<T, ID> extends EntityInformation
|
||||
@Nullable
|
||||
Long getVersion(T entity);
|
||||
|
||||
@Nullable
|
||||
VersionType getVersionType();
|
||||
|
||||
@Nullable
|
||||
|
||||
+13
-23
@@ -16,9 +16,9 @@
|
||||
package org.springframework.data.elasticsearch.repository.support;
|
||||
|
||||
import org.elasticsearch.index.VersionType;
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
|
||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
import org.springframework.data.repository.core.support.PersistentEntityInformation;
|
||||
|
||||
/**
|
||||
@@ -35,44 +35,34 @@ import org.springframework.data.repository.core.support.PersistentEntityInformat
|
||||
* @author Christoph Strobl
|
||||
* @author Ivan Greene
|
||||
* @author Sylvain Laurent
|
||||
* @author Peter-Josef Meisch
|
||||
*/
|
||||
public class MappingElasticsearchEntityInformation<T, ID> extends PersistentEntityInformation<T, ID>
|
||||
implements ElasticsearchEntityInformation<T, ID> {
|
||||
|
||||
private final ElasticsearchPersistentEntity<T> entityMetadata;
|
||||
private final IndexCoordinates indexCoordinates;
|
||||
private final VersionType versionType;
|
||||
private final ElasticsearchPersistentEntity<T> persistentEntity;
|
||||
|
||||
public MappingElasticsearchEntityInformation(ElasticsearchPersistentEntity<T> entity) {
|
||||
this(entity, entity.getIndexCoordinates(), entity.getVersionType());
|
||||
}
|
||||
|
||||
public MappingElasticsearchEntityInformation(ElasticsearchPersistentEntity<T> entity,
|
||||
IndexCoordinates indexCoordinates, VersionType versionType) {
|
||||
super(entity);
|
||||
|
||||
this.entityMetadata = entity;
|
||||
this.indexCoordinates = indexCoordinates;
|
||||
this.versionType = versionType;
|
||||
public MappingElasticsearchEntityInformation(ElasticsearchPersistentEntity<T> persistentEntity) {
|
||||
super(persistentEntity);
|
||||
this.persistentEntity = persistentEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdAttribute() {
|
||||
return entityMetadata.getRequiredIdProperty().getFieldName();
|
||||
return persistentEntity.getRequiredIdProperty().getFieldName();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public IndexCoordinates getIndexCoordinates() {
|
||||
return indexCoordinates;
|
||||
return persistentEntity.getIndexCoordinates();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getVersion(T entity) {
|
||||
|
||||
ElasticsearchPersistentProperty versionProperty = entityMetadata.getVersionProperty();
|
||||
ElasticsearchPersistentProperty versionProperty = persistentEntity.getVersionProperty();
|
||||
try {
|
||||
return versionProperty != null ? (Long) entityMetadata.getPropertyAccessor(entity).getProperty(versionProperty)
|
||||
return versionProperty != null ? (Long) persistentEntity.getPropertyAccessor(entity).getProperty(versionProperty)
|
||||
: null;
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException("failed to load version field", e);
|
||||
@@ -81,15 +71,15 @@ public class MappingElasticsearchEntityInformation<T, ID> extends PersistentEnti
|
||||
|
||||
@Override
|
||||
public VersionType getVersionType() {
|
||||
return versionType;
|
||||
return persistentEntity.getVersionType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getParentId(T entity) {
|
||||
|
||||
ElasticsearchPersistentProperty parentProperty = entityMetadata.getParentIdProperty();
|
||||
ElasticsearchPersistentProperty parentProperty = persistentEntity.getParentIdProperty();
|
||||
try {
|
||||
return parentProperty != null ? (String) entityMetadata.getPropertyAccessor(entity).getProperty(parentProperty)
|
||||
return parentProperty != null ? (String) persistentEntity.getPropertyAccessor(entity).getProperty(parentProperty)
|
||||
: null;
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException("failed to load parent ID: " + e, e);
|
||||
|
||||
+1
-2
@@ -113,8 +113,7 @@ public class ReactiveElasticsearchRepositoryFactory extends ReactiveRepositoryFa
|
||||
@Nullable RepositoryInformation information) {
|
||||
|
||||
ElasticsearchPersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(domainClass);
|
||||
return new MappingElasticsearchEntityInformation<>((ElasticsearchPersistentEntity<T>) entity,
|
||||
entity.getIndexCoordinates(), entity.getVersionType());
|
||||
return new MappingElasticsearchEntityInformation<>((ElasticsearchPersistentEntity<T>) entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+335
-3
@@ -15,8 +15,40 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.repository.support;
|
||||
|
||||
import static org.elasticsearch.index.query.QueryBuilders.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.elasticsearch.index.query.IdsQueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
||||
import org.springframework.data.elasticsearch.core.IndexOperations;
|
||||
import org.springframework.data.elasticsearch.core.SearchHit;
|
||||
import org.springframework.data.elasticsearch.core.SearchHitSupport;
|
||||
import org.springframework.data.elasticsearch.core.SearchHits;
|
||||
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
|
||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
import org.springframework.data.elasticsearch.core.query.MoreLikeThisQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
|
||||
import org.springframework.data.elasticsearch.core.query.Query;
|
||||
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
|
||||
import org.springframework.data.util.StreamUtils;
|
||||
import org.springframework.data.util.Streamable;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Elasticsearch specific repository implementation. Likely to be used as target within
|
||||
@@ -25,18 +57,318 @@ import org.springframework.lang.Nullable;
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
* @author Ryan Henszey
|
||||
* @author Kevin Leturc
|
||||
* @author Mark Paluch
|
||||
* @author Christoph Strobl
|
||||
* @author Michael Wirth
|
||||
* @author Sascha Woo
|
||||
* @author Murali Chevuri
|
||||
* @author Peter-Josef Meisch
|
||||
* @author Aleksei Arsenev
|
||||
*/
|
||||
public class SimpleElasticsearchRepository<T, ID> extends AbstractElasticsearchRepository<T, ID> {
|
||||
public class SimpleElasticsearchRepository<T, ID> implements ElasticsearchRepository<T, ID> {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(SimpleElasticsearchRepository.class);
|
||||
|
||||
protected ElasticsearchOperations operations;
|
||||
protected IndexOperations indexOperations;
|
||||
|
||||
protected Class<T> entityClass;
|
||||
protected ElasticsearchEntityInformation<T, ID> entityInformation;
|
||||
|
||||
public SimpleElasticsearchRepository(ElasticsearchEntityInformation<T, ID> metadata,
|
||||
ElasticsearchOperations elasticsearchOperations) {
|
||||
super(metadata, elasticsearchOperations);
|
||||
ElasticsearchOperations operations) {
|
||||
this.operations = operations;
|
||||
|
||||
Assert.notNull(metadata, "ElasticsearchEntityInformation must not be null!");
|
||||
|
||||
this.entityInformation = metadata;
|
||||
this.entityClass = this.entityInformation.getJavaType();
|
||||
this.indexOperations = operations.indexOps(this.entityClass);
|
||||
|
||||
try {
|
||||
if (shouldCreateIndexAndMapping() && !indexOperations.exists()) {
|
||||
indexOperations.create();
|
||||
indexOperations.putMapping(entityClass);
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
LOGGER.warn("Cannot create index: {}", exception.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldCreateIndexAndMapping() {
|
||||
|
||||
final ElasticsearchPersistentEntity<?> entity = operations.getElasticsearchConverter().getMappingContext()
|
||||
.getRequiredPersistentEntity(entityClass);
|
||||
return entity.isCreateIndexAndMapping();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<T> findById(ID id) {
|
||||
return Optional.ofNullable(
|
||||
execute(operations -> operations.get(stringIdRepresentation(id), entityClass, getIndexCoordinates())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<T> findAll() {
|
||||
int itemCount = (int) this.count();
|
||||
|
||||
if (itemCount == 0) {
|
||||
return new PageImpl<>(Collections.emptyList());
|
||||
}
|
||||
return this.findAll(PageRequest.of(0, Math.max(1, itemCount)));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Page<T> findAll(Pageable pageable) {
|
||||
NativeSearchQuery query = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).withPageable(pageable).build();
|
||||
SearchHits<T> searchHits = execute(operations -> operations.search(query, entityClass, getIndexCoordinates()));
|
||||
AggregatedPage<SearchHit<T>> page = SearchHitSupport.page(searchHits, query.getPageable());
|
||||
return (Page<T>) SearchHitSupport.unwrapSearchHits(page);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Iterable<T> findAll(Sort sort) {
|
||||
int itemCount = (int) this.count();
|
||||
|
||||
if (itemCount == 0) {
|
||||
return new PageImpl<>(Collections.emptyList());
|
||||
}
|
||||
NativeSearchQuery query = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
|
||||
.withPageable(PageRequest.of(0, itemCount, sort)).build();
|
||||
List<SearchHit<T>> searchHitList = execute(
|
||||
operations -> operations.search(query, entityClass, getIndexCoordinates()).getSearchHits());
|
||||
return (List<T>) SearchHitSupport.unwrapSearchHits(searchHitList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<T> findAllById(Iterable<ID> ids) {
|
||||
|
||||
Assert.notNull(ids, "ids can't be null.");
|
||||
|
||||
NativeSearchQuery query = new NativeSearchQueryBuilder().withIds(stringIdsRepresentation(ids)).build();
|
||||
List<T> result = new ArrayList<>();
|
||||
List<T> multiGetEntities = execute(operations -> operations.multiGet(query, entityClass, getIndexCoordinates()));
|
||||
|
||||
if (multiGetEntities != null) {
|
||||
multiGetEntities.forEach(entity -> {
|
||||
|
||||
if (entity != null) {
|
||||
result.add(entity);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long count() {
|
||||
NativeSearchQuery query = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build();
|
||||
// noinspection ConstantConditions
|
||||
return execute(operations -> operations.count(query, entityClass, getIndexCoordinates()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S extends T> S save(S entity) {
|
||||
|
||||
Assert.notNull(entity, "Cannot save 'null' entity.");
|
||||
|
||||
// noinspection ConstantConditions
|
||||
return executeAndRefresh(operations -> operations.save(entity, getIndexCoordinates()));
|
||||
}
|
||||
|
||||
public <S extends T> List<S> save(List<S> entities) {
|
||||
|
||||
Assert.notNull(entities, "Cannot insert 'null' as a List.");
|
||||
|
||||
return Streamable.of(saveAll(entities)).stream().collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public <S extends T> S indexWithoutRefresh(S entity) {
|
||||
Assert.notNull(entity, "Cannot save 'null' entity.");
|
||||
// noinspection ConstantConditions
|
||||
return execute(operations -> operations.save(entity));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S extends T> Iterable<S> saveAll(Iterable<S> entities) {
|
||||
|
||||
Assert.notNull(entities, "Cannot insert 'null' as a List.");
|
||||
|
||||
IndexCoordinates indexCoordinates = getIndexCoordinates();
|
||||
executeAndRefresh(operations -> operations.save(entities, indexCoordinates));
|
||||
|
||||
return entities;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean existsById(ID id) {
|
||||
// noinspection ConstantConditions
|
||||
return execute(operations -> operations.exists(stringIdRepresentation(id), getIndexCoordinates()));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Iterable<T> search(QueryBuilder query) {
|
||||
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(query).build();
|
||||
long count = execute(operations -> operations.count(searchQuery, entityClass, getIndexCoordinates()));
|
||||
|
||||
if (count == 0) {
|
||||
return new PageImpl<>(Collections.emptyList());
|
||||
}
|
||||
searchQuery.setPageable(PageRequest.of(0, (int) count));
|
||||
SearchHits<T> searchHits = execute(
|
||||
operations -> operations.search(searchQuery, entityClass, getIndexCoordinates()));
|
||||
AggregatedPage<SearchHit<T>> page = SearchHitSupport.page(searchHits, searchQuery.getPageable());
|
||||
return (Page<T>) SearchHitSupport.unwrapSearchHits(page);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Page<T> search(QueryBuilder query, Pageable pageable) {
|
||||
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(query).withPageable(pageable).build();
|
||||
SearchHits<T> searchHits = execute(
|
||||
operations -> operations.search(searchQuery, entityClass, getIndexCoordinates()));
|
||||
AggregatedPage<SearchHit<T>> page = SearchHitSupport.page(searchHits, searchQuery.getPageable());
|
||||
return (Page<T>) SearchHitSupport.unwrapSearchHits(page);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Page<T> search(Query query) {
|
||||
SearchHits<T> searchHits = execute(operations -> operations.search(query, entityClass, getIndexCoordinates()));
|
||||
AggregatedPage<SearchHit<T>> page = SearchHitSupport.page(searchHits, query.getPageable());
|
||||
return (Page<T>) SearchHitSupport.unwrapSearchHits(page);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Page<T> searchSimilar(T entity, @Nullable String[] fields, Pageable pageable) {
|
||||
|
||||
Assert.notNull(entity, "Cannot search similar records for 'null'.");
|
||||
Assert.notNull(pageable, "'pageable' cannot be 'null'");
|
||||
|
||||
MoreLikeThisQuery query = new MoreLikeThisQuery();
|
||||
query.setId(stringIdRepresentation(extractIdFromBean(entity)));
|
||||
query.setPageable(pageable);
|
||||
|
||||
if (fields != null) {
|
||||
query.addFields(fields);
|
||||
}
|
||||
|
||||
SearchHits<T> searchHits = execute(operations -> operations.search(query, entityClass, getIndexCoordinates()));
|
||||
AggregatedPage<SearchHit<T>> page = SearchHitSupport.page(searchHits, pageable);
|
||||
return (Page<T>) SearchHitSupport.unwrapSearchHits(page);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteById(ID id) {
|
||||
|
||||
Assert.notNull(id, "Cannot delete entity with id 'null'.");
|
||||
|
||||
doDelete(id, getIndexCoordinates());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(T entity) {
|
||||
|
||||
Assert.notNull(entity, "Cannot delete 'null' entity.");
|
||||
|
||||
doDelete(extractIdFromBean(entity), getIndexCoordinates());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteAll(Iterable<? extends T> entities) {
|
||||
|
||||
Assert.notNull(entities, "Cannot delete 'null' list.");
|
||||
|
||||
IndexCoordinates indexCoordinates = getIndexCoordinates();
|
||||
IdsQueryBuilder idsQueryBuilder = idsQuery();
|
||||
for (T entity : entities) {
|
||||
ID id = extractIdFromBean(entity);
|
||||
if (id != null) {
|
||||
idsQueryBuilder.addIds(stringIdRepresentation(id));
|
||||
}
|
||||
}
|
||||
|
||||
if (idsQueryBuilder.ids().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Query query = new NativeSearchQueryBuilder().withQuery(idsQueryBuilder).build();
|
||||
|
||||
executeAndRefresh((OperationsCallback<Void>) operations -> {
|
||||
operations.delete(query, entityClass, indexCoordinates);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
private void doDelete(@Nullable ID id, IndexCoordinates indexCoordinates) {
|
||||
|
||||
if (id != null) {
|
||||
executeAndRefresh(operations -> operations.delete(stringIdRepresentation(id), indexCoordinates));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteAll() {
|
||||
IndexCoordinates indexCoordinates = getIndexCoordinates();
|
||||
Query query = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build();
|
||||
|
||||
executeAndRefresh((OperationsCallback<Void>) operations -> {
|
||||
operations.delete(query, entityClass, indexCoordinates);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh() {
|
||||
indexOperations.refresh();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected ID extractIdFromBean(T entity) {
|
||||
return entityInformation.getId(entity);
|
||||
}
|
||||
|
||||
private List<String> stringIdsRepresentation(Iterable<ID> ids) {
|
||||
|
||||
Assert.notNull(ids, "ids can't be null.");
|
||||
|
||||
return StreamUtils.createStreamFromIterator(ids.iterator()).map(id -> stringIdRepresentation(id))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
protected @Nullable String stringIdRepresentation(@Nullable ID id) {
|
||||
return operations.stringIdRepresentation(id);
|
||||
}
|
||||
|
||||
private IndexCoordinates getIndexCoordinates() {
|
||||
return operations.getIndexCoordinatesFor(entityClass);
|
||||
}
|
||||
|
||||
// region operations callback
|
||||
@FunctionalInterface
|
||||
public interface OperationsCallback<R> {
|
||||
@Nullable
|
||||
R doWithOperations(ElasticsearchOperations operations);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public <R> R execute(OperationsCallback<R> callback) {
|
||||
return callback.doWithOperations(operations);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public <R> R executeAndRefresh(OperationsCallback<R> callback) {
|
||||
R result = callback.doWithOperations(operations);
|
||||
refresh();
|
||||
return result;
|
||||
}
|
||||
// endregion
|
||||
}
|
||||
|
||||
+77
-38
@@ -18,12 +18,18 @@ package org.springframework.data.elasticsearch.repository.support;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.elasticsearch.action.support.WriteRequest.RefreshPolicy;
|
||||
import org.elasticsearch.index.query.QueryBuilders;
|
||||
import org.reactivestreams.Publisher;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations;
|
||||
import org.springframework.data.elasticsearch.core.ReactiveElasticsearchTemplate;
|
||||
import org.springframework.data.elasticsearch.core.ReactiveIndexOperations;
|
||||
import org.springframework.data.elasticsearch.core.SearchHit;
|
||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
|
||||
import org.springframework.data.elasticsearch.core.query.Query;
|
||||
@@ -39,24 +45,53 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class SimpleReactiveElasticsearchRepository<T, ID> implements ReactiveElasticsearchRepository<T, ID> {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(SimpleElasticsearchRepository.class);
|
||||
|
||||
private final ElasticsearchEntityInformation<T, ID> entityInformation;
|
||||
private final ReactiveElasticsearchOperations elasticsearchOperations;
|
||||
private final ReactiveElasticsearchOperations operations;
|
||||
private final ReactiveIndexOperations indexOperations;
|
||||
|
||||
public SimpleReactiveElasticsearchRepository(ElasticsearchEntityInformation<T, ID> entityInformation,
|
||||
ReactiveElasticsearchOperations elasticsearchOperations) {
|
||||
ReactiveElasticsearchOperations operations) {
|
||||
|
||||
Assert.notNull(entityInformation, "EntityInformation must not be null!");
|
||||
Assert.notNull(elasticsearchOperations, "ElasticsearchOperations must not be null!");
|
||||
Assert.notNull(operations, "ElasticsearchOperations must not be null!");
|
||||
|
||||
this.entityInformation = entityInformation;
|
||||
this.elasticsearchOperations = elasticsearchOperations;
|
||||
this.operations = operations;
|
||||
this.indexOperations = operations.indexOps(entityInformation.getJavaType());
|
||||
|
||||
createIndexAndMappingIfNeeded();
|
||||
}
|
||||
|
||||
private void createIndexAndMappingIfNeeded() {
|
||||
try {
|
||||
|
||||
if (shouldCreateIndexAndMapping()) {
|
||||
indexOperations.exists() //
|
||||
.flatMap(exists -> exists ? Mono.empty() : indexOperations.create()) //
|
||||
.flatMap(success -> success ? indexOperations.putMapping() : Mono.empty()) //
|
||||
.block();
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
LOGGER.warn("Cannot create index: {}", exception.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldCreateIndexAndMapping() {
|
||||
|
||||
final ElasticsearchPersistentEntity<?> entity = operations.getElasticsearchConverter().getMappingContext()
|
||||
.getRequiredPersistentEntity(entityInformation.getJavaType());
|
||||
return entity.isCreateIndexAndMapping();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S extends T> Mono<S> save(S entity) {
|
||||
|
||||
Assert.notNull(entity, "Entity must not be null!");
|
||||
return elasticsearchOperations.save(entity, entityInformation.getIndexCoordinates());
|
||||
|
||||
return operations.save(entity, entityInformation.getIndexCoordinates())
|
||||
.flatMap(saved -> doRefresh().thenReturn(saved));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -71,16 +106,15 @@ public class SimpleReactiveElasticsearchRepository<T, ID> implements ReactiveEla
|
||||
|
||||
Assert.notNull(entityStream, "EntityStream must not be null!");
|
||||
|
||||
return elasticsearchOperations.saveAll(Flux.from(entityStream).collectList(),
|
||||
entityInformation.getIndexCoordinates());
|
||||
return operations.saveAll(Flux.from(entityStream).collectList(), entityInformation.getIndexCoordinates())
|
||||
.concatWith(doRefresh().then(Mono.empty()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<T> findById(ID id) {
|
||||
|
||||
Assert.notNull(id, "Id must not be null!");
|
||||
return elasticsearchOperations.get(convertId(id), entityInformation.getJavaType(),
|
||||
entityInformation.getIndexCoordinates());
|
||||
return operations.get(convertId(id), entityInformation.getJavaType(), entityInformation.getIndexCoordinates());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -94,8 +128,7 @@ public class SimpleReactiveElasticsearchRepository<T, ID> implements ReactiveEla
|
||||
public Mono<Boolean> existsById(ID id) {
|
||||
|
||||
Assert.notNull(id, "Id must not be null!");
|
||||
return elasticsearchOperations.exists(convertId(id), entityInformation.getJavaType(),
|
||||
entityInformation.getIndexCoordinates());
|
||||
return operations.exists(convertId(id), entityInformation.getIndexCoordinates());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -108,14 +141,14 @@ public class SimpleReactiveElasticsearchRepository<T, ID> implements ReactiveEla
|
||||
@Override
|
||||
public Flux<T> findAll() {
|
||||
|
||||
return elasticsearchOperations.search(Query.findAll().setPageable(Pageable.unpaged()),
|
||||
entityInformation.getJavaType(), entityInformation.getIndexCoordinates()).map(SearchHit::getContent);
|
||||
return operations.search(Query.findAll().setPageable(Pageable.unpaged()), entityInformation.getJavaType(),
|
||||
entityInformation.getIndexCoordinates()).map(SearchHit::getContent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<T> findAll(Sort sort) {
|
||||
|
||||
return elasticsearchOperations.search(Query.findAll().addSort(sort).setPageable(Pageable.unpaged()),
|
||||
return operations.search(Query.findAll().addSort(sort).setPageable(Pageable.unpaged()),
|
||||
entityInformation.getJavaType(), entityInformation.getIndexCoordinates()).map(SearchHit::getContent);
|
||||
}
|
||||
|
||||
@@ -138,24 +171,22 @@ public class SimpleReactiveElasticsearchRepository<T, ID> implements ReactiveEla
|
||||
.flatMapMany(query -> {
|
||||
|
||||
IndexCoordinates index = entityInformation.getIndexCoordinates();
|
||||
return elasticsearchOperations.multiGet(query, entityInformation.getJavaType(), index);
|
||||
return operations.multiGet(query, entityInformation.getJavaType(), index);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Long> count() {
|
||||
|
||||
return elasticsearchOperations.count(Query.findAll(), entityInformation.getJavaType(),
|
||||
entityInformation.getIndexCoordinates());
|
||||
return operations.count(Query.findAll(), entityInformation.getJavaType(), entityInformation.getIndexCoordinates());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> deleteById(ID id) {
|
||||
|
||||
Assert.notNull(id, "Id must not be null!");
|
||||
return elasticsearchOperations
|
||||
.delete(convertId(id), entityInformation.getIndexCoordinates()) //
|
||||
.then();
|
||||
return operations.delete(convertId(id), entityInformation.getIndexCoordinates()) //
|
||||
.then(doRefresh());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -169,8 +200,8 @@ public class SimpleReactiveElasticsearchRepository<T, ID> implements ReactiveEla
|
||||
public Mono<Void> delete(T entity) {
|
||||
|
||||
Assert.notNull(entity, "Entity must not be null!");
|
||||
return elasticsearchOperations.delete(entity, entityInformation.getIndexCoordinates()) //
|
||||
.then();
|
||||
return operations.delete(entity, entityInformation.getIndexCoordinates()) //
|
||||
.then(doRefresh());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -192,29 +223,37 @@ public class SimpleReactiveElasticsearchRepository<T, ID> implements ReactiveEla
|
||||
throw new IllegalStateException("Entity id must not be null!");
|
||||
}
|
||||
return convertId(id);
|
||||
}).collectList().map(objects -> {
|
||||
|
||||
return new StringQuery(QueryBuilders.idsQuery() //
|
||||
.addIds(objects.toArray(new String[0])) //
|
||||
.toString());
|
||||
}) //
|
||||
.flatMap(query -> {
|
||||
|
||||
return elasticsearchOperations.delete(query, entityInformation.getJavaType(),
|
||||
entityInformation.getIndexCoordinates());
|
||||
}) //
|
||||
.then();
|
||||
}).collectList().map(objects -> new StringQuery(QueryBuilders.idsQuery() //
|
||||
.addIds(objects.toArray(new String[0])) //
|
||||
.toString())) //
|
||||
.flatMap(
|
||||
query -> operations.delete(query, entityInformation.getJavaType(), entityInformation.getIndexCoordinates())) //
|
||||
.then(doRefresh());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> deleteAll() {
|
||||
|
||||
return elasticsearchOperations
|
||||
.delete(Query.findAll(), entityInformation.getJavaType(), entityInformation.getIndexCoordinates()) //
|
||||
.then();
|
||||
return operations.delete(Query.findAll(), entityInformation.getJavaType(), entityInformation.getIndexCoordinates()) //
|
||||
.then(doRefresh());
|
||||
}
|
||||
|
||||
private String convertId(Object id) {
|
||||
return elasticsearchOperations.getElasticsearchConverter().convertId(id);
|
||||
return operations.getElasticsearchConverter().convertId(id);
|
||||
}
|
||||
|
||||
private Mono<Void> doRefresh() {
|
||||
RefreshPolicy refreshPolicy = null;
|
||||
|
||||
if (operations instanceof ReactiveElasticsearchTemplate) {
|
||||
refreshPolicy = ((ReactiveElasticsearchTemplate) operations).getRefreshPolicy();
|
||||
}
|
||||
|
||||
if (refreshPolicy == null || refreshPolicy == RefreshPolicy.NONE) {
|
||||
return indexOperations.refresh();
|
||||
}
|
||||
|
||||
return Mono.empty();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,42 @@
|
||||
Spring Data Elasticsearch Changelog
|
||||
===================================
|
||||
|
||||
Changes in version 4.1.0-M1 (2020-06-25)
|
||||
----------------------------------------
|
||||
* DATAES-870 - Workaround for reactor-netty error.
|
||||
* DATAES-868 - Upgrade to Netty 4.1.50.Final.
|
||||
* DATAES-867 - Adopt to changes in Reactor Netty 1.0.
|
||||
* DATAES-866 - Implement suggest search in reactive client.
|
||||
* DATAES-865 - Fix MappingElasticsearchConverter writing an Object property containing a Map.
|
||||
* DATAES-863 - Improve server error response handling.
|
||||
* DATAES-859 - Don't use randomNumeric() in tests.
|
||||
* DATAES-858 - Use standard Spring code of conduct.
|
||||
* DATAES-857 - Registered simple types are not read from list.
|
||||
* DATAES-853 - Cleanup tests that do not delete test indices.
|
||||
* DATAES-852 - Upgrade to Elasticsearch 7.7.1.
|
||||
* DATAES-850 - Add warning and documentation for missing TemporalAccessor configuration.
|
||||
* DATAES-848 - Add the name of the index to SearchHit.
|
||||
* DATAES-847 - Add missing DateFormat values.
|
||||
* DATAES-845 - MappingElasticsearchConverter crashes when writing lists containing null values.
|
||||
* DATAES-844 - Improve TOC formatting for migration guides.
|
||||
* DATAES-841 - Remove deprecated type mappings code.
|
||||
* DATAES-840 - Consolidate index name SpEL resolution.
|
||||
* DATAES-839 - ReactiveElasticsearchTemplate should use RequestFactory.
|
||||
* DATAES-838 - Update to Elasticsearch 7.7.0.
|
||||
* DATAES-836 - Fix typo in Javadocs.
|
||||
* DATAES-835 - Fix code sample in documentation for scroll API.
|
||||
* DATAES-832 - findAllById repository method returns iterable with null elements for not found ids.
|
||||
* DATAES-831 - SearchOperations.searchForStream does not use requested maxResults.
|
||||
* DATAES-829 - Deprecate AbstractElasticsearchRepository and cleanup SimpleElasticsearchRepository.
|
||||
* DATAES-828 - Fields of type date need to have a format defined.
|
||||
* DATAES-827 - Repositories should not try to create an index when it already exists.
|
||||
* DATAES-826 - Add method to IndexOperations to write an index mapping from a entity class.
|
||||
* DATAES-825 - Update readme to use latest spring.io docs.
|
||||
* DATAES-824 - Release 4.1 M1 (2020.0.0).
|
||||
* DATAES-678 - Introduce ReactiveIndexOperations.
|
||||
* DATAES-263 - Inner Hits support.
|
||||
|
||||
|
||||
Changes in version 4.0.1.RELEASE (2020-06-10)
|
||||
---------------------------------------------
|
||||
* DATAES-857 - Registered simple types are not read from list.
|
||||
@@ -1173,3 +1209,4 @@ Release Notes - Spring Data Elasticsearch - Version 1.0 M1 (2014-02-07)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Spring Data Elasticsearch 4.0.1
|
||||
Spring Data Elasticsearch 4.1 M1 (2020.0.0)
|
||||
Copyright (c) [2013-2019] Pivotal Software, Inc.
|
||||
|
||||
This product is licensed to you under the Apache License, Version 2.0 (the "License").
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch;
|
||||
|
||||
import static org.apache.commons.lang.RandomStringUtils.*;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.*;
|
||||
import static org.springframework.data.elasticsearch.utils.IdGenerator.*;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
@@ -34,6 +34,7 @@ import java.util.Map;
|
||||
import org.apache.lucene.search.join.ScoreMode;
|
||||
import org.elasticsearch.index.query.BoolQueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -67,11 +68,16 @@ public class NestedObjectTests {
|
||||
|
||||
@Autowired private ElasticsearchOperations operations;
|
||||
|
||||
private final List<Class<?>> entityClasses = Arrays.asList(Book.class, Person.class, PersonMultipleLevelNested.class);
|
||||
|
||||
@BeforeEach
|
||||
public void before() {
|
||||
IndexInitializer.init(operations.indexOps(Book.class));
|
||||
IndexInitializer.init(operations.indexOps(Person.class));
|
||||
IndexInitializer.init(operations.indexOps(PersonMultipleLevelNested.class));
|
||||
entityClasses.stream().map(operations::indexOps).forEach(IndexInitializer::init);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
entityClasses.forEach(clazz -> operations.indexOps(clazz).delete());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -121,7 +127,7 @@ public class NestedObjectTests {
|
||||
indexQueries.add(indexQuery1);
|
||||
indexQueries.add(indexQuery2);
|
||||
|
||||
IndexCoordinates index = IndexCoordinates.of("test-index-person").withTypes("user");
|
||||
IndexCoordinates index = IndexCoordinates.of("test-index-person");
|
||||
operations.bulkIndex(indexQueries, index);
|
||||
operations.indexOps(Person.class).refresh();
|
||||
|
||||
@@ -141,13 +147,12 @@ public class NestedObjectTests {
|
||||
List<IndexQuery> indexQueries = createPerson();
|
||||
|
||||
// when
|
||||
operations.bulkIndex(indexQueries,
|
||||
IndexCoordinates.of("test-index-person-multiple-level-nested").withTypes("user"));
|
||||
operations.bulkIndex(indexQueries, IndexCoordinates.of("test-index-person-multiple-level-nested"));
|
||||
operations.indexOps(PersonMultipleLevelNested.class).refresh();
|
||||
|
||||
// then
|
||||
PersonMultipleLevelNested personIndexed = operations.get("1", PersonMultipleLevelNested.class,
|
||||
IndexCoordinates.of("test-index-person-multiple-level-nested").withTypes("user"));
|
||||
IndexCoordinates.of("test-index-person-multiple-level-nested"));
|
||||
assertThat(personIndexed).isNotNull();
|
||||
}
|
||||
|
||||
@@ -158,8 +163,7 @@ public class NestedObjectTests {
|
||||
List<IndexQuery> indexQueries = createPerson();
|
||||
|
||||
// when
|
||||
operations.bulkIndex(indexQueries,
|
||||
IndexCoordinates.of("test-index-person-multiple-level-nested").withTypes("user"));
|
||||
operations.bulkIndex(indexQueries, IndexCoordinates.of("test-index-person-multiple-level-nested"));
|
||||
|
||||
// then
|
||||
Map<String, Object> mapping = operations.indexOps(PersonMultipleLevelNested.class).getMapping();
|
||||
@@ -178,7 +182,7 @@ public class NestedObjectTests {
|
||||
List<IndexQuery> indexQueries = createPerson();
|
||||
|
||||
// when
|
||||
IndexCoordinates index = IndexCoordinates.of("test-index-person-multiple-level-nested").withTypes("user");
|
||||
IndexCoordinates index = IndexCoordinates.of("test-index-person-multiple-level-nested");
|
||||
operations.bulkIndex(indexQueries, index);
|
||||
operations.indexOps(PersonMultipleLevelNested.class).refresh();
|
||||
|
||||
@@ -318,7 +322,7 @@ public class NestedObjectTests {
|
||||
indexQueries.add(indexQuery1);
|
||||
indexQueries.add(indexQuery2);
|
||||
|
||||
IndexCoordinates index = IndexCoordinates.of("test-index-person").withTypes("user");
|
||||
IndexCoordinates index = IndexCoordinates.of("test-index-person");
|
||||
operations.bulkIndex(indexQueries, index);
|
||||
operations.indexOps(Person.class).refresh();
|
||||
|
||||
@@ -339,10 +343,10 @@ public class NestedObjectTests {
|
||||
Book book1 = new Book();
|
||||
Book book2 = new Book();
|
||||
|
||||
book1.setId(randomNumeric(5));
|
||||
book1.setId(nextIdAsString());
|
||||
book1.setName("testBook1");
|
||||
|
||||
book2.setId(randomNumeric(5));
|
||||
book2.setId(nextIdAsString());
|
||||
book2.setName("testBook2");
|
||||
|
||||
Map<Integer, Collection<String>> map1 = new HashMap<>();
|
||||
@@ -367,7 +371,7 @@ public class NestedObjectTests {
|
||||
indexQueries.add(indexQuery2);
|
||||
|
||||
// when
|
||||
IndexCoordinates index = IndexCoordinates.of("test-index-book-nested-objects").withTypes("book");
|
||||
IndexCoordinates index = IndexCoordinates.of("test-index-book-nested-objects");
|
||||
operations.bulkIndex(indexQueries, index);
|
||||
operations.indexOps(Book.class).refresh();
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import java.util.stream.Stream;
|
||||
|
||||
import org.elasticsearch.client.RequestOptions;
|
||||
import org.elasticsearch.client.RestHighLevelClient;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
@@ -26,6 +27,7 @@ import com.github.tomakehurst.wiremock.matching.EqualToPattern;
|
||||
/**
|
||||
* @author Peter-Josef Meisch
|
||||
*/
|
||||
@Disabled("SocketException: Socket closed happens on the CLI build while running the test individually succeeds")
|
||||
public class RestClientsTest {
|
||||
|
||||
@ParameterizedTest // DATAES-700
|
||||
@@ -125,7 +127,7 @@ public class RestClientsTest {
|
||||
|
||||
/**
|
||||
* starts a Wiremock server and calls consumer with the server as argument. Stops the server after consumer execution.
|
||||
*
|
||||
*
|
||||
* @param consumer the consumer
|
||||
*/
|
||||
private void wireMockServer(WiremockConsumer consumer) {
|
||||
@@ -147,7 +149,7 @@ public class RestClientsTest {
|
||||
interface ClientUnderTest {
|
||||
/**
|
||||
* Pings the configured server.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean ping() throws Exception;
|
||||
@@ -215,7 +217,7 @@ public class RestClientsTest {
|
||||
|
||||
/**
|
||||
* Provides the factories to use in the parameterized tests
|
||||
*
|
||||
*
|
||||
* @return stream of factories
|
||||
*/
|
||||
static Stream<ClientUnderTestFactory> clientUnderTestFactorySource() {
|
||||
|
||||
+2
@@ -117,9 +117,11 @@ public class MultiNodeHostProviderUnitTests {
|
||||
mock.when(HOST_2).get(requestHeadersUriSpec -> {
|
||||
|
||||
ClientResponse response1 = mock(ClientResponse.class);
|
||||
when(response1.releaseBody()).thenReturn(Mono.empty());
|
||||
Receive.error(response1);
|
||||
|
||||
ClientResponse response2 = mock(ClientResponse.class);
|
||||
when(response2.releaseBody()).thenReturn(Mono.empty());
|
||||
Receive.ok(response2);
|
||||
|
||||
when(requestHeadersUriSpec.exchange()).thenReturn(Mono.just(response1), Mono.just(response2));
|
||||
|
||||
+32
-2
@@ -53,6 +53,8 @@ import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.search.aggregations.AggregationBuilders;
|
||||
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
|
||||
import org.elasticsearch.search.builder.SearchSourceBuilder;
|
||||
import org.elasticsearch.search.suggest.SuggestBuilder;
|
||||
import org.elasticsearch.search.suggest.completion.CompletionSuggestionBuilder;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -71,6 +73,7 @@ import org.springframework.test.context.ContextConfiguration;
|
||||
* @author Peter-Josef Meisch
|
||||
* @author Henrique Amaral
|
||||
* @author Russell Parry
|
||||
* @author Thomas Geese
|
||||
*/
|
||||
@SpringIntegrationTest
|
||||
@ContextConfiguration(classes = { ElasticsearchRestTemplateConfiguration.class })
|
||||
@@ -497,11 +500,12 @@ public class ReactiveElasticsearchClientTests {
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-569
|
||||
@Test // DATAES-569, DATAES-678
|
||||
public void createIndex() throws IOException {
|
||||
|
||||
client.indices().createIndex(request -> request.index(INDEX_I)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(true) //
|
||||
.verifyComplete();
|
||||
|
||||
assertThat(syncClient.indices().exists(new GetIndexRequest(INDEX_I), RequestOptions.DEFAULT)).isTrue();
|
||||
@@ -517,13 +521,14 @@ public class ReactiveElasticsearchClientTests {
|
||||
.verifyError(ElasticsearchStatusException.class);
|
||||
}
|
||||
|
||||
@Test // DATAES-569
|
||||
@Test // DATAES-569, DATAES-678
|
||||
public void deleteExistingIndex() throws IOException {
|
||||
|
||||
syncClient.indices().create(new CreateIndexRequest(INDEX_I), RequestOptions.DEFAULT);
|
||||
|
||||
client.indices().deleteIndex(request -> request.indices(INDEX_I)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(true) //
|
||||
.verifyComplete();
|
||||
|
||||
assertThat(syncClient.indices().exists(new GetIndexRequest(INDEX_I), RequestOptions.DEFAULT)).isFalse();
|
||||
@@ -601,6 +606,7 @@ public class ReactiveElasticsearchClientTests {
|
||||
|
||||
client.indices().updateMapping(request -> request.indices(INDEX_I).type(TYPE_I).source(jsonMap)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(true) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@@ -678,6 +684,30 @@ public class ReactiveElasticsearchClientTests {
|
||||
.expectNextMatches(aggregation -> aggregation.getType().equals(StringTerms.NAME)).verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-866
|
||||
public void suggestReturnsSuggestionResults() throws IOException {
|
||||
syncClient.indices().create(new CreateIndexRequest(INDEX_I), RequestOptions.DEFAULT);
|
||||
Map<String, Object> jsonMap = Collections.singletonMap("properties",
|
||||
Collections.singletonMap("firstname", Collections.singletonMap("type", "completion")));
|
||||
syncClient.indices().putMapping(new PutMappingRequest(INDEX_I).source(jsonMap), RequestOptions.DEFAULT);
|
||||
|
||||
addSourceDocument().ofType(TYPE_I).to(INDEX_I);
|
||||
|
||||
SuggestBuilder suggestBuilder = new SuggestBuilder().addSuggestion("firstname",
|
||||
new CompletionSuggestionBuilder("firstname").prefix("ch"));
|
||||
|
||||
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
|
||||
searchSourceBuilder.suggest(suggestBuilder);
|
||||
|
||||
SearchRequest request = new SearchRequest(INDEX_I) //
|
||||
.source(searchSourceBuilder);
|
||||
|
||||
client
|
||||
.suggest(request).as(StepVerifier::create).expectNextMatches(suggestions -> suggestions
|
||||
.getSuggestion("firstname").getEntries().get(0).getOptions().get(0).getText().string().equals("chade"))
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
private AddToIndexOfType addSourceDocument() {
|
||||
return add(DOC_SOURCE);
|
||||
}
|
||||
|
||||
+1
@@ -243,6 +243,7 @@ public class ReactiveMockClientTestsUtils {
|
||||
Mockito.when(headersUriSpec.exchange()).thenReturn(Mono.just(response));
|
||||
Mockito.when(bodySpy.exchange()).thenReturn(Mono.just(response));
|
||||
Mockito.when(response.statusCode()).thenReturn(HttpStatus.ACCEPTED);
|
||||
Mockito.when(response.releaseBody()).thenReturn(Mono.empty());
|
||||
|
||||
headersUriSpecMap.putIfAbsent(key, headersUriSpec);
|
||||
bodyUriSpecMap.putIfAbsent(key, bodySpy);
|
||||
|
||||
+8
@@ -24,6 +24,7 @@ import java.lang.Double;
|
||||
import java.lang.Long;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.BeansException;
|
||||
@@ -42,6 +43,7 @@ import org.springframework.data.elasticsearch.annotations.ScriptedField;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
||||
import org.springframework.data.elasticsearch.core.IndexOperations;
|
||||
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.ElasticsearchRestTemplateConfiguration;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.SpringIntegrationTest;
|
||||
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
|
||||
@@ -90,6 +92,12 @@ public class EnableElasticsearchRepositoriesTests implements ApplicationContextA
|
||||
IndexInitializer.init(indexOperations);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
operations.indexOps(IndexCoordinates.of("test-index-sample-config-not-nested")).delete();
|
||||
operations.indexOps(IndexCoordinates.of("test-index-uuid-keyed-config-not-nested")).delete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bootstrapsRepository() {
|
||||
|
||||
|
||||
+20
-7
@@ -17,6 +17,7 @@ package org.springframework.data.elasticsearch.core;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -27,7 +28,9 @@ import org.elasticsearch.common.bytes.BytesArray;
|
||||
import org.elasticsearch.common.document.DocumentField;
|
||||
import org.elasticsearch.common.text.Text;
|
||||
import org.elasticsearch.index.get.GetResult;
|
||||
import org.elasticsearch.index.shard.ShardId;
|
||||
import org.elasticsearch.search.SearchHit;
|
||||
import org.elasticsearch.search.SearchShardTarget;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.data.elasticsearch.core.document.Document;
|
||||
import org.springframework.data.elasticsearch.core.document.DocumentAdapters;
|
||||
@@ -42,7 +45,7 @@ import org.springframework.data.elasticsearch.core.document.SearchDocument;
|
||||
*/
|
||||
public class DocumentAdaptersUnitTests {
|
||||
|
||||
@Test // DATAES-628
|
||||
@Test // DATAES-628, DATAES-848
|
||||
public void shouldAdaptGetResponse() {
|
||||
|
||||
Map<String, DocumentField> fields = Collections.singletonMap("field",
|
||||
@@ -53,6 +56,7 @@ public class DocumentAdaptersUnitTests {
|
||||
|
||||
Document document = DocumentAdapters.from(response);
|
||||
|
||||
assertThat(document.getIndex()).isEqualTo("index");
|
||||
assertThat(document.hasId()).isTrue();
|
||||
assertThat(document.getId()).isEqualTo("my-id");
|
||||
assertThat(document.hasVersion()).isTrue();
|
||||
@@ -64,7 +68,7 @@ public class DocumentAdaptersUnitTests {
|
||||
assertThat(document.getPrimaryTerm()).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test // DATAES-628
|
||||
@Test // DATAES-628, DATAES-848
|
||||
public void shouldAdaptGetResponseSource() {
|
||||
|
||||
BytesArray source = new BytesArray("{\"field\":\"value\"}");
|
||||
@@ -74,6 +78,7 @@ public class DocumentAdaptersUnitTests {
|
||||
|
||||
Document document = DocumentAdapters.from(response);
|
||||
|
||||
assertThat(document.getIndex()).isEqualTo("index");
|
||||
assertThat(document.hasId()).isTrue();
|
||||
assertThat(document.getId()).isEqualTo("my-id");
|
||||
assertThat(document.hasVersion()).isTrue();
|
||||
@@ -85,7 +90,7 @@ public class DocumentAdaptersUnitTests {
|
||||
assertThat(document.getPrimaryTerm()).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test // DATAES-799
|
||||
@Test // DATAES-799, DATAES-848
|
||||
public void shouldAdaptGetResult() {
|
||||
|
||||
Map<String, DocumentField> fields = Collections.singletonMap("field",
|
||||
@@ -95,6 +100,7 @@ public class DocumentAdaptersUnitTests {
|
||||
|
||||
Document document = DocumentAdapters.from(getResult);
|
||||
|
||||
assertThat(document.getIndex()).isEqualTo("index");
|
||||
assertThat(document.hasId()).isTrue();
|
||||
assertThat(document.getId()).isEqualTo("my-id");
|
||||
assertThat(document.hasVersion()).isTrue();
|
||||
@@ -106,7 +112,7 @@ public class DocumentAdaptersUnitTests {
|
||||
assertThat(document.getPrimaryTerm()).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test // DATAES-799
|
||||
@Test // DATAES-799, DATAES-848
|
||||
public void shouldAdaptGetResultSource() {
|
||||
|
||||
BytesArray source = new BytesArray("{\"field\":\"value\"}");
|
||||
@@ -115,6 +121,7 @@ public class DocumentAdaptersUnitTests {
|
||||
|
||||
Document document = DocumentAdapters.from(getResult);
|
||||
|
||||
assertThat(document.getIndex()).isEqualTo("index");
|
||||
assertThat(document.hasId()).isTrue();
|
||||
assertThat(document.getId()).isEqualTo("my-id");
|
||||
assertThat(document.hasVersion()).isTrue();
|
||||
@@ -126,19 +133,22 @@ public class DocumentAdaptersUnitTests {
|
||||
assertThat(document.getPrimaryTerm()).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test // DATAES-628
|
||||
public void shouldAdaptSearchResponse() {
|
||||
@Test // DATAES-628, DATAES-848
|
||||
public void shouldAdaptSearchResponse() throws IOException {
|
||||
|
||||
Map<String, DocumentField> fields = Collections.singletonMap("field",
|
||||
new DocumentField("field", Collections.singletonList("value")));
|
||||
|
||||
SearchShardTarget shard = new SearchShardTarget("node", new ShardId("index", "uuid", 42), null, null);
|
||||
SearchHit searchHit = new SearchHit(123, "my-id", new Text("type"), fields);
|
||||
searchHit.shard(shard);
|
||||
searchHit.setSeqNo(1);
|
||||
searchHit.setPrimaryTerm(2);
|
||||
searchHit.score(42);
|
||||
|
||||
SearchDocument document = DocumentAdapters.from(searchHit);
|
||||
|
||||
assertThat(document.getIndex()).isEqualTo("index");
|
||||
assertThat(document.hasId()).isTrue();
|
||||
assertThat(document.getId()).isEqualTo("my-id");
|
||||
assertThat(document.hasVersion()).isFalse();
|
||||
@@ -199,12 +209,14 @@ public class DocumentAdaptersUnitTests {
|
||||
assertThat(document.toJson()).isEqualTo("{\"string\":\"value\",\"bool\":[true,true,false]}");
|
||||
}
|
||||
|
||||
@Test // DATAES-628
|
||||
@Test // DATAES-628, DATAES-848
|
||||
public void shouldAdaptSearchResponseSource() {
|
||||
|
||||
BytesArray source = new BytesArray("{\"field\":\"value\"}");
|
||||
|
||||
SearchShardTarget shard = new SearchShardTarget("node", new ShardId("index", "uuid", 42), null, null);
|
||||
SearchHit searchHit = new SearchHit(123, "my-id", new Text("type"), Collections.emptyMap());
|
||||
searchHit.shard(shard);
|
||||
searchHit.sourceRef(source).score(42);
|
||||
searchHit.version(22);
|
||||
searchHit.setSeqNo(1);
|
||||
@@ -212,6 +224,7 @@ public class DocumentAdaptersUnitTests {
|
||||
|
||||
SearchDocument document = DocumentAdapters.from(searchHit);
|
||||
|
||||
assertThat(document.getIndex()).isEqualTo("index");
|
||||
assertThat(document.hasId()).isTrue();
|
||||
assertThat(document.getId()).isEqualTo("my-id");
|
||||
assertThat(document.hasVersion()).isTrue();
|
||||
|
||||
+1
@@ -492,6 +492,7 @@ class ElasticsearchPartQueryTests {
|
||||
|
||||
private String getQueryBuilder(String methodName, Class<?>[] parameterClasses, Object[] parameters)
|
||||
throws NoSuchMethodException {
|
||||
|
||||
Method method = SampleRepository.class.getMethod(methodName, parameterClasses);
|
||||
ElasticsearchQueryMethod queryMethod = new ElasticsearchQueryMethod(method,
|
||||
new DefaultRepositoryMetadata(SampleRepository.class), new SpelAwareProxyProjectionFactory(),
|
||||
|
||||
+2
-2
@@ -15,9 +15,9 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.core;
|
||||
|
||||
import static org.apache.commons.lang.RandomStringUtils.*;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.springframework.data.elasticsearch.annotations.FieldType.*;
|
||||
import static org.springframework.data.elasticsearch.utils.IdGenerator.*;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
@@ -67,7 +67,7 @@ public class ElasticsearchRestTemplateTests extends ElasticsearchTemplateTests {
|
||||
// when
|
||||
org.springframework.data.elasticsearch.core.document.Document document = org.springframework.data.elasticsearch.core.document.Document
|
||||
.create();
|
||||
UpdateQuery updateQuery = UpdateQuery.builder(randomNumeric(5)).withDocument(document).build();
|
||||
UpdateQuery updateQuery = UpdateQuery.builder(nextIdAsString()).withDocument(document).build();
|
||||
assertThatThrownBy(() -> operations.update(updateQuery, index))
|
||||
.isInstanceOf(UncategorizedElasticsearchException.class);
|
||||
}
|
||||
|
||||
+158
-131
@@ -16,11 +16,11 @@
|
||||
package org.springframework.data.elasticsearch.core;
|
||||
|
||||
import static java.util.Collections.*;
|
||||
import static org.apache.commons.lang.RandomStringUtils.*;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.*;
|
||||
import static org.springframework.data.elasticsearch.annotations.FieldType.*;
|
||||
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 lombok.AllArgsConstructor;
|
||||
@@ -110,9 +110,8 @@ public abstract class ElasticsearchTemplateTests {
|
||||
private static final String INDEX_1_NAME = "test-index-1";
|
||||
private static final String INDEX_2_NAME = "test-index-2";
|
||||
private static final String INDEX_3_NAME = "test-index-3";
|
||||
private static final String TYPE_NAME = "test-type";
|
||||
|
||||
protected final IndexCoordinates index = IndexCoordinates.of(INDEX_NAME_SAMPLE_ENTITY).withTypes(TYPE_NAME);
|
||||
protected final IndexCoordinates index = IndexCoordinates.of(INDEX_NAME_SAMPLE_ENTITY);
|
||||
|
||||
@Autowired protected ElasticsearchOperations operations;
|
||||
private IndexOperations indexOperations;
|
||||
@@ -123,15 +122,15 @@ public abstract class ElasticsearchTemplateTests {
|
||||
deleteIndices();
|
||||
|
||||
indexOperations.create();
|
||||
indexOperations.putMapping(indexOperations.createMapping(SampleEntity.class));
|
||||
indexOperations.putMapping(SampleEntity.class);
|
||||
|
||||
IndexOperations indexOpsSampleEntityUUIDKeyed = operations.indexOps(SampleEntityUUIDKeyed.class);
|
||||
indexOpsSampleEntityUUIDKeyed.create();
|
||||
indexOpsSampleEntityUUIDKeyed.putMapping(indexOpsSampleEntityUUIDKeyed.createMapping(SampleEntityUUIDKeyed.class));
|
||||
indexOpsSampleEntityUUIDKeyed.putMapping(SampleEntityUUIDKeyed.class);
|
||||
|
||||
IndexOperations indexOpsSearchHitsEntity = operations.indexOps(SearchHitsEntity.class);
|
||||
indexOpsSearchHitsEntity.create();
|
||||
indexOpsSearchHitsEntity.putMapping(indexOpsSearchHitsEntity.createMapping(SearchHitsEntity.class));
|
||||
indexOpsSearchHitsEntity.putMapping(SearchHitsEntity.class);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
@@ -152,13 +151,15 @@ public abstract class ElasticsearchTemplateTests {
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_3_NAME)).delete();
|
||||
operations.indexOps(SearchHitsEntity.class).delete();
|
||||
operations.indexOps(HighlightEntity.class).delete();
|
||||
operations.indexOps(OptimisticEntity.class).delete();
|
||||
operations.indexOps(OptimisticAndVersionedEntity.class).delete();
|
||||
}
|
||||
|
||||
@Test // DATAES-106
|
||||
public void shouldReturnCountForGivenCriteriaQuery() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
@@ -180,7 +181,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
public void shouldReturnCountForGivenSearchQuery() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
@@ -201,7 +202,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
public void shouldReturnObjectForGivenId() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
IndexQuery indexQuery = getIndexQuery(sampleEntity);
|
||||
@@ -219,12 +220,12 @@ public abstract class ElasticsearchTemplateTests {
|
||||
|
||||
// given
|
||||
// first document
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity1 = SampleEntity.builder().id(documentId).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
// second document
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = SampleEntity.builder().id(documentId2).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
@@ -248,12 +249,12 @@ public abstract class ElasticsearchTemplateTests {
|
||||
|
||||
// given
|
||||
// first document
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity1 = SampleEntity.builder().id(documentId).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
// second document
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = SampleEntity.builder().id(documentId2).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
@@ -263,7 +264,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
indexOperations.refresh();
|
||||
|
||||
// when
|
||||
List<String> idsToSearch = Arrays.asList(documentId, randomNumeric(5), documentId2);
|
||||
List<String> idsToSearch = Arrays.asList(documentId, nextIdAsString(), documentId2);
|
||||
assertThat(idsToSearch).hasSize(3);
|
||||
|
||||
NativeSearchQuery query = new NativeSearchQueryBuilder().withIds(idsToSearch).build();
|
||||
@@ -281,12 +282,12 @@ public abstract class ElasticsearchTemplateTests {
|
||||
|
||||
// given
|
||||
// first document
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity1 = SampleEntity.builder().id(documentId).message("some message").type("type1")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
// second document
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = SampleEntity.builder().id(documentId2).message("some message").type("type2")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
@@ -308,7 +309,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
public void shouldReturnSearchHitsForGivenSearchQuery() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
@@ -332,7 +333,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
public void shouldReturnSearchHitsUsingLocalPreferenceForGivenSearchQuery() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
@@ -356,7 +357,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
public void shouldThrowExceptionWhenInvalidPreferenceForSearchQuery() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
@@ -377,13 +378,13 @@ public abstract class ElasticsearchTemplateTests {
|
||||
public void shouldPassIndicesOptionsForGivenSearchQuery() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
IndexQuery idxQuery = new IndexQueryBuilder().withId(sampleEntity.getId()).withObject(sampleEntity).build();
|
||||
|
||||
operations.index(idxQuery, IndexCoordinates.of(INDEX_1_NAME).withTypes("test-type"));
|
||||
operations.index(idxQuery, IndexCoordinates.of(INDEX_1_NAME));
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_1_NAME)).refresh();
|
||||
|
||||
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
|
||||
@@ -405,12 +406,12 @@ public abstract class ElasticsearchTemplateTests {
|
||||
List<IndexQuery> indexQueries = new ArrayList<>();
|
||||
|
||||
// first document
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity1 = SampleEntity.builder().id(documentId).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
// second document
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = SampleEntity.builder().id(documentId2).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
@@ -431,7 +432,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
public void shouldDoBulkUpdate() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
String messageBeforeUpdate = "some test message";
|
||||
String messageAfterUpdate = "test message";
|
||||
|
||||
@@ -465,7 +466,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
public void shouldDeleteDocumentForGivenId() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
@@ -488,7 +489,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
public void shouldDeleteEntityForGivenId() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
@@ -510,7 +511,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
public void shouldDeleteDocumentForGivenQuery() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
@@ -539,19 +540,19 @@ public abstract class ElasticsearchTemplateTests {
|
||||
.version(System.currentTimeMillis()) //
|
||||
.build();
|
||||
|
||||
IndexQuery idxQuery1 = new IndexQueryBuilder().withId(randomNumeric(5)).withObject(sampleEntity).build();
|
||||
IndexQuery idxQuery1 = new IndexQueryBuilder().withId(nextIdAsString()).withObject(sampleEntity).build();
|
||||
|
||||
operations.index(idxQuery1, IndexCoordinates.of(INDEX_1_NAME).withTypes("test-type"));
|
||||
operations.index(idxQuery1, IndexCoordinates.of(INDEX_1_NAME));
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_1_NAME)).refresh();
|
||||
|
||||
IndexQuery idxQuery2 = new IndexQueryBuilder().withId(randomNumeric(5)).withObject(sampleEntity).build();
|
||||
IndexQuery idxQuery2 = new IndexQueryBuilder().withId(nextIdAsString()).withObject(sampleEntity).build();
|
||||
|
||||
operations.index(idxQuery2, IndexCoordinates.of(INDEX_2_NAME).withTypes("test-type"));
|
||||
operations.index(idxQuery2, IndexCoordinates.of(INDEX_2_NAME));
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_2_NAME)).refresh();
|
||||
|
||||
// when
|
||||
Query query = new NativeSearchQueryBuilder().withQuery(termQuery("message", "foo")).build();
|
||||
operations.delete(query, SampleEntity.class, IndexCoordinates.of("test-index-*").withTypes(TYPE_NAME));
|
||||
operations.delete(query, SampleEntity.class, IndexCoordinates.of("test-index-*"));
|
||||
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_1_NAME)).refresh();
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_2_NAME)).refresh();
|
||||
@@ -571,20 +572,20 @@ public abstract class ElasticsearchTemplateTests {
|
||||
.version(System.currentTimeMillis()) //
|
||||
.build();
|
||||
|
||||
IndexQuery idxQuery1 = new IndexQueryBuilder().withId(randomNumeric(5)).withObject(sampleEntity).build();
|
||||
IndexQuery idxQuery1 = new IndexQueryBuilder().withId(nextIdAsString()).withObject(sampleEntity).build();
|
||||
|
||||
operations.index(idxQuery1, IndexCoordinates.of(INDEX_1_NAME).withTypes("test-type"));
|
||||
operations.index(idxQuery1, IndexCoordinates.of(INDEX_1_NAME));
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_1_NAME)).refresh();
|
||||
|
||||
IndexQuery idxQuery2 = new IndexQueryBuilder().withId(randomNumeric(5)).withObject(sampleEntity).build();
|
||||
IndexQuery idxQuery2 = new IndexQueryBuilder().withId(nextIdAsString()).withObject(sampleEntity).build();
|
||||
|
||||
operations.index(idxQuery2, IndexCoordinates.of(INDEX_2_NAME).withTypes("test-type"));
|
||||
operations.index(idxQuery2, IndexCoordinates.of(INDEX_2_NAME));
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_2_NAME)).refresh();
|
||||
|
||||
// when
|
||||
Query query = new NativeSearchQueryBuilder().withQuery(termQuery("message", "negative")).build();
|
||||
|
||||
operations.delete(query, SampleEntity.class, IndexCoordinates.of("test-index-*").withTypes(TYPE_NAME));
|
||||
operations.delete(query, SampleEntity.class, IndexCoordinates.of("test-index-*"));
|
||||
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_1_NAME)).refresh();
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_2_NAME)).refresh();
|
||||
@@ -599,7 +600,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
public void shouldFilterSearchResultsForGivenFilter() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
@@ -623,17 +624,17 @@ public abstract class ElasticsearchTemplateTests {
|
||||
// given
|
||||
List<IndexQuery> indexQueries = new ArrayList<>();
|
||||
// first document
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity1 = SampleEntity.builder().id(documentId).message("abc").rate(10)
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
// second document
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = SampleEntity.builder().id(documentId2).message("xyz").rate(5)
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
// third document
|
||||
String documentId3 = randomNumeric(5);
|
||||
String documentId3 = nextIdAsString();
|
||||
SampleEntity sampleEntity3 = SampleEntity.builder().id(documentId3).message("xyz").rate(15)
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
@@ -659,17 +660,17 @@ public abstract class ElasticsearchTemplateTests {
|
||||
// given
|
||||
List<IndexQuery> indexQueries = new ArrayList<>();
|
||||
// first document
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity1 = SampleEntity.builder().id(documentId).message("abc").rate(10)
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
// second document
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = SampleEntity.builder().id(documentId2).message("xyz").rate(5)
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
// third document
|
||||
String documentId3 = randomNumeric(5);
|
||||
String documentId3 = nextIdAsString();
|
||||
SampleEntity sampleEntity3 = SampleEntity.builder().id(documentId3).message("xyz").rate(15)
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
@@ -698,17 +699,17 @@ public abstract class ElasticsearchTemplateTests {
|
||||
List<IndexQuery> indexQueries;
|
||||
|
||||
// first document
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity1 = SampleEntity.builder().id(documentId).message("abc").rate(15)
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
// second document
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = SampleEntity.builder().id(documentId2).message("xyz").rate(5)
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
// third document
|
||||
String documentId3 = randomNumeric(5);
|
||||
String documentId3 = nextIdAsString();
|
||||
SampleEntity sampleEntity3 = SampleEntity.builder().id(documentId3).rate(10).version(System.currentTimeMillis())
|
||||
.build();
|
||||
|
||||
@@ -736,17 +737,17 @@ public abstract class ElasticsearchTemplateTests {
|
||||
List<IndexQuery> indexQueries;
|
||||
|
||||
// first document
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity1 = SampleEntity.builder().id(documentId).message("abc").rate(15)
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
// second document
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = SampleEntity.builder().id(documentId2).message("xyz").rate(5)
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
// third document
|
||||
String documentId3 = randomNumeric(5);
|
||||
String documentId3 = nextIdAsString();
|
||||
SampleEntity sampleEntity3 = SampleEntity.builder().id(documentId3).rate(10).version(System.currentTimeMillis())
|
||||
.build();
|
||||
|
||||
@@ -797,7 +798,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
public void shouldExecuteStringQuery() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
@@ -819,7 +820,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
public void shouldUseScriptedFields() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setRate(2);
|
||||
@@ -851,7 +852,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
public void shouldReturnPageableResultsGivenStringQuery() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
@@ -873,7 +874,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
public void shouldReturnSortedResultsGivenStringQuery() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setMessage("some message");
|
||||
@@ -900,7 +901,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
public void shouldReturnObjectMatchingGivenStringQuery() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
@@ -935,7 +936,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
public void shouldExecuteGivenCriteriaQuery() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("test message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
@@ -956,7 +957,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
public void shouldDeleteGivenCriteriaQuery() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("test message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
@@ -981,7 +982,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
public void shouldReturnSpecifiedFields() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
String message = "some test message";
|
||||
String type = "some type";
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message(message).type(type)
|
||||
@@ -1010,7 +1011,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
public void shouldReturnFieldsBasedOnSourceFilter() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
String message = "some test message";
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message(message)
|
||||
.version(System.currentTimeMillis()).build();
|
||||
@@ -1045,7 +1046,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
+ "we want our search server to be always available, we want to be able to start with one machine and scale to hundreds, "
|
||||
+ "we want real-time search, we want simple multi-tenancy, and we want a solution that is built for the cloud.";
|
||||
|
||||
String documentId1 = randomNumeric(5);
|
||||
String documentId1 = nextIdAsString();
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(documentId1).message(sampleMessage)
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
@@ -1053,7 +1054,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
|
||||
operations.index(indexQuery, index);
|
||||
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
|
||||
operations.index(
|
||||
getIndexQuery(
|
||||
@@ -1350,17 +1351,17 @@ public abstract class ElasticsearchTemplateTests {
|
||||
// given
|
||||
List<IndexQuery> indexQueries = new ArrayList<>();
|
||||
// first document
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity1 = SampleEntity.builder().id(documentId).message("test message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
// second document
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = SampleEntity.builder().id(documentId2).message("test test").rate(5)
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
// third document
|
||||
String documentId3 = randomNumeric(5);
|
||||
String documentId3 = nextIdAsString();
|
||||
SampleEntity sampleEntity3 = SampleEntity.builder().id(documentId3).message("some message").rate(15)
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
@@ -1387,17 +1388,17 @@ public abstract class ElasticsearchTemplateTests {
|
||||
|
||||
// given
|
||||
// first document
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity1 = SampleEntity.builder().id(documentId).message("test message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
// second document
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = SampleEntity.builder().id(documentId2).message("test test").rate(5)
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
// third document
|
||||
String documentId3 = randomNumeric(5);
|
||||
String documentId3 = nextIdAsString();
|
||||
SampleEntity sampleEntity3 = SampleEntity.builder().id(documentId3).message("some message").rate(15)
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
@@ -1425,7 +1426,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
// when
|
||||
|
||||
// then
|
||||
assertThat(indexOperations.putMapping(indexOperations.createMapping(entityClass))).isTrue();
|
||||
assertThat(indexOperations.putMapping(entityClass)).isTrue();
|
||||
}
|
||||
|
||||
@Test // DATAES-305
|
||||
@@ -1438,7 +1439,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
indexOperations1.create();
|
||||
|
||||
// when
|
||||
indexOperations1.putMapping(indexOperations1.createMapping(entity));
|
||||
indexOperations1.putMapping(entity);
|
||||
|
||||
// then
|
||||
Map<String, Object> mapping = indexOperations.getMapping();
|
||||
@@ -1462,7 +1463,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
public void shouldDoPartialUpdateForExistingDocument() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
String messageBeforeUpdate = "some test message";
|
||||
String messageAfterUpdate = "test message";
|
||||
|
||||
@@ -1540,7 +1541,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
public void shouldDoUpsertIfDocumentDoesNotExist() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
org.springframework.data.elasticsearch.core.document.Document document = org.springframework.data.elasticsearch.core.document.Document
|
||||
.create();
|
||||
document.put("message", "test message");
|
||||
@@ -1562,13 +1563,13 @@ public abstract class ElasticsearchTemplateTests {
|
||||
|
||||
// given
|
||||
long scrollTimeInMillis = 3000;
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
IndexQuery idxQuery = new IndexQueryBuilder().withId(sampleEntity.getId()).withObject(sampleEntity).build();
|
||||
|
||||
IndexCoordinates index = IndexCoordinates.of(INDEX_1_NAME).withTypes("test-type");
|
||||
IndexCoordinates index = IndexCoordinates.of(INDEX_1_NAME);
|
||||
operations.index(idxQuery, index);
|
||||
operations.indexOps(index).refresh();
|
||||
|
||||
@@ -1628,10 +1629,10 @@ public abstract class ElasticsearchTemplateTests {
|
||||
IndexOperations bookIndexOperations = operations.indexOps(Book.class);
|
||||
bookIndexOperations.delete();
|
||||
bookIndexOperations.create();
|
||||
indexOperations.putMapping(indexOperations.createMapping(clazz));
|
||||
indexOperations.putMapping(clazz);
|
||||
bookIndexOperations.refresh();
|
||||
|
||||
IndexCoordinates bookIndex = IndexCoordinates.of("test-index-book-core-template").withTypes("book");
|
||||
IndexCoordinates bookIndex = IndexCoordinates.of("test-index-book-core-template");
|
||||
|
||||
operations.index(buildIndex(SampleEntity.builder().id("1").message("ab").build()), index);
|
||||
operations.index(buildIndex(Book.builder().id("2").description("bc").build()), bookIndex);
|
||||
@@ -1661,7 +1662,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
public void shouldDeleteDocumentBySpecifiedTypeUsingDeleteQuery() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
@@ -1691,7 +1692,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
indexQuery.setSource(documentSource);
|
||||
|
||||
// when
|
||||
operations.index(indexQuery, IndexCoordinates.of(INDEX_NAME_SAMPLE_ENTITY).withTypes(TYPE_NAME));
|
||||
operations.index(indexQuery, IndexCoordinates.of(INDEX_NAME_SAMPLE_ENTITY));
|
||||
indexOperations.refresh();
|
||||
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(termQuery("id", indexQuery.getId()))
|
||||
.build();
|
||||
@@ -1711,9 +1712,8 @@ public abstract class ElasticsearchTemplateTests {
|
||||
indexQuery.setId("2333343434");
|
||||
|
||||
// when
|
||||
assertThatThrownBy(
|
||||
() -> operations.index(indexQuery, IndexCoordinates.of(INDEX_NAME_SAMPLE_ENTITY).withTypes(TYPE_NAME)))
|
||||
.isInstanceOf(ElasticsearchException.class);
|
||||
assertThatThrownBy(() -> operations.index(indexQuery, IndexCoordinates.of(INDEX_NAME_SAMPLE_ENTITY)))
|
||||
.isInstanceOf(ElasticsearchException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1730,6 +1730,23 @@ public abstract class ElasticsearchTemplateTests {
|
||||
assertThat(ids).hasSize(30);
|
||||
}
|
||||
|
||||
@Test // DATAES-848
|
||||
public void shouldReturnIndexName() {
|
||||
// given
|
||||
List<IndexQuery> entities = createSampleEntitiesWithMessage("Test message", 3);
|
||||
// when
|
||||
operations.bulkIndex(entities, index);
|
||||
indexOperations.refresh();
|
||||
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(termQuery("message", "message"))
|
||||
.withPageable(PageRequest.of(0, 100)).build();
|
||||
// then
|
||||
SearchHits<SampleEntity> searchHits = operations.search(searchQuery, SampleEntity.class);
|
||||
|
||||
searchHits.forEach(searchHit -> {
|
||||
assertThat(searchHit.getIndex()).isEqualTo(INDEX_NAME_SAMPLE_ENTITY);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnDocumentAboveMinimalScoreGivenQuery() {
|
||||
// given
|
||||
@@ -1884,7 +1901,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
public void shouldIndexGteEntityWithVersionType() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
GTEVersionEntity entity = GTEVersionEntity.builder().id(documentId).name("FooBar")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
@@ -1914,13 +1931,13 @@ public abstract class ElasticsearchTemplateTests {
|
||||
public void shouldIndexSampleEntityWithIndexAndTypeAtRuntime() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
IndexQuery indexQuery = new IndexQueryBuilder().withId(documentId).withObject(sampleEntity).build();
|
||||
|
||||
operations.index(indexQuery, IndexCoordinates.of(INDEX_NAME_SAMPLE_ENTITY).withTypes(TYPE_NAME));
|
||||
operations.index(indexQuery, IndexCoordinates.of(INDEX_NAME_SAMPLE_ENTITY));
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_NAME_SAMPLE_ENTITY)).refresh();
|
||||
|
||||
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build();
|
||||
@@ -1937,7 +1954,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
public void shouldReturnCountForGivenCriteriaQueryWithGivenIndexUsingCriteriaQuery() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
@@ -1957,7 +1974,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
public void shouldReturnCountForGivenSearchQueryWithGivenIndexUsingSearchQuery() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
@@ -1977,7 +1994,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
public void shouldReturnCountForGivenCriteriaQueryWithGivenIndexAndTypeUsingCriteriaQuery() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
@@ -1997,7 +2014,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
public void shouldReturnCountForGivenSearchQueryWithGivenIndexAndTypeUsingSearchQuery() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
@@ -2018,20 +2035,20 @@ public abstract class ElasticsearchTemplateTests {
|
||||
|
||||
// given
|
||||
cleanUpIndices();
|
||||
String documentId1 = randomNumeric(5);
|
||||
String documentId1 = nextIdAsString();
|
||||
SampleEntity sampleEntity1 = SampleEntity.builder().id(documentId1).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
IndexQuery indexQuery1 = new IndexQueryBuilder().withId(sampleEntity1.getId()).withObject(sampleEntity1).build();
|
||||
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = SampleEntity.builder().id(documentId2).message("some test message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
IndexQuery indexQuery2 = new IndexQueryBuilder().withId(sampleEntity2.getId()).withObject(sampleEntity2).build();
|
||||
|
||||
operations.index(indexQuery1, IndexCoordinates.of(INDEX_1_NAME).withTypes("test-type"));
|
||||
operations.index(indexQuery2, IndexCoordinates.of(INDEX_2_NAME).withTypes("test-type"));
|
||||
operations.index(indexQuery1, IndexCoordinates.of(INDEX_1_NAME));
|
||||
operations.index(indexQuery2, IndexCoordinates.of(INDEX_2_NAME));
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_1_NAME)).refresh();
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_2_NAME)).refresh();
|
||||
|
||||
@@ -2049,20 +2066,20 @@ public abstract class ElasticsearchTemplateTests {
|
||||
|
||||
// given
|
||||
cleanUpIndices();
|
||||
String documentId1 = randomNumeric(5);
|
||||
String documentId1 = nextIdAsString();
|
||||
SampleEntity sampleEntity1 = SampleEntity.builder().id(documentId1).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
IndexQuery indexQuery1 = new IndexQueryBuilder().withId(sampleEntity1.getId()).withObject(sampleEntity1).build();
|
||||
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = SampleEntity.builder().id(documentId2).message("some test message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
IndexQuery indexQuery2 = new IndexQueryBuilder().withId(sampleEntity2.getId()).withObject(sampleEntity2).build();
|
||||
|
||||
operations.index(indexQuery1, IndexCoordinates.of(INDEX_1_NAME).withTypes("test-type"));
|
||||
operations.index(indexQuery2, IndexCoordinates.of(INDEX_2_NAME).withTypes("test-type"));
|
||||
operations.index(indexQuery1, IndexCoordinates.of(INDEX_1_NAME));
|
||||
operations.index(indexQuery2, IndexCoordinates.of(INDEX_2_NAME));
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_1_NAME)).refresh();
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_2_NAME)).refresh();
|
||||
|
||||
@@ -2119,20 +2136,20 @@ public abstract class ElasticsearchTemplateTests {
|
||||
|
||||
// given
|
||||
cleanUpIndices();
|
||||
String documentId1 = randomNumeric(5);
|
||||
String documentId1 = nextIdAsString();
|
||||
SampleEntity sampleEntity1 = SampleEntity.builder().id(documentId1).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
IndexQuery indexQuery1 = new IndexQueryBuilder().withId(sampleEntity1.getId()).withObject(sampleEntity1).build();
|
||||
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = SampleEntity.builder().id(documentId2).message("some test message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
IndexQuery indexQuery2 = new IndexQueryBuilder().withId(sampleEntity2.getId()).withObject(sampleEntity2).build();
|
||||
|
||||
operations.index(indexQuery1, IndexCoordinates.of(INDEX_1_NAME).withTypes("test-type"));
|
||||
operations.index(indexQuery2, IndexCoordinates.of(INDEX_2_NAME).withTypes("test-type"));
|
||||
operations.index(indexQuery1, IndexCoordinates.of(INDEX_1_NAME));
|
||||
operations.index(indexQuery2, IndexCoordinates.of(INDEX_2_NAME));
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_1_NAME)).refresh();
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_2_NAME)).refresh();
|
||||
|
||||
@@ -2150,20 +2167,20 @@ public abstract class ElasticsearchTemplateTests {
|
||||
|
||||
// given
|
||||
cleanUpIndices();
|
||||
String documentId1 = randomNumeric(5);
|
||||
String documentId1 = nextIdAsString();
|
||||
SampleEntity sampleEntity1 = SampleEntity.builder().id(documentId1).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
IndexQuery indexQuery1 = new IndexQueryBuilder().withId(sampleEntity1.getId()).withObject(sampleEntity1).build();
|
||||
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = SampleEntity.builder().id(documentId2).message("some test message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
IndexQuery indexQuery2 = new IndexQueryBuilder().withId(sampleEntity2.getId()).withObject(sampleEntity2).build();
|
||||
|
||||
operations.index(indexQuery1, IndexCoordinates.of(INDEX_1_NAME).withTypes("test-type"));
|
||||
operations.index(indexQuery2, IndexCoordinates.of(INDEX_2_NAME).withTypes("test-type"));
|
||||
operations.index(indexQuery1, IndexCoordinates.of(INDEX_1_NAME));
|
||||
operations.index(indexQuery2, IndexCoordinates.of(INDEX_2_NAME));
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_1_NAME)).refresh();
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_2_NAME)).refresh();
|
||||
|
||||
@@ -2180,7 +2197,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
public void shouldThrowAnExceptionForGivenCriteriaQueryWhenNoIndexSpecifiedForCountQuery() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
@@ -2198,7 +2215,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
public void shouldThrowAnExceptionForGivenSearchQueryWhenNoIndexSpecifiedForCountQuery() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
@@ -2269,7 +2286,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
// when
|
||||
indexOperations.delete();
|
||||
indexOperations.create(parse(settings));
|
||||
indexOperations.putMapping(indexOperations.createMapping(SampleEntity.class));
|
||||
indexOperations.putMapping(SampleEntity.class);
|
||||
indexOperations.refresh();
|
||||
|
||||
// then
|
||||
@@ -2285,20 +2302,20 @@ public abstract class ElasticsearchTemplateTests {
|
||||
public void shouldTestResultsAcrossMultipleIndices() {
|
||||
|
||||
// given
|
||||
String documentId1 = randomNumeric(5);
|
||||
String documentId1 = nextIdAsString();
|
||||
SampleEntity sampleEntity1 = SampleEntity.builder().id(documentId1).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
IndexQuery indexQuery1 = new IndexQueryBuilder().withId(sampleEntity1.getId()).withObject(sampleEntity1).build();
|
||||
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = SampleEntity.builder().id(documentId2).message("some test message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
IndexQuery indexQuery2 = new IndexQueryBuilder().withId(sampleEntity2.getId()).withObject(sampleEntity2).build();
|
||||
|
||||
operations.index(indexQuery1, IndexCoordinates.of(INDEX_1_NAME).withTypes("test-type"));
|
||||
operations.index(indexQuery2, IndexCoordinates.of(INDEX_2_NAME).withTypes("test-type"));
|
||||
operations.index(indexQuery1, IndexCoordinates.of(INDEX_1_NAME));
|
||||
operations.index(indexQuery2, IndexCoordinates.of(INDEX_2_NAME));
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_1_NAME)).refresh();
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_2_NAME)).refresh();
|
||||
|
||||
@@ -2319,14 +2336,14 @@ public abstract class ElasticsearchTemplateTests {
|
||||
public void shouldComposeObjectsReturnedFromHeterogeneousIndexes() {
|
||||
|
||||
// given
|
||||
HetroEntity1 entity1 = new HetroEntity1(randomNumeric(3), "aFirstName");
|
||||
HetroEntity2 entity2 = new HetroEntity2(randomNumeric(4), "aLastName");
|
||||
HetroEntity1 entity1 = new HetroEntity1(nextIdAsString(), "aFirstName");
|
||||
HetroEntity2 entity2 = new HetroEntity2(nextIdAsString(), "aLastName");
|
||||
|
||||
IndexQuery indexQuery1 = new IndexQueryBuilder().withId(entity1.getId()).withObject(entity1).build();
|
||||
IndexQuery indexQuery2 = new IndexQueryBuilder().withId(entity2.getId()).withObject(entity2).build();
|
||||
|
||||
operations.index(indexQuery1, IndexCoordinates.of(INDEX_1_NAME).withTypes("hetro"));
|
||||
operations.index(indexQuery2, IndexCoordinates.of(INDEX_2_NAME).withTypes("hetro"));
|
||||
operations.index(indexQuery1, IndexCoordinates.of(INDEX_1_NAME));
|
||||
operations.index(indexQuery2, IndexCoordinates.of(INDEX_2_NAME));
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_1_NAME)).refresh();
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_2_NAME)).refresh();
|
||||
|
||||
@@ -2571,17 +2588,17 @@ public abstract class ElasticsearchTemplateTests {
|
||||
|
||||
// given
|
||||
// first document
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity1 = SampleEntity.builder().id(documentId).message("abc").rate(10)
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
// second document
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = SampleEntity.builder().id(documentId2).message("xyz").rate(5)
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
// third document
|
||||
String documentId3 = randomNumeric(5);
|
||||
String documentId3 = nextIdAsString();
|
||||
SampleEntity sampleEntity3 = SampleEntity.builder().id(documentId3).message("xyz").rate(10)
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
@@ -2618,17 +2635,17 @@ public abstract class ElasticsearchTemplateTests {
|
||||
|
||||
// given
|
||||
// first document
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity1 = SampleEntity.builder().id(documentId).message("abc").rate(10)
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
// second document
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = SampleEntity.builder().id(documentId2).message("xyz").rate(5)
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
// third document
|
||||
String documentId3 = randomNumeric(5);
|
||||
String documentId3 = nextIdAsString();
|
||||
SampleEntity sampleEntity3 = SampleEntity.builder().id(documentId3).message("xyz").rate(10)
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
@@ -2665,11 +2682,11 @@ public abstract class ElasticsearchTemplateTests {
|
||||
public void shouldReturnDocumentWithCollapsedField() {
|
||||
|
||||
// given
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(randomNumeric(5)).message("message 1").rate(1)
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(nextIdAsString()).message("message 1").rate(1)
|
||||
.version(System.currentTimeMillis()).build();
|
||||
SampleEntity sampleEntity2 = SampleEntity.builder().id(randomNumeric(5)).message("message 2").rate(2)
|
||||
SampleEntity sampleEntity2 = SampleEntity.builder().id(nextIdAsString()).message("message 2").rate(2)
|
||||
.version(System.currentTimeMillis()).build();
|
||||
SampleEntity sampleEntity3 = SampleEntity.builder().id(randomNumeric(5)).message("message 1").rate(1)
|
||||
SampleEntity sampleEntity3 = SampleEntity.builder().id(nextIdAsString()).message("message 1").rate(1)
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
List<IndexQuery> indexQueries = getIndexQueries(Arrays.asList(sampleEntity, sampleEntity2, sampleEntity3));
|
||||
@@ -2744,7 +2761,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
indexOperations.addAlias(aliasQuery1);
|
||||
indexOperations.addAlias(aliasQuery2);
|
||||
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity entity = SampleEntity.builder() //
|
||||
.id(documentId) //
|
||||
.message("some message") //
|
||||
@@ -2756,7 +2773,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
.withObject(entity) //
|
||||
.build();
|
||||
|
||||
operations.index(indexQuery, IndexCoordinates.of(alias1).withTypes(TYPE_NAME));
|
||||
operations.index(indexQuery, IndexCoordinates.of(alias1));
|
||||
|
||||
// then
|
||||
List<AliasMetaData> aliasMetaData = indexOperations.queryForAlias();
|
||||
@@ -2764,13 +2781,23 @@ public abstract class ElasticsearchTemplateTests {
|
||||
|
||||
AliasMetaData aliasMetaData1 = aliasMetaData.get(0);
|
||||
assertThat(aliasMetaData1).isNotNull();
|
||||
assertThat(aliasMetaData1.alias()).isEqualTo(alias1);
|
||||
assertThat(aliasMetaData1.indexRouting()).isEqualTo("0");
|
||||
if (aliasMetaData1.alias().equals(alias1)) {
|
||||
assertThat(aliasMetaData1.indexRouting()).isEqualTo("0");
|
||||
} else if (aliasMetaData1.alias().equals(alias2)) {
|
||||
assertThat(aliasMetaData1.searchRouting()).isEqualTo("1");
|
||||
} else {
|
||||
fail("unknown alias");
|
||||
}
|
||||
|
||||
AliasMetaData aliasMetaData2 = aliasMetaData.get(1);
|
||||
assertThat(aliasMetaData2).isNotNull();
|
||||
assertThat(aliasMetaData2.alias()).isEqualTo(alias2);
|
||||
assertThat(aliasMetaData2.searchRouting()).isEqualTo("1");
|
||||
if (aliasMetaData2.alias().equals(alias1)) {
|
||||
assertThat(aliasMetaData2.indexRouting()).isEqualTo("0");
|
||||
} else if (aliasMetaData2.alias().equals(alias2)) {
|
||||
assertThat(aliasMetaData2.searchRouting()).isEqualTo("1");
|
||||
} else {
|
||||
fail("unknown alias");
|
||||
}
|
||||
|
||||
// cleanup
|
||||
indexOperations.removeAlias(aliasQuery1);
|
||||
@@ -2792,7 +2819,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
// when
|
||||
indexOperations.addAlias(aliasQuery);
|
||||
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = SampleEntity.builder() //
|
||||
.id(documentId) //
|
||||
.message("some message") //
|
||||
@@ -2804,7 +2831,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
.withObject(sampleEntity) //
|
||||
.build();
|
||||
|
||||
operations.index(indexQuery, IndexCoordinates.of(alias).withTypes(TYPE_NAME));
|
||||
operations.index(indexQuery, IndexCoordinates.of(alias));
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_NAME_SAMPLE_ENTITY)).refresh();
|
||||
|
||||
NativeSearchQuery query = new NativeSearchQueryBuilder() //
|
||||
|
||||
+2
-2
@@ -15,9 +15,9 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.core;
|
||||
|
||||
import static org.apache.commons.lang.RandomStringUtils.*;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.springframework.data.elasticsearch.annotations.FieldType.*;
|
||||
import static org.springframework.data.elasticsearch.utils.IdGenerator.*;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.val;
|
||||
@@ -65,7 +65,7 @@ public class ElasticsearchTransportTemplateTests extends ElasticsearchTemplateTe
|
||||
// when
|
||||
org.springframework.data.elasticsearch.core.document.Document document = org.springframework.data.elasticsearch.core.document.Document
|
||||
.create();
|
||||
UpdateQuery updateQuery = UpdateQuery.builder(randomNumeric(5)).withDocument(document).build();
|
||||
UpdateQuery updateQuery = UpdateQuery.builder(nextIdAsString()).withDocument(document).build();
|
||||
assertThatThrownBy(() -> operations.update(updateQuery, index)).isInstanceOf(DocumentMissingException.class);
|
||||
}
|
||||
|
||||
|
||||
@@ -39,11 +39,4 @@ class IndexCoordinatesTest {
|
||||
void cannotBeInitializedWithEmptyIndexNames() {
|
||||
assertThatThrownBy(() -> IndexCoordinates.of(new String[] {})).isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldHaveEmptyTypesWhenNotSet() {
|
||||
IndexCoordinates indexCoordinates = IndexCoordinates.of("test");
|
||||
|
||||
assertThat(indexCoordinates.getTypeNames()).isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright 2020 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;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.*;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.lucene.search.join.ScoreMode;
|
||||
import org.assertj.core.api.SoftAssertions;
|
||||
import org.elasticsearch.index.query.InnerHitBuilder;
|
||||
import org.elasticsearch.index.query.NestedQueryBuilder;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.annotation.Id;
|
||||
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.core.document.NestedMetaData;
|
||||
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.ElasticsearchRestTemplateConfiguration;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.SpringIntegrationTest;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
/**
|
||||
* Testing the querying and parsing of inner_hits.
|
||||
*
|
||||
* @author Peter-Josef Meisch
|
||||
*/
|
||||
@SpringIntegrationTest
|
||||
@ContextConfiguration(classes = { InnerHitsTests.Config.class })
|
||||
public class InnerHitsTests {
|
||||
|
||||
public static final String INDEX_NAME = "tests-inner-hits";
|
||||
|
||||
@Configuration
|
||||
@Import({ ElasticsearchRestTemplateConfiguration.class })
|
||||
static class Config {}
|
||||
|
||||
@Autowired ElasticsearchOperations operations;
|
||||
@Nullable IndexOperations indexOps;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
indexOps = operations.indexOps(City.class);
|
||||
indexOps.create();
|
||||
indexOps.putMapping(City.class);
|
||||
|
||||
Inhabitant john = new Inhabitant("John", "Smith");
|
||||
Inhabitant carla = new Inhabitant("Carla", "Miller");
|
||||
House cornerHouse = new House("Round the corner", "7", Arrays.asList(john, carla));
|
||||
City metropole = new City("Metropole", Arrays.asList(cornerHouse));
|
||||
|
||||
Inhabitant jack = new Inhabitant("Jack", "Wayne");
|
||||
Inhabitant emmy = new Inhabitant("Emmy", "Stone");
|
||||
House mainStreet = new House("Main Street", "42", Arrays.asList(jack, emmy));
|
||||
City village = new City("Village", Arrays.asList(mainStreet));
|
||||
|
||||
operations.save(Arrays.asList(metropole, village));
|
||||
indexOps.refresh();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
indexOps.delete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnInnerHits() {
|
||||
String innerHitName = "inner_hit_name";
|
||||
|
||||
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
|
||||
|
||||
NestedQueryBuilder nestedQueryBuilder = nestedQuery("hou-ses.in-habi-tants",
|
||||
matchQuery("hou-ses.in-habi-tants.first-name", "Carla"), ScoreMode.Avg);
|
||||
nestedQueryBuilder.innerHit(new InnerHitBuilder(innerHitName));
|
||||
queryBuilder.withQuery(nestedQueryBuilder);
|
||||
|
||||
NativeSearchQuery query = queryBuilder.build();
|
||||
|
||||
SoftAssertions softly = new SoftAssertions();
|
||||
SearchHits<City> searchHits = operations.search(query, City.class);
|
||||
|
||||
softly.assertThat(searchHits.getTotalHits()).isEqualTo(1);
|
||||
|
||||
SearchHit<City> searchHit = searchHits.getSearchHit(0);
|
||||
softly.assertThat(searchHit.getInnerHits()).hasSize(1);
|
||||
|
||||
SearchHits<?> innerHits = searchHit.getInnerHits(innerHitName);
|
||||
softly.assertThat(innerHits).hasSize(1);
|
||||
|
||||
SearchHit<?> innerHit = innerHits.getSearchHit(0);
|
||||
Object content = innerHit.getContent();
|
||||
assertThat(content).isInstanceOf(Inhabitant.class);
|
||||
Inhabitant inhabitant = (Inhabitant) content;
|
||||
softly.assertThat(inhabitant.getFirstName()).isEqualTo("Carla");
|
||||
softly.assertThat(inhabitant.getLastName()).isEqualTo("Miller");
|
||||
|
||||
NestedMetaData nestedMetaData = innerHit.getNestedMetaData();
|
||||
softly.assertThat(nestedMetaData.getField()).isEqualTo("houses");
|
||||
softly.assertThat(nestedMetaData.getOffset()).isEqualTo(0);
|
||||
softly.assertThat(nestedMetaData.getChild().getField()).isEqualTo("inhabitants");
|
||||
softly.assertThat(nestedMetaData.getChild().getOffset()).isEqualTo(1);
|
||||
|
||||
softly.assertAll();
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@RequiredArgsConstructor
|
||||
@Document(indexName = INDEX_NAME)
|
||||
static class City {
|
||||
|
||||
@Id private String name;
|
||||
|
||||
// NOTE: using a custom names here to cover property name matching
|
||||
@Field(name = "hou-ses", type = FieldType.Nested) private Collection<House> houses = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@RequiredArgsConstructor
|
||||
static class House {
|
||||
|
||||
@Field(type = FieldType.Text) private String street;
|
||||
|
||||
@Field(type = FieldType.Text) private String streetNumber;
|
||||
|
||||
// NOTE: using a custom names here to cover property name matching
|
||||
@Field(name = "in-habi-tants", type = FieldType.Nested) private List<Inhabitant> inhabitants = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@RequiredArgsConstructor
|
||||
static class Inhabitant {
|
||||
// NOTE: using a custom names here to cover property name matching
|
||||
|
||||
@Field(name = "first-name", type = FieldType.Text) private String firstName;
|
||||
|
||||
@Field(name = "last-name", type = FieldType.Text) private String lastName;
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2020 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;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.ElasticsearchTemplateConfiguration;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
/**
|
||||
* @author Peter-Josef Meisch
|
||||
*/
|
||||
@ContextConfiguration(classes = { InnerHitsTransportTests.Config.class })
|
||||
public class InnerHitsTransportTests extends InnerHitsTests {
|
||||
@Configuration
|
||||
@Import({ ElasticsearchTemplateConfiguration.class })
|
||||
static class Config {}
|
||||
}
|
||||
@@ -61,7 +61,7 @@ public class LogEntityTests {
|
||||
@Import({ ElasticsearchRestTemplateConfiguration.class })
|
||||
static class Config {}
|
||||
|
||||
private final IndexCoordinates index = IndexCoordinates.of("test-index-log-core").withTypes("test-log-type");
|
||||
private final IndexCoordinates index = IndexCoordinates.of("test-index-log-core");
|
||||
@Autowired private ElasticsearchOperations operations;
|
||||
private IndexOperations indexOperations;
|
||||
|
||||
|
||||
+13
-12
@@ -49,7 +49,6 @@ import org.elasticsearch.search.sort.SortOrder;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.dao.OptimisticLockingFailureException;
|
||||
import org.springframework.data.annotation.Id;
|
||||
@@ -108,7 +107,7 @@ public class ReactiveElasticsearchTemplateTests {
|
||||
deleteIndices();
|
||||
|
||||
indexOperations.create();
|
||||
indexOperations.putMapping(indexOperations.createMapping(SampleEntity.class));
|
||||
indexOperations.putMapping(SampleEntity.class);
|
||||
indexOperations.refresh();
|
||||
|
||||
template = new ReactiveElasticsearchTemplate(TestUtils.reactiveClient(), restTemplate.getElasticsearchConverter());
|
||||
@@ -120,7 +119,9 @@ public class ReactiveElasticsearchTemplateTests {
|
||||
}
|
||||
|
||||
private void deleteIndices() {
|
||||
TestUtils.deleteIndex(DEFAULT_INDEX, ALTERNATE_INDEX, "rx-template-test-index-this", "rx-template-test-index-that");
|
||||
TestUtils.deleteIndex(DEFAULT_INDEX, ALTERNATE_INDEX, "rx-template-test-index-this", "rx-template-test-index-that",
|
||||
"test-index-reactive-optimistic-entity-template",
|
||||
"test-index-reactive-optimistic-and-versioned-entity-template");
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
@@ -201,7 +202,7 @@ public class ReactiveElasticsearchTemplateTests {
|
||||
|
||||
Map<String, Object> map = new LinkedHashMap<>(Collections.singletonMap("foo", "bar"));
|
||||
|
||||
template.save(map, IndexCoordinates.of(ALTERNATE_INDEX).withTypes("singleton-map")) //
|
||||
template.save(map, IndexCoordinates.of(ALTERNATE_INDEX)) //
|
||||
.as(StepVerifier::create) //
|
||||
.consumeNextWith(actual -> {
|
||||
assertThat(map).containsKey("id");
|
||||
@@ -218,7 +219,7 @@ public class ReactiveElasticsearchTemplateTests {
|
||||
@Test // DATAES-519, DATAES-767, DATAES-822
|
||||
public void getByIdShouldErrorWhenIndexDoesNotExist() {
|
||||
|
||||
template.get("foo", SampleEntity.class, IndexCoordinates.of("no-such-index").withTypes("test-type")) //
|
||||
template.get("foo", SampleEntity.class, IndexCoordinates.of("no-such-index")) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectError(ElasticsearchStatusException.class);
|
||||
}
|
||||
@@ -276,8 +277,8 @@ public class ReactiveElasticsearchTemplateTests {
|
||||
|
||||
IndexQuery indexQuery = getIndexQuery(sampleEntity);
|
||||
|
||||
IndexCoordinates defaultIndex = IndexCoordinates.of(DEFAULT_INDEX).withTypes("test-type");
|
||||
IndexCoordinates alternateIndex = IndexCoordinates.of(ALTERNATE_INDEX).withTypes("test-type");
|
||||
IndexCoordinates defaultIndex = IndexCoordinates.of(DEFAULT_INDEX);
|
||||
IndexCoordinates alternateIndex = IndexCoordinates.of(ALTERNATE_INDEX);
|
||||
|
||||
restTemplate.index(indexQuery, alternateIndex);
|
||||
indexOperations.refresh();
|
||||
@@ -524,7 +525,8 @@ public class ReactiveElasticsearchTemplateTests {
|
||||
|
||||
@Test // DATAES-567, DATAES-767
|
||||
public void aggregateShouldErrorWhenIndexDoesNotExist() {
|
||||
template.aggregate(new CriteriaQuery(Criteria.where("message").is("some message")), SampleEntity.class,
|
||||
template
|
||||
.aggregate(new CriteriaQuery(Criteria.where("message").is("some message")), SampleEntity.class,
|
||||
IndexCoordinates.of("no-such-index")) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectError(ElasticsearchStatusException.class);
|
||||
@@ -588,7 +590,7 @@ public class ReactiveElasticsearchTemplateTests {
|
||||
SampleEntity sampleEntity = randomEntity("test message");
|
||||
index(sampleEntity);
|
||||
|
||||
template.delete(sampleEntity.getId(), IndexCoordinates.of(DEFAULT_INDEX).withTypes("test-type")) //
|
||||
template.delete(sampleEntity.getId(), IndexCoordinates.of(DEFAULT_INDEX)) //
|
||||
.as(StepVerifier::create)//
|
||||
.expectNext(sampleEntity.getId()) //
|
||||
.verifyComplete();
|
||||
@@ -845,6 +847,7 @@ public class ReactiveElasticsearchTemplateTests {
|
||||
.expectNext(entity1) //
|
||||
.expectNext(entity2) //
|
||||
.verifyComplete();
|
||||
indexOperations.refresh();
|
||||
|
||||
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build();
|
||||
template.search(searchQuery, SampleEntity.class, IndexCoordinates.of(DEFAULT_INDEX)) //
|
||||
@@ -977,8 +980,6 @@ public class ReactiveElasticsearchTemplateTests {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: check field mapping !!!
|
||||
|
||||
// --> JUST some helpers
|
||||
|
||||
private SampleEntity randomEntity(String message) {
|
||||
@@ -1001,7 +1002,7 @@ public class ReactiveElasticsearchTemplateTests {
|
||||
|
||||
private void index(SampleEntity... entities) {
|
||||
|
||||
IndexCoordinates indexCoordinates = IndexCoordinates.of(DEFAULT_INDEX).withTypes("test-type");
|
||||
IndexCoordinates indexCoordinates = IndexCoordinates.of(DEFAULT_INDEX);
|
||||
|
||||
if (entities.length == 1) {
|
||||
restTemplate.index(getIndexQuery(entities[0]), indexCoordinates);
|
||||
|
||||
+3
-4
@@ -24,7 +24,6 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
@@ -56,6 +55,7 @@ import org.springframework.data.elasticsearch.annotations.Field;
|
||||
import org.springframework.data.elasticsearch.annotations.ScriptedField;
|
||||
import org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient;
|
||||
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
|
||||
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.Query;
|
||||
@@ -71,7 +71,7 @@ public class ReactiveElasticsearchTemplateUnitTests {
|
||||
@Mock ReactiveElasticsearchClient client;
|
||||
ReactiveElasticsearchTemplate template;
|
||||
|
||||
private IndexCoordinates index = IndexCoordinates.of("index").withTypes("type");
|
||||
private IndexCoordinates index = IndexCoordinates.of("index");
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
@@ -258,8 +258,7 @@ public class ReactiveElasticsearchTemplateUnitTests {
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
@Document(indexName = "test-index-sample-core-reactive-template-Unit", replicas = 0,
|
||||
refreshInterval = "-1")
|
||||
@Document(indexName = "test-index-sample-core-reactive-template-Unit", replicas = 0, refreshInterval = "-1")
|
||||
static class SampleEntity {
|
||||
|
||||
@Id private String id;
|
||||
|
||||
+358
@@ -0,0 +1,358 @@
|
||||
/*
|
||||
* Copyright 2018-2020 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;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.skyscreamer.jsonassert.JSONAssert.*;
|
||||
|
||||
import lombok.Data;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.skyscreamer.jsonassert.JSONCompareMode;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.annotation.Id;
|
||||
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.annotations.Setting;
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.ElasticsearchRestTemplateConfiguration;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.ReactiveElasticsearchRestTemplateConfiguration;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.SpringIntegrationTest;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
/**
|
||||
* @author Peter-Josef Meisch
|
||||
*/
|
||||
@SpringIntegrationTest
|
||||
@ContextConfiguration(classes = { ReactiveIndexOperationsTest.Config.class })
|
||||
public class ReactiveIndexOperationsTest {
|
||||
|
||||
public static final String TESTINDEX = "reactive-index-operations-testindex";
|
||||
|
||||
@Configuration
|
||||
@Import({ ReactiveElasticsearchRestTemplateConfiguration.class, ElasticsearchRestTemplateConfiguration.class })
|
||||
static class Config {}
|
||||
|
||||
@Autowired private ReactiveElasticsearchOperations operations;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
deleteIndices();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
deleteIndices();
|
||||
}
|
||||
|
||||
private void deleteIndices() {
|
||||
operations.indexOps(IndexCoordinates.of(TESTINDEX + "*")).delete().block();
|
||||
}
|
||||
|
||||
@Test // DATAES-678
|
||||
void shouldCreateIndexOpsForIndexCoordinates() {
|
||||
|
||||
IndexCoordinates indexCoordinates = IndexCoordinates.of(TESTINDEX);
|
||||
|
||||
ReactiveIndexOperations indexOperations = operations.indexOps(indexCoordinates);
|
||||
|
||||
assertThat(indexOperations).isNotNull();
|
||||
}
|
||||
|
||||
@Test // DATAES-678
|
||||
void shouldCreateIndexOpsForEntityClass() {
|
||||
|
||||
ReactiveIndexOperations indexOperations = operations.indexOps(Entity.class);
|
||||
|
||||
assertThat(indexOperations).isNotNull();
|
||||
}
|
||||
|
||||
@Test // DATAES-678
|
||||
void shouldCreateIndexForName() {
|
||||
|
||||
ReactiveIndexOperations indexOps = operations.indexOps(IndexCoordinates.of(TESTINDEX + "-create"));
|
||||
|
||||
indexOps.create() //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(true) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-678
|
||||
void shouldCreateIndexForEntity() {
|
||||
|
||||
ReactiveIndexOperations indexOps = operations.indexOps(Entity.class);
|
||||
|
||||
indexOps.create() //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(true) //
|
||||
.verifyComplete();
|
||||
|
||||
// check the settings from the class annotation
|
||||
indexOps.getSettings().as(StepVerifier::create).consumeNextWith(settings -> {
|
||||
assertThat(settings.get("index.number_of_replicas")).isEqualTo("2");
|
||||
assertThat(settings.get("index.number_of_shards")).isEqualTo("3");
|
||||
assertThat(settings.get("index.refresh_interval")).isEqualTo("4s");
|
||||
}).verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-678
|
||||
void shouldCreateIndexWithGivenSettings() {
|
||||
|
||||
ReactiveIndexOperations indexOps = operations.indexOps(IndexCoordinates.of(TESTINDEX + "-create"));
|
||||
|
||||
org.springframework.data.elasticsearch.core.document.Document requiredSettings = org.springframework.data.elasticsearch.core.document.Document
|
||||
.create();
|
||||
requiredSettings.put("index.number_of_replicas", 3);
|
||||
requiredSettings.put("index.number_of_shards", 4);
|
||||
requiredSettings.put("index.refresh_interval", "5s");
|
||||
|
||||
indexOps.create(requiredSettings) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(true) //
|
||||
.verifyComplete();
|
||||
|
||||
indexOps.getSettings().as(StepVerifier::create).consumeNextWith(settings -> {
|
||||
assertThat(settings.get("index.number_of_replicas")).isEqualTo("3");
|
||||
assertThat(settings.get("index.number_of_shards")).isEqualTo("4");
|
||||
assertThat(settings.get("index.refresh_interval")).isEqualTo("5s");
|
||||
}).verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-678
|
||||
void shouldCreateIndexWithAnnotatedSettings() {
|
||||
|
||||
ReactiveIndexOperations indexOps = operations.indexOps(EntityWithAnnotatedSettingsAndMappings.class);
|
||||
|
||||
indexOps.create() //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(true) //
|
||||
.verifyComplete();
|
||||
|
||||
indexOps.getSettings().as(StepVerifier::create).consumeNextWith(settings -> {
|
||||
assertThat(settings.get("index.number_of_replicas")).isEqualTo("0");
|
||||
assertThat(settings.get("index.number_of_shards")).isEqualTo("1");
|
||||
assertThat(settings.containsKey("index.analysis.analyzer.emailAnalyzer.tokenizer")).isTrue();
|
||||
assertThat(settings.get("index.analysis.analyzer.emailAnalyzer.tokenizer")).isEqualTo("uax_url_email");
|
||||
}).verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-678
|
||||
public void shouldCreateIndexUsingServerDefaultConfiguration() {
|
||||
|
||||
ReactiveIndexOperations indexOps = operations.indexOps(EntityUseServerConfig.class);
|
||||
|
||||
indexOps.create() //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(true) //
|
||||
.verifyComplete();
|
||||
|
||||
// check the settings from the class annotation
|
||||
indexOps.getSettings().as(StepVerifier::create).consumeNextWith(settings -> {
|
||||
assertThat(settings.get("index.number_of_replicas")).isEqualTo("1");
|
||||
assertThat(settings.get("index.number_of_shards")).isEqualTo("1");
|
||||
}).verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-678
|
||||
void shouldDeleteIfItExists() {
|
||||
|
||||
ReactiveIndexOperations indexOps = operations.indexOps(IndexCoordinates.of(TESTINDEX + "-delete"));
|
||||
indexOps.create().block();
|
||||
|
||||
indexOps.delete() //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(true) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-678
|
||||
void shouldReturnFalseOnDeleteIfItDoesNotExist() {
|
||||
|
||||
ReactiveIndexOperations indexOps = operations.indexOps(IndexCoordinates.of(TESTINDEX + "-delete"));
|
||||
|
||||
indexOps.delete() //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(false) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-678
|
||||
void shouldReturnExistsTrueIfIndexDoesExist() {
|
||||
|
||||
ReactiveIndexOperations indexOps = operations.indexOps(IndexCoordinates.of(TESTINDEX + "-exists"));
|
||||
indexOps.create().block();
|
||||
|
||||
indexOps.exists() //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(true) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-678
|
||||
void shouldReturnExistsFalseIfIndexDoesNotExist() {
|
||||
ReactiveIndexOperations indexOps = operations.indexOps(IndexCoordinates.of(TESTINDEX + "-exists"));
|
||||
|
||||
indexOps.exists() //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(false) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-678
|
||||
void shouldCreateMappingForEntityFromProperties() {
|
||||
ReactiveIndexOperations indexOps = operations.indexOps(IndexCoordinates.of(TESTINDEX + "-mappings"));
|
||||
|
||||
String expected = "{\n" + //
|
||||
" \"properties\":{\n" + //
|
||||
" \"text\": {\n" + //
|
||||
" \"type\": \"text\"\n" + //
|
||||
" },\n" + //
|
||||
" \"publication-date\": {\n" + //
|
||||
" \"type\": \"date\",\n" + //
|
||||
" \"format\": \"basic_date\"\n" + //
|
||||
" }\n" + //
|
||||
" }\n" + //
|
||||
"}\n"; //
|
||||
|
||||
indexOps.createMapping(Entity.class) //
|
||||
.as(StepVerifier::create) //
|
||||
.assertNext(document -> {
|
||||
try {
|
||||
assertEquals(expected, document.toJson(), JSONCompareMode.NON_EXTENSIBLE);
|
||||
} catch (JSONException e) {
|
||||
fail("", e);
|
||||
}
|
||||
}) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-678
|
||||
void shouldCreateMappingForEntityFromMappingAnnotation() {
|
||||
ReactiveIndexOperations indexOps = operations.indexOps(IndexCoordinates.of(TESTINDEX + "-mappings"));
|
||||
|
||||
String expected = "{\n" + //
|
||||
" \"properties\": {\n" + //
|
||||
" \"email\": {\n" + //
|
||||
" \"type\": \"text\",\n" + //
|
||||
" \"analyzer\": \"emailAnalyzer\"\n" + //
|
||||
" }\n" + //
|
||||
" }\n" + //
|
||||
"}\n"; //
|
||||
|
||||
indexOps.createMapping(EntityWithAnnotatedSettingsAndMappings.class) //
|
||||
.as(StepVerifier::create) //
|
||||
.assertNext(document -> {
|
||||
try {
|
||||
assertEquals(expected, document.toJson(), JSONCompareMode.NON_EXTENSIBLE);
|
||||
} catch (JSONException e) {
|
||||
fail("", e);
|
||||
}
|
||||
}) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-678
|
||||
void shouldCreateMappingBoundEntity() {
|
||||
ReactiveIndexOperations indexOps = operations.indexOps(Entity.class);
|
||||
|
||||
String expected = "{\n" + //
|
||||
" \"properties\":{\n" + //
|
||||
" \"text\": {\n" + //
|
||||
" \"type\": \"text\"\n" + //
|
||||
" },\n" + //
|
||||
" \"publication-date\": {\n" + //
|
||||
" \"type\": \"date\",\n" + //
|
||||
" \"format\": \"basic_date\"\n" + //
|
||||
" }\n" + //
|
||||
" }\n" + //
|
||||
"}\n"; //
|
||||
|
||||
indexOps.createMapping() //
|
||||
.as(StepVerifier::create) //
|
||||
.assertNext(document -> {
|
||||
try {
|
||||
assertEquals(expected, document.toJson(), JSONCompareMode.NON_EXTENSIBLE);
|
||||
} catch (JSONException e) {
|
||||
fail("", e);
|
||||
}
|
||||
}) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-678
|
||||
void shouldPutAndGetMapping() {
|
||||
ReactiveIndexOperations indexOps = operations.indexOps(Entity.class);
|
||||
|
||||
String expected = "{\n" + //
|
||||
" \"properties\":{\n" + //
|
||||
" \"text\": {\n" + //
|
||||
" \"type\": \"text\"\n" + //
|
||||
" },\n" + //
|
||||
" \"publication-date\": {\n" + //
|
||||
" \"type\": \"date\",\n" + //
|
||||
" \"format\": \"basic_date\"\n" + //
|
||||
" }\n" + //
|
||||
" }\n" + //
|
||||
"}\n"; //
|
||||
|
||||
indexOps.create() //
|
||||
.then(indexOps.putMapping()) //
|
||||
.then(indexOps.getMapping()) //
|
||||
.as(StepVerifier::create) //
|
||||
.assertNext(document -> {
|
||||
try {
|
||||
assertEquals(expected, document.toJson(), JSONCompareMode.NON_EXTENSIBLE);
|
||||
} catch (JSONException e) {
|
||||
fail("", e);
|
||||
}
|
||||
}).verifyComplete();
|
||||
}
|
||||
|
||||
@Data
|
||||
@Document(indexName = TESTINDEX, shards = 3, replicas = 2, refreshInterval = "4s")
|
||||
static class Entity {
|
||||
@Id private String id;
|
||||
@Field(type = FieldType.Text) private String text;
|
||||
@Field(name = "publication-date", type = FieldType.Date,
|
||||
format = DateFormat.basic_date) private LocalDate publicationDate;
|
||||
}
|
||||
|
||||
@Data
|
||||
@Document(indexName = TESTINDEX, useServerConfiguration = true)
|
||||
static class EntityUseServerConfig {
|
||||
@Id private String id;
|
||||
}
|
||||
|
||||
@Data
|
||||
@Document(indexName = TESTINDEX)
|
||||
@Setting(settingPath = "/settings/test-settings.json")
|
||||
@Mapping(mappingPath = "/mappings/test-mappings.json")
|
||||
static class EntityWithAnnotatedSettingsAndMappings {
|
||||
@Id private String id;
|
||||
}
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2020 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;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.skyscreamer.jsonassert.JSONAssert.*;
|
||||
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* @author Peter-Josef Meisch
|
||||
*/
|
||||
class ReactiveResourceUtilTest {
|
||||
|
||||
@Test
|
||||
void shouldReadFromClasspath() {
|
||||
|
||||
String expected = "{\n" + //
|
||||
" \"index\": {\n" + //
|
||||
" \"number_of_shards\": \"1\",\n" + //
|
||||
" \"number_of_replicas\": \"0\",\n" + //
|
||||
" \"analysis\": {\n" + //
|
||||
" \"analyzer\": {\n" + //
|
||||
" \"emailAnalyzer\": {\n" + //
|
||||
" \"type\": \"custom\",\n" + //
|
||||
" \"tokenizer\": \"uax_url_email\"\n" + //
|
||||
" }\n" + //
|
||||
" }\n" + //
|
||||
" }\n" + //
|
||||
" }\n" + //
|
||||
"}\n"; //
|
||||
|
||||
ReactiveResourceUtil.readFileFromClasspath("/settings/test-settings.json") //
|
||||
.as(StepVerifier::create) //
|
||||
.consumeNextWith(actual -> {
|
||||
try {
|
||||
assertEquals(expected, actual, false);
|
||||
} catch (JSONException e) {
|
||||
fail("", e);
|
||||
}
|
||||
}) //
|
||||
.verifyComplete();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnEmptyMonoOnNonExistingResource() {
|
||||
ReactiveResourceUtil.readFileFromClasspath("/this/should/really/not/exist") //
|
||||
.as(StepVerifier::create) //
|
||||
.verifyComplete();
|
||||
}
|
||||
}
|
||||
@@ -84,7 +84,7 @@ class SearchHitSupportTest {
|
||||
@Override
|
||||
public SearchHit<String> next() {
|
||||
String nextString = iterator.next();
|
||||
return new SearchHit<>("id", 1.0f, new Object[0], emptyMap(), nextString);
|
||||
return new SearchHit<>("index", "id", 1.0f, new Object[0], emptyMap(), nextString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ public class StreamQueriesTest {
|
||||
|
||||
// given
|
||||
List<SearchHit<String>> hits = new ArrayList<>();
|
||||
hits.add(new SearchHit<String>(null, 0, null, null, "one"));
|
||||
hits.add(new SearchHit<String>(null, null, 0, null, null, "one"));
|
||||
|
||||
SearchScrollHits<String> searchHits = newSearchScrollHits(hits, "1234");
|
||||
|
||||
@@ -66,7 +66,7 @@ public class StreamQueriesTest {
|
||||
|
||||
// given
|
||||
List<SearchHit<String>> hits = new ArrayList<>();
|
||||
hits.add(new SearchHit<String>(null, 0, null, null, "one"));
|
||||
hits.add(new SearchHit<String>(null, null, 0, null, null, "one"));
|
||||
|
||||
SearchScrollHits<String> searchHits = newSearchScrollHits(hits, "1234");
|
||||
|
||||
@@ -86,11 +86,11 @@ public class StreamQueriesTest {
|
||||
void shouldClearAllScrollIds() {
|
||||
|
||||
SearchScrollHits<String> searchHits1 = newSearchScrollHits(
|
||||
Collections.singletonList(new SearchHit<String>(null, 0, null, null, "one")), "s-1");
|
||||
Collections.singletonList(new SearchHit<String>(null, null, 0, null, null, "one")), "s-1");
|
||||
SearchScrollHits<String> searchHits2 = newSearchScrollHits(
|
||||
Collections.singletonList(new SearchHit<String>(null, 0, null, null, "one")), "s-2");
|
||||
Collections.singletonList(new SearchHit<String>(null, null, 0, null, null, "one")), "s-2");
|
||||
SearchScrollHits<String> searchHits3 = newSearchScrollHits(
|
||||
Collections.singletonList(new SearchHit<String>(null, 0, null, null, "one")), "s-2");
|
||||
Collections.singletonList(new SearchHit<String>(null, null, 0, null, null, "one")), "s-2");
|
||||
SearchScrollHits<String> searchHits4 = newSearchScrollHits(Collections.emptyList(), "s-3");
|
||||
|
||||
Iterator<SearchScrollHits<String>> searchScrollHitsIterator = Arrays
|
||||
@@ -115,11 +115,11 @@ public class StreamQueriesTest {
|
||||
void shouldReturnAllForRequestedSizeOf0() {
|
||||
|
||||
SearchScrollHits<String> searchHits1 = newSearchScrollHits(
|
||||
Collections.singletonList(new SearchHit<String>(null, 0, null, null, "one")), "s-1");
|
||||
Collections.singletonList(new SearchHit<String>(null, null, 0, null, null, "one")), "s-1");
|
||||
SearchScrollHits<String> searchHits2 = newSearchScrollHits(
|
||||
Collections.singletonList(new SearchHit<String>(null, 0, null, null, "one")), "s-2");
|
||||
Collections.singletonList(new SearchHit<String>(null, null, 0, null, null, "one")), "s-2");
|
||||
SearchScrollHits<String> searchHits3 = newSearchScrollHits(
|
||||
Collections.singletonList(new SearchHit<String>(null, 0, null, null, "one")), "s-2");
|
||||
Collections.singletonList(new SearchHit<String>(null, null, 0, null, null, "one")), "s-2");
|
||||
SearchScrollHits<String> searchHits4 = newSearchScrollHits(Collections.emptyList(), "s-3");
|
||||
|
||||
Iterator<SearchScrollHits<String>> searchScrollHitsIterator = Arrays
|
||||
@@ -140,11 +140,11 @@ public class StreamQueriesTest {
|
||||
void shouldOnlyReturnRequestedCount() {
|
||||
|
||||
SearchScrollHits<String> searchHits1 = newSearchScrollHits(
|
||||
Collections.singletonList(new SearchHit<String>(null, 0, null, null, "one")), "s-1");
|
||||
Collections.singletonList(new SearchHit<String>(null, null, 0, null, null, "one")), "s-1");
|
||||
SearchScrollHits<String> searchHits2 = newSearchScrollHits(
|
||||
Collections.singletonList(new SearchHit<String>(null, 0, null, null, "one")), "s-2");
|
||||
Collections.singletonList(new SearchHit<String>(null, null, 0, null, null, "one")), "s-2");
|
||||
SearchScrollHits<String> searchHits3 = newSearchScrollHits(
|
||||
Collections.singletonList(new SearchHit<String>(null, 0, null, null, "one")), "s-2");
|
||||
Collections.singletonList(new SearchHit<String>(null, null, 0, null, null, "one")), "s-2");
|
||||
SearchScrollHits<String> searchHits4 = newSearchScrollHits(Collections.emptyList(), "s-3");
|
||||
|
||||
Iterator<SearchScrollHits<String>> searchScrollHitsIterator = Arrays
|
||||
|
||||
+1
-1
@@ -97,7 +97,7 @@ public class ElasticsearchTemplateAggregationTests {
|
||||
.addAuthor(RIZWAN_IDREES).addPublishedYear(YEAR_2002).addPublishedYear(YEAR_2001).addPublishedYear(YEAR_2000)
|
||||
.score(40).buildIndex();
|
||||
|
||||
IndexCoordinates index = IndexCoordinates.of(INDEX_NAME).withTypes("article");
|
||||
IndexCoordinates index = IndexCoordinates.of(INDEX_NAME);
|
||||
operations.index(article1, index);
|
||||
operations.index(article2, index);
|
||||
operations.index(article3, index);
|
||||
|
||||
+5
-7
@@ -108,8 +108,7 @@ public class ElasticsearchTemplateCompletionTests {
|
||||
indexQueries.add(new AnnotatedCompletionEntityBuilder("4").name("Artur Konczak")
|
||||
.suggest(new String[] { "Artur", "Konczak" }).buildIndex());
|
||||
|
||||
operations.bulkIndex(indexQueries,
|
||||
IndexCoordinates.of("test-index-annotated-completion").withTypes("annotated-completion-type"));
|
||||
operations.bulkIndex(indexQueries, IndexCoordinates.of("test-index-annotated-completion"));
|
||||
operations.indexOps(AnnotatedCompletionEntity.class).refresh();
|
||||
}
|
||||
|
||||
@@ -125,8 +124,7 @@ public class ElasticsearchTemplateCompletionTests {
|
||||
indexQueries.add(new AnnotatedCompletionEntityBuilder("4").name("Mewes Kochheim4")
|
||||
.suggest(new String[] { "Mewes Kochheim4" }, Integer.MAX_VALUE).buildIndex());
|
||||
|
||||
operations.bulkIndex(indexQueries,
|
||||
IndexCoordinates.of("test-index-annotated-completion").withTypes("annotated-completion-type"));
|
||||
operations.bulkIndex(indexQueries, IndexCoordinates.of("test-index-annotated-completion"));
|
||||
operations.indexOps(AnnotatedCompletionEntity.class).refresh();
|
||||
}
|
||||
|
||||
@@ -142,7 +140,7 @@ public class ElasticsearchTemplateCompletionTests {
|
||||
// when
|
||||
SearchResponse suggestResponse = ((AbstractElasticsearchTemplate) operations).suggest(
|
||||
new SuggestBuilder().addSuggestion("test-suggest", completionSuggestionFuzzyBuilder),
|
||||
IndexCoordinates.of("test-index-core-completion").withTypes("completion-type"));
|
||||
IndexCoordinates.of("test-index-core-completion"));
|
||||
CompletionSuggestion completionSuggestion = suggestResponse.getSuggest().getSuggestion("test-suggest");
|
||||
List<CompletionSuggestion.Entry.Option> options = completionSuggestion.getEntries().get(0).getOptions();
|
||||
|
||||
@@ -170,7 +168,7 @@ public class ElasticsearchTemplateCompletionTests {
|
||||
// when
|
||||
SearchResponse suggestResponse = ((AbstractElasticsearchTemplate) operations).suggest(
|
||||
new SuggestBuilder().addSuggestion("test-suggest", completionSuggestionFuzzyBuilder),
|
||||
IndexCoordinates.of("test-index-annotated-completion").withTypes("annotated-completion-type"));
|
||||
IndexCoordinates.of("test-index-annotated-completion"));
|
||||
CompletionSuggestion completionSuggestion = suggestResponse.getSuggest().getSuggestion("test-suggest");
|
||||
List<CompletionSuggestion.Entry.Option> options = completionSuggestion.getEntries().get(0).getOptions();
|
||||
|
||||
@@ -191,7 +189,7 @@ public class ElasticsearchTemplateCompletionTests {
|
||||
// when
|
||||
SearchResponse suggestResponse = ((AbstractElasticsearchTemplate) operations).suggest(
|
||||
new SuggestBuilder().addSuggestion("test-suggest", completionSuggestionFuzzyBuilder),
|
||||
IndexCoordinates.of("test-index-annotated-completion").withTypes("annotated-completion-type"));
|
||||
IndexCoordinates.of("test-index-annotated-completion"));
|
||||
CompletionSuggestion completionSuggestion = suggestResponse.getSuggest().getSuggestion("test-suggest");
|
||||
List<CompletionSuggestion.Entry.Option> options = completionSuggestion.getEntries().get(0).getOptions();
|
||||
|
||||
|
||||
+4
-5
@@ -110,8 +110,7 @@ public class ElasticsearchTemplateCompletionWithContextsTests {
|
||||
indexQueries.add(new ContextCompletionEntityBuilder("4").name("Artur Konczak")
|
||||
.suggest(new String[] { "Artur", "Konczak" }, context4).buildIndex());
|
||||
|
||||
operations.bulkIndex(indexQueries,
|
||||
IndexCoordinates.of("test-index-context-completion").withTypes("context-completion-type"));
|
||||
operations.bulkIndex(indexQueries, IndexCoordinates.of("test-index-context-completion"));
|
||||
operations.indexOps(ContextCompletionEntity.class).refresh();
|
||||
}
|
||||
|
||||
@@ -137,7 +136,7 @@ public class ElasticsearchTemplateCompletionWithContextsTests {
|
||||
// when
|
||||
SearchResponse suggestResponse = ((AbstractElasticsearchTemplate) operations).suggest(
|
||||
new SuggestBuilder().addSuggestion("test-suggest", completionSuggestionFuzzyBuilder),
|
||||
IndexCoordinates.of("test-index-context-completion").withTypes("context-completion-type"));
|
||||
IndexCoordinates.of("test-index-context-completion"));
|
||||
assertThat(suggestResponse.getSuggest()).isNotNull();
|
||||
CompletionSuggestion completionSuggestion = suggestResponse.getSuggest().getSuggestion("test-suggest");
|
||||
List<CompletionSuggestion.Entry.Option> options = completionSuggestion.getEntries().get(0).getOptions();
|
||||
@@ -169,7 +168,7 @@ public class ElasticsearchTemplateCompletionWithContextsTests {
|
||||
// when
|
||||
SearchResponse suggestResponse = ((AbstractElasticsearchTemplate) operations).suggest(
|
||||
new SuggestBuilder().addSuggestion("test-suggest", completionSuggestionFuzzyBuilder),
|
||||
IndexCoordinates.of("test-index-context-completion").withTypes("context-completion-type"));
|
||||
IndexCoordinates.of("test-index-context-completion"));
|
||||
assertThat(suggestResponse.getSuggest()).isNotNull();
|
||||
CompletionSuggestion completionSuggestion = suggestResponse.getSuggest().getSuggestion("test-suggest");
|
||||
List<CompletionSuggestion.Entry.Option> options = completionSuggestion.getEntries().get(0).getOptions();
|
||||
@@ -201,7 +200,7 @@ public class ElasticsearchTemplateCompletionWithContextsTests {
|
||||
// when
|
||||
SearchResponse suggestResponse = ((AbstractElasticsearchTemplate) operations).suggest(
|
||||
new SuggestBuilder().addSuggestion("test-suggest", completionSuggestionFuzzyBuilder),
|
||||
IndexCoordinates.of("test-index-context-completion").withTypes("context-completion-type"));
|
||||
IndexCoordinates.of("test-index-context-completion"));
|
||||
assertThat(suggestResponse.getSuggest()).isNotNull();
|
||||
CompletionSuggestion completionSuggestion = suggestResponse.getSuggest().getSuggestion("test-suggest");
|
||||
List<CompletionSuggestion.Entry.Option> options = completionSuggestion.getEntries().get(0).getOptions();
|
||||
|
||||
+22
@@ -2,6 +2,7 @@ package org.springframework.data.elasticsearch.core.convert;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
@@ -16,6 +17,7 @@ import org.springframework.data.elasticsearch.annotations.DateFormat;
|
||||
|
||||
/**
|
||||
* @author Peter-Josef Meisch
|
||||
* @author Tim te Beek
|
||||
*/
|
||||
class ElasticsearchDateConverterTests {
|
||||
|
||||
@@ -76,4 +78,24 @@ class ElasticsearchDateConverterTests {
|
||||
|
||||
assertThat(parsed).isEqualTo(legacyDate);
|
||||
}
|
||||
|
||||
@Test // DATAES-847
|
||||
void shouldParseEpochMillisString() {
|
||||
Instant instant = Instant.ofEpochMilli(1234568901234L);
|
||||
ElasticsearchDateConverter converter = ElasticsearchDateConverter.of(DateFormat.epoch_millis);
|
||||
|
||||
Date parsed = converter.parse("1234568901234");
|
||||
|
||||
assertThat(parsed.toInstant()).isEqualTo(instant);
|
||||
}
|
||||
|
||||
@Test // DATAES-847
|
||||
void shouldConvertInstantToString() {
|
||||
Instant instant = Instant.ofEpochMilli(1234568901234L);
|
||||
ElasticsearchDateConverter converter = ElasticsearchDateConverter.of(DateFormat.epoch_millis);
|
||||
|
||||
String formatted = converter.format(instant);
|
||||
|
||||
assertThat(formatted).isEqualTo("1234568901234");
|
||||
}
|
||||
}
|
||||
|
||||
+31
-1
@@ -789,6 +789,30 @@ public class MappingElasticsearchConverterUnitTests {
|
||||
assertThat(entity.locations).containsExactly(new GeoPoint(12.34, 23.45), new GeoPoint(34.56, 45.67));
|
||||
}
|
||||
|
||||
@Test // DATAES-865
|
||||
void shouldWriteEntityWithMapAsObject() throws JSONException {
|
||||
|
||||
Map<String, Object> map = new LinkedHashMap<>();
|
||||
map.put("foo", "bar");
|
||||
|
||||
EntityWithObject entity = new EntityWithObject();
|
||||
entity.setId("42");
|
||||
entity.setContent(map);
|
||||
|
||||
String expected = "{\n" + //
|
||||
" \"id\": \"42\",\n" + //
|
||||
" \"content\": {\n" + //
|
||||
" \"foo\": \"bar\"\n" + //
|
||||
" }\n" + //
|
||||
"}\n"; //
|
||||
|
||||
Document document = Document.create();
|
||||
|
||||
mappingElasticsearchConverter.write(entity, document);
|
||||
|
||||
assertEquals(expected, document.toJson(), false);
|
||||
}
|
||||
|
||||
private String pointTemplate(String name, Point point) {
|
||||
return String.format(Locale.ENGLISH, "\"%s\":{\"lat\":%.1f,\"lon\":%.1f}", name, point.getX(), point.getY());
|
||||
}
|
||||
@@ -968,7 +992,7 @@ public class MappingElasticsearchConverterUnitTests {
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
@org.springframework.data.elasticsearch.annotations.Document(indexName = "test-index-geo-core-entity-mapper",
|
||||
type = "geo-test-index", replicas = 0, refreshInterval = "-1")
|
||||
replicas = 0, refreshInterval = "-1")
|
||||
static class GeoEntity {
|
||||
|
||||
@Id private String id;
|
||||
@@ -1016,4 +1040,10 @@ public class MappingElasticsearchConverterUnitTests {
|
||||
@Id String id;
|
||||
List<GeoPoint> locations;
|
||||
}
|
||||
|
||||
@Data
|
||||
static class EntityWithObject {
|
||||
@Id private String id;
|
||||
private Object content;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ abstract class ElasticsearchOperationsCallbackTest {
|
||||
IndexOperations indexOps = operations.indexOps(SampleEntity.class);
|
||||
indexOps.delete();
|
||||
indexOps.create();
|
||||
indexOps.putMapping(indexOps.createMapping(SampleEntity.class));
|
||||
indexOps.putMapping(SampleEntity.class);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
|
||||
+1
-1
@@ -67,7 +67,7 @@ public class ReactiveElasticsearchOperationsCallbackTest {
|
||||
void setUp() {
|
||||
IndexOperations indexOps = nonreactiveOperations.indexOps(SampleEntity.class);
|
||||
indexOps.create();
|
||||
indexOps.putMapping(indexOps.createMapping(SampleEntity.class));
|
||||
indexOps.putMapping(SampleEntity.class);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
|
||||
+2
-4
@@ -71,10 +71,8 @@ public class ElasticsearchTemplateGeoTests {
|
||||
@Import({ ElasticsearchRestTemplateConfiguration.class })
|
||||
static class Config {}
|
||||
|
||||
private final IndexCoordinates locationMarkerIndex = IndexCoordinates.of("test-index-location-marker-core-geo")
|
||||
.withTypes("geo-annotation-point-type");
|
||||
private final IndexCoordinates authorMarkerIndex = IndexCoordinates.of("test-index-author-marker-core-geo")
|
||||
.withTypes("geo-class-point-type");
|
||||
private final IndexCoordinates locationMarkerIndex = IndexCoordinates.of("test-index-location-marker-core-geo");
|
||||
private final IndexCoordinates authorMarkerIndex = IndexCoordinates.of("test-index-author-marker-core-geo");
|
||||
|
||||
@Autowired private ElasticsearchOperations operations;
|
||||
|
||||
|
||||
+13
-11
@@ -47,6 +47,7 @@ import java.util.Set;
|
||||
import org.assertj.core.data.Percentage;
|
||||
import org.elasticsearch.search.suggest.completion.context.ContextMapping;
|
||||
import org.json.JSONException;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -91,8 +92,9 @@ public class MappingBuilderTests extends MappingContextBaseTests {
|
||||
@Autowired private ElasticsearchOperations operations;
|
||||
private IndexOperations indexOperations;
|
||||
|
||||
@AfterEach
|
||||
@BeforeEach
|
||||
public void before() {
|
||||
public void deleteIndices() {
|
||||
indexOperations = operations.indexOps(SimpleRecursiveEntity.class);
|
||||
indexOperations.delete();
|
||||
operations.indexOps(StockPrice.class).delete();
|
||||
@@ -108,7 +110,7 @@ public class MappingBuilderTests extends MappingContextBaseTests {
|
||||
public void shouldNotFailOnCircularReference() {
|
||||
|
||||
operations.indexOps(SimpleRecursiveEntity.class).create();
|
||||
indexOperations.putMapping(indexOperations.createMapping(SimpleRecursiveEntity.class));
|
||||
indexOperations.putMapping(SimpleRecursiveEntity.class);
|
||||
indexOperations.refresh();
|
||||
}
|
||||
|
||||
@@ -144,12 +146,12 @@ public class MappingBuilderTests extends MappingContextBaseTests {
|
||||
|
||||
// When
|
||||
indexOps.create();
|
||||
indexOps.putMapping(indexOps.createMapping(StockPrice.class));
|
||||
indexOps.putMapping(StockPrice.class);
|
||||
String symbol = "AU";
|
||||
double price = 2.34;
|
||||
String id = "abc";
|
||||
|
||||
IndexCoordinates index = IndexCoordinates.of("test-index-stock-mapping-builder").withTypes("price");
|
||||
IndexCoordinates index = IndexCoordinates.of("test-index-stock-mapping-builder");
|
||||
operations.index(buildIndex(StockPrice.builder() //
|
||||
.id(id) //
|
||||
.symbol(symbol) //
|
||||
@@ -192,12 +194,12 @@ public class MappingBuilderTests extends MappingContextBaseTests {
|
||||
@Test // DATAES-76
|
||||
public void shouldAddSampleInheritedEntityDocumentToIndex() {
|
||||
// given
|
||||
IndexCoordinates index = IndexCoordinates.of("test-index-sample-inherited-mapping-builder").withTypes("mapping");
|
||||
IndexCoordinates index = IndexCoordinates.of("test-index-sample-inherited-mapping-builder");
|
||||
IndexOperations indexOps = operations.indexOps(index);
|
||||
|
||||
// when
|
||||
indexOps.create();
|
||||
indexOps.putMapping(indexOps.createMapping(SampleInheritedEntity.class));
|
||||
indexOps.putMapping(SampleInheritedEntity.class);
|
||||
Date createdDate = new Date();
|
||||
String message = "msg";
|
||||
String id = "abc";
|
||||
@@ -238,11 +240,11 @@ public class MappingBuilderTests extends MappingContextBaseTests {
|
||||
// given
|
||||
IndexOperations indexOpsUser = operations.indexOps(User.class);
|
||||
indexOpsUser.create();
|
||||
indexOpsUser.putMapping(indexOpsUser.createMapping(User.class));
|
||||
indexOpsUser.putMapping(User.class);
|
||||
|
||||
IndexOperations indexOpsGroup = operations.indexOps(Group.class);
|
||||
indexOpsGroup.create();
|
||||
indexOpsGroup.putMapping(indexOpsGroup.createMapping(Group.class));
|
||||
indexOpsGroup.putMapping(Group.class);
|
||||
|
||||
// when
|
||||
|
||||
@@ -255,7 +257,7 @@ public class MappingBuilderTests extends MappingContextBaseTests {
|
||||
// given
|
||||
IndexOperations indexOps = operations.indexOps(Book.class);
|
||||
indexOps.create();
|
||||
indexOps.putMapping(indexOps.createMapping(Book.class));
|
||||
indexOps.putMapping(Book.class);
|
||||
|
||||
// when
|
||||
|
||||
@@ -268,7 +270,7 @@ public class MappingBuilderTests extends MappingContextBaseTests {
|
||||
// given
|
||||
IndexOperations indexOps = this.operations.indexOps(Book.class);
|
||||
indexOps.create();
|
||||
indexOps.putMapping(indexOps.createMapping(Book.class));
|
||||
indexOps.putMapping(Book.class);
|
||||
|
||||
// when
|
||||
Map mapping = indexOps.getMapping();
|
||||
@@ -310,7 +312,7 @@ public class MappingBuilderTests extends MappingContextBaseTests {
|
||||
// given
|
||||
IndexOperations indexOps = operations.indexOps(CopyToEntity.class);
|
||||
indexOps.create();
|
||||
indexOps.putMapping(indexOps.createMapping(CopyToEntity.class));
|
||||
indexOps.putMapping(CopyToEntity.class);
|
||||
|
||||
// when
|
||||
Map mapping = indexOps.getMapping();
|
||||
|
||||
+36
-36
@@ -15,9 +15,9 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.core.query;
|
||||
|
||||
import static org.apache.commons.lang.RandomStringUtils.*;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.springframework.data.elasticsearch.annotations.FieldType.*;
|
||||
import static org.springframework.data.elasticsearch.utils.IdGenerator.*;
|
||||
import static org.springframework.data.elasticsearch.utils.IndexBuilder.*;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
@@ -64,7 +64,7 @@ public class CriteriaQueryTests {
|
||||
@Import({ ElasticsearchRestTemplateConfiguration.class })
|
||||
static class Config {}
|
||||
|
||||
private final IndexCoordinates index = IndexCoordinates.of("test-index-sample-core-query").withTypes("test-type");
|
||||
private final IndexCoordinates index = IndexCoordinates.of("test-index-sample-core-query");
|
||||
|
||||
@Autowired private ElasticsearchOperations operations;
|
||||
private IndexOperations indexOperations;
|
||||
@@ -74,7 +74,7 @@ public class CriteriaQueryTests {
|
||||
indexOperations = operations.indexOps(SampleEntity.class);
|
||||
indexOperations.delete();
|
||||
indexOperations.create();
|
||||
indexOperations.putMapping(indexOperations.createMapping(SampleEntity.class));
|
||||
indexOperations.putMapping(SampleEntity.class);
|
||||
indexOperations.refresh();
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ public class CriteriaQueryTests {
|
||||
public void shouldPerformAndOperation() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setMessage("some test message");
|
||||
@@ -116,7 +116,7 @@ public class CriteriaQueryTests {
|
||||
List<IndexQuery> indexQueries = new ArrayList<>();
|
||||
|
||||
// first document
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity1 = new SampleEntity();
|
||||
sampleEntity1.setId(documentId);
|
||||
sampleEntity1.setMessage("some message");
|
||||
@@ -128,7 +128,7 @@ public class CriteriaQueryTests {
|
||||
indexQueries.add(indexQuery1);
|
||||
|
||||
// second document
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId2);
|
||||
sampleEntity2.setMessage("test message");
|
||||
@@ -159,7 +159,7 @@ public class CriteriaQueryTests {
|
||||
List<IndexQuery> indexQueries = new ArrayList<>();
|
||||
|
||||
// first document
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setMessage("some message");
|
||||
@@ -190,7 +190,7 @@ public class CriteriaQueryTests {
|
||||
List<IndexQuery> indexQueries = new ArrayList<>();
|
||||
|
||||
// first document
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setMessage("some message");
|
||||
@@ -219,7 +219,7 @@ public class CriteriaQueryTests {
|
||||
// given
|
||||
List<IndexQuery> indexQueries = new ArrayList<>();
|
||||
// first document
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setMessage("some message");
|
||||
@@ -249,7 +249,7 @@ public class CriteriaQueryTests {
|
||||
List<IndexQuery> indexQueries = new ArrayList<>();
|
||||
|
||||
// first document
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity1 = new SampleEntity();
|
||||
sampleEntity1.setId(documentId);
|
||||
sampleEntity1.setMessage("some message");
|
||||
@@ -261,7 +261,7 @@ public class CriteriaQueryTests {
|
||||
indexQueries.add(indexQuery1);
|
||||
|
||||
// second document
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId2);
|
||||
sampleEntity2.setMessage("test message");
|
||||
@@ -291,7 +291,7 @@ public class CriteriaQueryTests {
|
||||
List<IndexQuery> indexQueries = new ArrayList<>();
|
||||
|
||||
// first document
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity1 = new SampleEntity();
|
||||
sampleEntity1.setId(documentId);
|
||||
sampleEntity1.setMessage("some message");
|
||||
@@ -303,7 +303,7 @@ public class CriteriaQueryTests {
|
||||
indexQueries.add(indexQuery1);
|
||||
|
||||
// second document
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId2);
|
||||
sampleEntity2.setMessage("test message end");
|
||||
@@ -333,7 +333,7 @@ public class CriteriaQueryTests {
|
||||
// given
|
||||
List<IndexQuery> indexQueries = new ArrayList<>();
|
||||
// first document
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity1 = new SampleEntity();
|
||||
sampleEntity1.setId(documentId);
|
||||
sampleEntity1.setMessage("start some message");
|
||||
@@ -345,7 +345,7 @@ public class CriteriaQueryTests {
|
||||
indexQueries.add(indexQuery1);
|
||||
|
||||
// second document
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId2);
|
||||
sampleEntity2.setMessage("test message");
|
||||
@@ -375,7 +375,7 @@ public class CriteriaQueryTests {
|
||||
// given
|
||||
List<IndexQuery> indexQueries = new ArrayList<>();
|
||||
// first document
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity1 = new SampleEntity();
|
||||
sampleEntity1.setId(documentId);
|
||||
sampleEntity1.setMessage("contains some message");
|
||||
@@ -387,7 +387,7 @@ public class CriteriaQueryTests {
|
||||
indexQueries.add(indexQuery1);
|
||||
|
||||
// second document
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId2);
|
||||
sampleEntity2.setMessage("test message");
|
||||
@@ -416,7 +416,7 @@ public class CriteriaQueryTests {
|
||||
// given
|
||||
List<IndexQuery> indexQueries = new ArrayList<>();
|
||||
// first document
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity1 = new SampleEntity();
|
||||
sampleEntity1.setId(documentId);
|
||||
sampleEntity1.setMessage("elasticsearch search");
|
||||
@@ -428,7 +428,7 @@ public class CriteriaQueryTests {
|
||||
indexQueries.add(indexQuery1);
|
||||
|
||||
// second document
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId2);
|
||||
sampleEntity2.setMessage("test message");
|
||||
@@ -457,7 +457,7 @@ public class CriteriaQueryTests {
|
||||
// given
|
||||
List<IndexQuery> indexQueries = new ArrayList<>();
|
||||
// first document
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity1 = new SampleEntity();
|
||||
sampleEntity1.setId(documentId);
|
||||
sampleEntity1.setMessage("some message search");
|
||||
@@ -469,7 +469,7 @@ public class CriteriaQueryTests {
|
||||
indexQueries.add(indexQuery1);
|
||||
|
||||
// second document
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId2);
|
||||
sampleEntity2.setMessage("test test message");
|
||||
@@ -499,7 +499,7 @@ public class CriteriaQueryTests {
|
||||
// given
|
||||
List<IndexQuery> indexQueries = new ArrayList<>();
|
||||
// first document
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity1 = new SampleEntity();
|
||||
sampleEntity1.setId(documentId);
|
||||
sampleEntity1.setMessage("bar");
|
||||
@@ -511,7 +511,7 @@ public class CriteriaQueryTests {
|
||||
indexQueries.add(indexQuery1);
|
||||
|
||||
// second document
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId2);
|
||||
sampleEntity2.setMessage("foo");
|
||||
@@ -541,7 +541,7 @@ public class CriteriaQueryTests {
|
||||
// given
|
||||
List<IndexQuery> indexQueries = new ArrayList<>();
|
||||
// first document
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity1 = new SampleEntity();
|
||||
sampleEntity1.setId(documentId);
|
||||
sampleEntity1.setRate(100);
|
||||
@@ -554,7 +554,7 @@ public class CriteriaQueryTests {
|
||||
indexQueries.add(indexQuery1);
|
||||
|
||||
// second document
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId2);
|
||||
sampleEntity2.setRate(200);
|
||||
@@ -583,7 +583,7 @@ public class CriteriaQueryTests {
|
||||
// given
|
||||
List<IndexQuery> indexQueries = new ArrayList<>();
|
||||
// first document
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity1 = new SampleEntity();
|
||||
sampleEntity1.setId(documentId);
|
||||
sampleEntity1.setRate(300);
|
||||
@@ -596,7 +596,7 @@ public class CriteriaQueryTests {
|
||||
indexQueries.add(indexQuery1);
|
||||
|
||||
// second document
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId2);
|
||||
sampleEntity2.setRate(400);
|
||||
@@ -626,7 +626,7 @@ public class CriteriaQueryTests {
|
||||
// given
|
||||
List<IndexQuery> indexQueries = new ArrayList<>();
|
||||
// first document
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity1 = new SampleEntity();
|
||||
sampleEntity1.setId(documentId);
|
||||
sampleEntity1.setRate(500);
|
||||
@@ -639,7 +639,7 @@ public class CriteriaQueryTests {
|
||||
indexQueries.add(indexQuery1);
|
||||
|
||||
// second document
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId2);
|
||||
sampleEntity2.setRate(600);
|
||||
@@ -669,7 +669,7 @@ public class CriteriaQueryTests {
|
||||
// given
|
||||
List<IndexQuery> indexQueries = new ArrayList<>();
|
||||
// first document
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity1 = new SampleEntity();
|
||||
sampleEntity1.setId(documentId);
|
||||
sampleEntity1.setRate(700);
|
||||
@@ -682,7 +682,7 @@ public class CriteriaQueryTests {
|
||||
indexQueries.add(indexQuery1);
|
||||
|
||||
// second document
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId2);
|
||||
sampleEntity2.setRate(800);
|
||||
@@ -712,7 +712,7 @@ public class CriteriaQueryTests {
|
||||
// given
|
||||
List<IndexQuery> indexQueries = new ArrayList<>();
|
||||
// first document
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity1 = new SampleEntity();
|
||||
sampleEntity1.setId(documentId);
|
||||
sampleEntity1.setRate(900);
|
||||
@@ -725,7 +725,7 @@ public class CriteriaQueryTests {
|
||||
indexQueries.add(indexQuery1);
|
||||
|
||||
// second document
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId2);
|
||||
sampleEntity2.setRate(1000);
|
||||
@@ -755,7 +755,7 @@ public class CriteriaQueryTests {
|
||||
// given
|
||||
List<IndexQuery> indexQueries = new ArrayList<>();
|
||||
// first document
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity1 = new SampleEntity();
|
||||
sampleEntity1.setId(documentId);
|
||||
sampleEntity1.setRate(700);
|
||||
@@ -768,7 +768,7 @@ public class CriteriaQueryTests {
|
||||
indexQueries.add(indexQuery1);
|
||||
|
||||
// second document
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId2);
|
||||
sampleEntity2.setRate(800);
|
||||
@@ -819,7 +819,7 @@ public class CriteriaQueryTests {
|
||||
public void shouldEscapeValue() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setMessage("Hello World!");
|
||||
|
||||
+83
-83
@@ -15,9 +15,9 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.repositories.custommethod;
|
||||
|
||||
import static org.apache.commons.lang.RandomStringUtils.*;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.springframework.data.elasticsearch.annotations.FieldType.*;
|
||||
import static org.springframework.data.elasticsearch.utils.IdGenerator.*;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
@@ -100,7 +100,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldExecuteCustomMethod() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -119,7 +119,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldExecuteCustomMethodForNot() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("some");
|
||||
@@ -137,7 +137,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldExecuteCustomMethodWithQuery() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -157,7 +157,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldExecuteCustomMethodWithLessThan() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -165,7 +165,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
sampleEntity.setMessage("some message");
|
||||
repository.save(sampleEntity);
|
||||
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId2);
|
||||
sampleEntity2.setType("test");
|
||||
@@ -185,7 +185,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldExecuteCustomMethodWithBefore() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -205,7 +205,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldExecuteCustomMethodWithAfter() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -225,7 +225,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldExecuteCustomMethodWithLike() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -245,7 +245,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldExecuteCustomMethodForStartingWith() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -265,7 +265,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldExecuteCustomMethodForEndingWith() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -285,7 +285,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldExecuteCustomMethodForContains() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -305,7 +305,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldExecuteCustomMethodForIn() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -313,7 +313,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
repository.save(sampleEntity);
|
||||
|
||||
// given
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId2);
|
||||
sampleEntity2.setType("test");
|
||||
@@ -334,7 +334,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldExecuteCustomMethodForNotIn() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -342,7 +342,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
repository.save(sampleEntity);
|
||||
|
||||
// given
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId2);
|
||||
sampleEntity2.setType("test");
|
||||
@@ -363,13 +363,13 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldHandleManyValuesQueryingIn() {
|
||||
|
||||
// given
|
||||
String documentId1 = randomNumeric(32);
|
||||
String documentId1 = nextIdAsString();
|
||||
SampleEntity sampleEntity1 = new SampleEntity();
|
||||
sampleEntity1.setId(documentId1);
|
||||
sampleEntity1.setKeyword("foo");
|
||||
repository.save(sampleEntity1);
|
||||
|
||||
String documentId2 = randomNumeric(32);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId2);
|
||||
sampleEntity2.setKeyword("bar");
|
||||
@@ -379,7 +379,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
keywords.add("foo");
|
||||
|
||||
for (int i = 0; i < 1025; i++) {
|
||||
keywords.add(randomNumeric(32));
|
||||
keywords.add(nextIdAsString());
|
||||
}
|
||||
|
||||
// when
|
||||
@@ -394,13 +394,13 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldHandleManyValuesQueryingNotIn() {
|
||||
|
||||
// given
|
||||
String documentId1 = randomNumeric(32);
|
||||
String documentId1 = nextIdAsString();
|
||||
SampleEntity sampleEntity1 = new SampleEntity();
|
||||
sampleEntity1.setId(documentId1);
|
||||
sampleEntity1.setKeyword("foo");
|
||||
repository.save(sampleEntity1);
|
||||
|
||||
String documentId2 = randomNumeric(32);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId2);
|
||||
sampleEntity2.setKeyword("bar");
|
||||
@@ -410,7 +410,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
keywords.add("foo");
|
||||
|
||||
for (int i = 0; i < 1025; i++) {
|
||||
keywords.add(randomNumeric(32));
|
||||
keywords.add(nextIdAsString());
|
||||
}
|
||||
|
||||
// when
|
||||
@@ -425,7 +425,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldExecuteCustomMethodForTrue() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -434,7 +434,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
repository.save(sampleEntity);
|
||||
|
||||
// given
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId2);
|
||||
sampleEntity2.setType("test");
|
||||
@@ -453,7 +453,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldExecuteCustomMethodForFalse() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -462,7 +462,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
repository.save(sampleEntity);
|
||||
|
||||
// given
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId2);
|
||||
sampleEntity2.setType("test");
|
||||
@@ -482,7 +482,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldExecuteCustomMethodForOrderBy() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("abc");
|
||||
@@ -491,7 +491,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
repository.save(sampleEntity);
|
||||
|
||||
// document 2
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId2);
|
||||
sampleEntity2.setType("xyz");
|
||||
@@ -500,7 +500,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
repository.save(sampleEntity2);
|
||||
|
||||
// document 3
|
||||
String documentId3 = randomNumeric(5);
|
||||
String documentId3 = nextIdAsString();
|
||||
SampleEntity sampleEntity3 = new SampleEntity();
|
||||
sampleEntity3.setId(documentId3);
|
||||
sampleEntity3.setType("def");
|
||||
@@ -520,7 +520,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldExecuteCustomMethodWithBooleanParameter() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -529,7 +529,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
repository.save(sampleEntity);
|
||||
|
||||
// given
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId2);
|
||||
sampleEntity2.setType("test");
|
||||
@@ -549,7 +549,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldReturnPageableInUnwrappedPageResult() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -558,7 +558,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
repository.save(sampleEntity);
|
||||
|
||||
// given
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId2);
|
||||
sampleEntity2.setType("test");
|
||||
@@ -601,21 +601,21 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldReturnPageableResultsWithGivenSortingOrder() {
|
||||
|
||||
// given
|
||||
String documentId = random(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setMessage("abc");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
repository.save(sampleEntity);
|
||||
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId2);
|
||||
sampleEntity2.setMessage("abd");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
repository.save(sampleEntity2);
|
||||
|
||||
String documentId3 = randomNumeric(5);
|
||||
String documentId3 = nextIdAsString();
|
||||
SampleEntity sampleEntity3 = new SampleEntity();
|
||||
sampleEntity3.setId(documentId3);
|
||||
sampleEntity3.setMessage("abe");
|
||||
@@ -635,21 +635,21 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldReturnListForMessage() {
|
||||
|
||||
// given
|
||||
String documentId = random(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setMessage("abc");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
repository.save(sampleEntity);
|
||||
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId2);
|
||||
sampleEntity2.setMessage("abd");
|
||||
sampleEntity.setVersion(System.currentTimeMillis());
|
||||
repository.save(sampleEntity2);
|
||||
|
||||
String documentId3 = randomNumeric(5);
|
||||
String documentId3 = nextIdAsString();
|
||||
SampleEntity sampleEntity3 = new SampleEntity();
|
||||
sampleEntity3.setId(documentId3);
|
||||
sampleEntity3.setMessage("abe");
|
||||
@@ -667,7 +667,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldExecuteCustomMethodWithGeoPoint() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -689,7 +689,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldExecuteCustomMethodWithGeoPointAndString() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -699,7 +699,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
|
||||
repository.save(sampleEntity);
|
||||
|
||||
documentId = randomNumeric(5);
|
||||
documentId = nextIdAsString();
|
||||
sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -722,7 +722,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldExecuteCustomMethodWithWithinGeoPoint() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -745,7 +745,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldExecuteCustomMethodWithWithinPoint() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -768,7 +768,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldExecuteCustomMethodWithNearBox() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -778,7 +778,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
|
||||
repository.save(sampleEntity);
|
||||
|
||||
documentId = randomNumeric(5);
|
||||
documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId);
|
||||
sampleEntity2.setType("test2");
|
||||
@@ -808,7 +808,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldExecuteCustomMethodWithNearPointAndDistance() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -846,7 +846,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldCountCustomMethod() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -854,7 +854,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
|
||||
repository.save(sampleEntity);
|
||||
|
||||
documentId = randomNumeric(5);
|
||||
documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId);
|
||||
sampleEntity2.setType("test2");
|
||||
@@ -873,7 +873,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldCountCustomMethodForNot() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("some");
|
||||
@@ -881,7 +881,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
|
||||
repository.save(sampleEntity);
|
||||
|
||||
documentId = randomNumeric(5);
|
||||
documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId);
|
||||
sampleEntity2.setType("test");
|
||||
@@ -900,7 +900,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldCountCustomMethodWithBooleanParameter() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -909,7 +909,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
repository.save(sampleEntity);
|
||||
|
||||
// given
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId2);
|
||||
sampleEntity2.setType("test");
|
||||
@@ -928,7 +928,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldCountCustomMethodWithLessThan() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -936,7 +936,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
sampleEntity.setMessage("some message");
|
||||
repository.save(sampleEntity);
|
||||
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId2);
|
||||
sampleEntity2.setType("test");
|
||||
@@ -955,7 +955,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldCountCustomMethodWithBefore() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -964,7 +964,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
|
||||
repository.save(sampleEntity);
|
||||
|
||||
documentId = randomNumeric(5);
|
||||
documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId);
|
||||
sampleEntity2.setType("test");
|
||||
@@ -984,7 +984,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldCountCustomMethodWithAfter() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -993,7 +993,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
|
||||
repository.save(sampleEntity);
|
||||
|
||||
documentId = randomNumeric(5);
|
||||
documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId);
|
||||
sampleEntity2.setType("test");
|
||||
@@ -1013,7 +1013,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldCountCustomMethodWithLike() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -1022,7 +1022,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
|
||||
repository.save(sampleEntity);
|
||||
|
||||
documentId = randomNumeric(5);
|
||||
documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId);
|
||||
sampleEntity2.setType("test");
|
||||
@@ -1042,7 +1042,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldCountCustomMethodForStartingWith() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -1051,7 +1051,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
|
||||
repository.save(sampleEntity);
|
||||
|
||||
documentId = randomNumeric(5);
|
||||
documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId);
|
||||
sampleEntity2.setType("test");
|
||||
@@ -1071,7 +1071,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldCountCustomMethodForEndingWith() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -1080,7 +1080,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
|
||||
repository.save(sampleEntity);
|
||||
|
||||
documentId = randomNumeric(5);
|
||||
documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId);
|
||||
sampleEntity2.setType("test");
|
||||
@@ -1100,7 +1100,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldCountCustomMethodForContains() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -1109,7 +1109,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
|
||||
repository.save(sampleEntity);
|
||||
|
||||
documentId = randomNumeric(5);
|
||||
documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId);
|
||||
sampleEntity2.setType("test");
|
||||
@@ -1129,7 +1129,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldCountCustomMethodForIn() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -1137,7 +1137,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
repository.save(sampleEntity);
|
||||
|
||||
// given
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId2);
|
||||
sampleEntity2.setType("test");
|
||||
@@ -1157,7 +1157,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldCountCustomMethodForNotIn() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -1165,7 +1165,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
repository.save(sampleEntity);
|
||||
|
||||
// given
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId2);
|
||||
sampleEntity2.setType("test");
|
||||
@@ -1185,7 +1185,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldCountCustomMethodForTrue() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -1194,7 +1194,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
repository.save(sampleEntity);
|
||||
|
||||
// given
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId2);
|
||||
sampleEntity2.setType("test");
|
||||
@@ -1212,7 +1212,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldCountCustomMethodForFalse() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -1221,7 +1221,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
repository.save(sampleEntity);
|
||||
|
||||
// given
|
||||
String documentId2 = randomNumeric(5);
|
||||
String documentId2 = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId2);
|
||||
sampleEntity2.setType("test");
|
||||
@@ -1240,7 +1240,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldCountCustomMethodWithWithinGeoPoint() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -1250,7 +1250,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
|
||||
repository.save(sampleEntity);
|
||||
|
||||
documentId = randomNumeric(5);
|
||||
documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId);
|
||||
sampleEntity2.setType("test");
|
||||
@@ -1271,7 +1271,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldCountCustomMethodWithWithinPoint() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -1281,7 +1281,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
|
||||
repository.save(sampleEntity);
|
||||
|
||||
documentId = randomNumeric(5);
|
||||
documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId);
|
||||
sampleEntity2.setType("test");
|
||||
@@ -1302,7 +1302,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldCountCustomMethodWithNearBox() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -1312,7 +1312,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
|
||||
repository.save(sampleEntity);
|
||||
|
||||
documentId = randomNumeric(5);
|
||||
documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId);
|
||||
sampleEntity2.setType("test2");
|
||||
@@ -1333,7 +1333,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
public void shouldCountCustomMethodWithNearPointAndDistance() {
|
||||
|
||||
// given
|
||||
String documentId = randomNumeric(5);
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
@@ -1343,7 +1343,7 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
|
||||
repository.save(sampleEntity);
|
||||
|
||||
documentId = randomNumeric(5);
|
||||
documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId);
|
||||
sampleEntity2.setType("test");
|
||||
|
||||
+4
-4
@@ -16,11 +16,11 @@
|
||||
package org.springframework.data.elasticsearch.repositories.doubleid;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.springframework.data.elasticsearch.utils.IdGenerator.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.commons.lang.math.RandomUtils;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -75,13 +75,13 @@ public class DoubleIDRepositoryTests {
|
||||
public void shouldDoBulkIndexDocument() {
|
||||
|
||||
// given
|
||||
Double documentId1 = RandomUtils.nextDouble();
|
||||
Double documentId1 = nextIdAsDouble();
|
||||
DoubleIDEntity sampleEntity1 = new DoubleIDEntity();
|
||||
sampleEntity1.setId(documentId1);
|
||||
sampleEntity1.setMessage("some message");
|
||||
sampleEntity1.setVersion(System.currentTimeMillis());
|
||||
|
||||
Double documentId2 = RandomUtils.nextDouble();
|
||||
Double documentId2 = nextIdAsDouble();
|
||||
DoubleIDEntity sampleEntity2 = new DoubleIDEntity();
|
||||
sampleEntity2.setId(documentId2);
|
||||
sampleEntity2.setMessage("some message");
|
||||
@@ -102,7 +102,7 @@ public class DoubleIDRepositoryTests {
|
||||
public void shouldSaveDocument() {
|
||||
|
||||
// given
|
||||
Double documentId = RandomUtils.nextDouble();
|
||||
Double documentId = nextIdAsDouble();
|
||||
DoubleIDEntity sampleEntity = new DoubleIDEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setMessage("some message");
|
||||
|
||||
+10
-12
@@ -87,35 +87,37 @@ public class DynamicIndexEntityTests {
|
||||
|
||||
int initialCallsCount = indexNameProvider.callsCount;
|
||||
|
||||
indexNameProvider.setIndexName("index1");
|
||||
indexNameProvider.indexName = "index1";
|
||||
repository.save(new DynamicIndexEntity());
|
||||
assertThat(indexNameProvider.callsCount > initialCallsCount).isTrue();
|
||||
assertThat(repository.count()).isEqualTo(1L);
|
||||
|
||||
indexNameProvider.setIndexName("index2");
|
||||
indexNameProvider.indexName = "index2";
|
||||
assertThat(repository.count()).isEqualTo(0L);
|
||||
}
|
||||
|
||||
@Test // DATAES-821
|
||||
void indexOpsShouldUseDynamicallyProvidedName() {
|
||||
|
||||
indexNameProvider.setIndexName("test-dynamic");
|
||||
IndexOperations indexOps = operations.indexOps(DynamicIndexEntity.class);
|
||||
indexNameProvider.indexName = "index-dynamic";
|
||||
indexNameProvider.callsCount = 0;
|
||||
|
||||
int initialCallsCount = indexNameProvider.callsCount;
|
||||
operations.indexOps(IndexCoordinates.of("index-dynamic")).delete();
|
||||
|
||||
IndexOperations indexOps = operations.indexOps(DynamicIndexEntity.class);
|
||||
indexOps.create();
|
||||
indexOps.refresh();
|
||||
indexOps.refresh();
|
||||
indexOps.delete();
|
||||
indexOps.delete(); // internally calls doExists
|
||||
|
||||
assertThat(indexNameProvider.callsCount - initialCallsCount).isEqualTo(4);
|
||||
assertThat(indexNameProvider.callsCount).isGreaterThan(0);
|
||||
}
|
||||
|
||||
static class IndexNameProvider {
|
||||
|
||||
private String indexName;
|
||||
|
||||
int callsCount;
|
||||
private int callsCount;
|
||||
|
||||
public String getIndexName() {
|
||||
|
||||
@@ -123,10 +125,6 @@ public class DynamicIndexEntityTests {
|
||||
return indexName;
|
||||
}
|
||||
|
||||
public void setIndexName(String indexName) {
|
||||
this.indexName = indexName;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Document(indexName = "#{@indexNameProvider.getIndexName()}", createIndex = false)
|
||||
|
||||
+4
-4
@@ -16,11 +16,11 @@
|
||||
package org.springframework.data.elasticsearch.repositories.integer;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.springframework.data.elasticsearch.utils.IdGenerator.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.commons.lang.math.RandomUtils;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -76,13 +76,13 @@ public class IntegerIDRepositoryTests {
|
||||
public void shouldDoBulkIndexDocument() {
|
||||
|
||||
// given
|
||||
Integer documentId1 = RandomUtils.nextInt();
|
||||
Integer documentId1 = nextIdAsInt();
|
||||
IntegerIDEntity sampleEntity1 = new IntegerIDEntity();
|
||||
sampleEntity1.setId(documentId1);
|
||||
sampleEntity1.setMessage("some message");
|
||||
sampleEntity1.setVersion(System.currentTimeMillis());
|
||||
|
||||
Integer documentId2 = RandomUtils.nextInt();
|
||||
Integer documentId2 = nextIdAsInt();
|
||||
IntegerIDEntity sampleEntity2 = new IntegerIDEntity();
|
||||
sampleEntity2.setId(documentId2);
|
||||
sampleEntity2.setMessage("some message");
|
||||
@@ -103,7 +103,7 @@ public class IntegerIDRepositoryTests {
|
||||
public void shouldSaveDocument() {
|
||||
|
||||
// given
|
||||
Integer documentId = RandomUtils.nextInt();
|
||||
Integer documentId = nextIdAsInt();
|
||||
IntegerIDEntity sampleEntity = new IntegerIDEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setMessage("some message");
|
||||
|
||||
+2
-2
@@ -16,8 +16,8 @@
|
||||
|
||||
package org.springframework.data.elasticsearch.repositories.nestedobject;
|
||||
|
||||
import static org.apache.commons.lang.RandomStringUtils.*;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.springframework.data.elasticsearch.utils.IdGenerator.*;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
@@ -85,7 +85,7 @@ public class InnerObjectTests {
|
||||
public void shouldIndexInnerObject() {
|
||||
|
||||
// given
|
||||
String id = randomAlphanumeric(5);
|
||||
String id = nextIdAsString();
|
||||
Book book = new Book();
|
||||
book.setId(id);
|
||||
book.setName("xyz");
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user