Make the new client the default.

Original Pull Request #2208
Closes #2159
This commit is contained in:
Peter-Josef Meisch 2022-07-03 21:56:21 +02:00 committed by GitHub
parent 81e2613669
commit 094e79d601
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 279 additions and 186 deletions

View File

@ -22,11 +22,14 @@
<elasticsearch-rhlc>7.17.4</elasticsearch-rhlc>
<!-- version of the new ElasticsearchClient -->
<elasticsearch-java>8.2.3</elasticsearch-java>
<log4j>2.17.2</log4j>
<netty>4.1.65.Final</netty>
<springdata.commons>3.0.0-SNAPSHOT</springdata.commons>
<testcontainers>1.16.2</testcontainers>
<blockhound-junit>1.0.6.RELEASE</blockhound-junit>
<java-module-name>spring.data.elasticsearch</java-module-name>
<!--
@ -137,11 +140,12 @@
<scope>test</scope>
</dependency>
<!-- Elasticsearch RestHighLevelClient, will be removed probably in SDE 5 -->
<!-- optional Elasticsearch RestHighLevelClient, deprecated in SDE 5.0 -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>${elasticsearch-rhlc}</version>
<optional>true</optional>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>

View File

@ -49,4 +49,5 @@ built and tested.
| Ingallsfootnote:oom[] | 2.1.xfootnote:oom[] | 2.4.0 | 4.3.25 | 1.5.x
|===
Support for upcoming versions of Elasticsearch is being tracked and general compatibility should be given assuming the usage of the <<elasticsearch.clients.rest,high-level REST client>>.
Support for upcoming versions of Elasticsearch is being tracked and general compatibility should be given assuming
the usage of the <<elasticsearch.operations,ElasticsearchOperations interface>>.

View File

@ -6,15 +6,104 @@ This chapter illustrates configuration and usage of supported Elasticsearch clie
Spring Data Elasticsearch operates upon an Elasticsearch client that is connected to a single Elasticsearch node or a cluster.
Although the Elasticsearch Client can be used to work with the cluster, applications using Spring Data Elasticsearch normally use the higher level abstractions of <<elasticsearch.operations>> and <<elasticsearch.repositories>>.
[[elasticsearch.clients.rest]]
== High Level REST Client
[[elasticsearch.clients.restclient]]
== Imperative Rest Client
The Java High Level REST Client is the default client of Elasticsearch, it is configured like shown:
To use the imperative (non-reactive) client, a configuration bean must be configured like this:
.High Level REST Client
====
[source,java]
----
import org.springframework.data.elasticsearch.client.elc.ElasticsearchConfiguration;
@Configuration
public class MyClientConfig extends ElasticsearchConfiguration {
@Override
public ClientConfiguration clientConfiguration() {
return ClientConfiguration.builder() //
.connectedTo("localhost:9200") //
.build();
}
}
// ...
@Autowired
ElasticsearchOperations operations; <.>
@Autowired
ElasticsearchClient elasticsearchClient; <.>
@Autowired
RestClient restClient; <.>
----
the following can be injected:
<.> an implementation of `ElasticsearchOperations`
<.> the `co.elastic.clients.elasticsearch.ElasticsearchClient` that is used. This is new Elasticsearch client
implementation.
<.> the low level `RestClient` from the Elasticsearch libraries
====
Basically one should just use the `ElasticsearchOperations` to interact with the Elasticsearch cluster. When using
repositories, this instance is used under the hood as well.
[[elasticsearch.clients.reactiverestclient]]
== Reactive Rest Client
When working with the reactive stack, the configuration must be derived from a different class:
====
[source,java]
----
import org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchConfiguration;
@Configuration
public class MyClientConfig extends ElasticsearchConfiguration {
@Override
public ClientConfiguration clientConfiguration() {
return ClientConfiguration.builder() //
.connectedTo("localhost:9200") //
.build();
}
}
// ...
@Autowired
ReactiveElasticsearchOperations operations; <.>
@Autowired
ReactiveElasticsearchClient elasticsearchClient; <.>
@Autowired
RestClient restClient; <.>
----
the following can be injected:
<.> an implementation of `ElasticsearchOperations`
<.> the `org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchClient` that is used. This is based
on the new Elasticsearch client implementation.
<.> the low level `RestClient` from the Elasticsearch libraries
====
Basically one should just use the `ReactiveElasticsearchOperations` to interact with the Elasticsearch cluster. When
using repositories, this instance is used under the hood as well.
[[elasticsearch.clients.resthighlevelclient]]
== High Level REST Client (deprecated)
The Java RestHighLevelClient is deprecated, but still can be configured like shown (read
<<elasticsearch-migration-guide-4.4-5.0.old-client>> as well):
.RestHighLevelClient
====
[source,java]
----
import org.springframework.data.elasticsearch.client.erhlc.AbstractElasticsearchConfiguration;
@Configuration
public class RestClientConfig extends AbstractElasticsearchConfiguration {
@ -53,16 +142,21 @@ IndexResponse response = highLevelClient.index(request,RequestOptions.DEFAULT);
====
[[elasticsearch.clients.reactive]]
== Reactive Client
== Reactive Client (deprecated)
The `ReactiveElasticsearchClient` is a non official driver based on `WebClient`.
The `org.springframework.data.elasticsearch.client.erhlc.ReactiveElasticsearchClient` is a non official driver based on `WebClient`.
It uses the request/response objects provided by the Elasticsearch core project.
Calls are directly operated on the reactive stack, **not** wrapping async (thread pool bound) responses into reactive types.
.Reactive REST Client
This was the first reactive implementation Spring Data Elasticsearch provided, but now is deprecated in favour of the `org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchClient`
which uses the functionality offered by the new Elasticsearch client libraries.
.Reactive REST Client (deprecated)
====
[source,java]
----
import org.springframework.data.elasticsearch.client.erhlc.AbstractReactiveElasticsearchConfiguration;
@Configuration
public class ReactiveRestClientConfig extends AbstractReactiveElasticsearchConfiguration {
@ -89,8 +183,6 @@ Mono<IndexResponse> response = client.index(request ->
<.> Use the builder to provide cluster addresses, set default `HttpHeaders` or enable SSL.
====
NOTE: The ReactiveClient response, especially for search operations, is bound to the `from` (offset) & `size` (limit) options of the request.
[[elasticsearch.clients.configuration]]
== Client Configuration
@ -118,12 +210,7 @@ ClientConfiguration clientConfiguration = ClientConfiguration.builder()
return headers;
})
.withClientConfigurer( <.>
ReactiveRestClients.WebClientConfigurationCallback.from(webClient -> {
// ...
return webClient;
}))
.withClientConfigurer( <.>
RestClients.RestClientConfigurationCallback.from(clientBuilder -> {
ElasticsearchClients.ElasticsearchClientConfigurationCallback.from(clientBuilder -> {
// ...
return clientBuilder;
}))
@ -144,8 +231,7 @@ Default is 5 sec.
<.> Optionally set headers.
<.> Add basic authentication.
<.> A `Supplier<Header>` function can be specified which is called every time before a request is sent to Elasticsearch - here, as an example, the current time is written in a header.
<.> for reactive setup a function configuring the `WebClient`
<.> for non-reactive setup a function configuring the REST client
<.> a function configuring the low level REST client (the same for the imperative and reactive stack)
====
IMPORTANT: Adding a Header supplier as shown in above example allows to inject headers that may change over the time, like authentication JWT tokens.
@ -153,7 +239,7 @@ If this is used in the reactive setup, the supplier function *must not* block!
=== Elasticsearch 7 compatibility headers
When using Spring Data Elasticsearch 4 - which uses the Elasticsearch 7 client libraries - and accessing an Elasticsearch cluster that is running on version 8, it is necessary to set the compatibility headers
When using the deprecated `RestHighLevelClient` and accessing an Elasticsearch cluster that is running on version 8, it is necessary to set the compatibility headers
https://www.elastic.co/guide/en/elasticsearch/reference/8.0/rest-api-compatibility.html[see Elasticsearch
documentation].

View File

@ -211,7 +211,7 @@ void init() {
== Retrieving data
Currently native search queries must be used to query the data, so there is no support from standard repository methods. <<repositories.custom-implementations>> can be used instead.
Currently native queries must be used to query the data, so there is no support from standard repository methods. <<repositories.custom-implementations>> can be used instead.
The following code shows as an example how to retrieve all entries that have a _vote_ (which must be _answers_, because only answers can have a vote) using an `ElasticsearchOperations` instance:
@ -219,11 +219,17 @@ The following code shows as an example how to retrieve all entries that have a _
[source,java]
----
SearchHits<Statement> hasVotes() {
NativeSearchQuery query = new NativeSearchQueryBuilder()
.withQuery(hasChildQuery("vote", matchAllQuery(), ScoreMode.None))
.build();
return operations.search(query, Statement.class);
Query query = NativeQuery.builder()
.withQuery(co.elastic.clients.elasticsearch._types.query_dsl.Query.of(qb -> qb //
.hasChild(hc -> hc
.queryName("vote") //
.query(matchAllQueryAsQuery()) //
.scoreMode(ChildScoreMode.None)//
)))
.build();
return operations.search(query, Statement.class);
}
----
====

View File

@ -32,6 +32,11 @@ using the old deprecated Elasticsearch libraries, code using the new Elasticsear
independent of the client implementation. Also the reactive implementation that was provided up to now has been moved
here, as this implementation contains code that was copied and adapted from Elasticsearch libraries.
If you are using `ElasticsearchRestTemplate` directly and not the `ElasticsearchOperations` interface you'll need to
adjust your imports as well.
When working with the `NativeSearchQuery` class, you'll need to switch to the `NativeQuery` class, which can take a
`Query` instance comign from the new Elasticsearch client libraries. You'll find plenty of examples in the test code.
[[elasticsearch-migration-guide-4.4-5.0.new-clients]]
== New Elasticsearch client
@ -39,58 +44,7 @@ here, as this implementation contains code that was copied and adapted from Elas
Spring Data Elasticsearch now uses the new `ElasticsearchClient` and has
deprecated the use of the previous `RestHighLevelClient`.
=== How to use the new client
In order to use the new client the following steps are necessary:
==== Add dependencies
The dependencies for the new Elasticsearch client are still optional in Spring Data Elasticsearch so they need to be added explicitly:
====
[source,xml]
----
<dependencies>
<dependency>
<groupId>co.elastic.clients</groupId>
<artifactId>elasticsearch-java</artifactId>
<version>7.17.3</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId> <!-- is Apache 2-->
<version>7.17.3</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
----
====
When using Spring Boot, it is necessary to set the following property in the _pom.xml_.
====
[source,xml]
----
<properties>
<jakarta-json.version>2.0.1</jakarta-json.version>
</properties>
----
====
==== New configuration classes
===== Imperative style
=== Imperative style configuration
To configure Spring Data Elasticsearch to use the new client, it is necessary to create a configuration bean that
derives from `org.springframework.data.elasticsearch.client.elc.ElasticsearchConfiguration`:
@ -118,7 +72,7 @@ With this configuration, the following beans will be available in the Spring app
* an `ElasticsearchClient` bean, this is the new client that uses the `RestClient`
* an `ElasticsearchOperations` bean, available with the bean names _elasticsearchOperations_ and _elasticsearchTemplate_, this uses the `ElasticsearchClient`
===== Reactive style
=== Reactive style configuration
To use the new client in a reactive environment the only difference is the class from which to derive the configuration:
@ -143,3 +97,29 @@ With this configuration, the following beans will be available in the Spring app
* a `RestClient` bean, that is the configured low level `RestClient` that is used by the Elasticsearch client
* an `ReactiveElasticsearchClient` bean, this is the new reactive client that uses the `RestClient`
* an `ReactiveElasticsearchOperations` bean, available with the bean names _reactiveElasticsearchOperations_ and _reactiveElasticsearchTemplate_, this uses the `ReactiveElasticsearchClient`
[[elasticsearch-migration-guide-4.4-5.0.old-client]]
=== Still want to use the old client?
The old deprecated `RestHighLevelClient` can still be used, but you will need to add the dependency explicitly to
your application as Spring Data Elasticsearch does not pull it in automatically anymore:
====
[source,xml]
----
<!-- include the RHLC, specify version explicitly -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.17.4</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
----
====
Make sure to specify the version 7.17.4 explicitly, otherwise maven will resolve to 8.2.3, and this does not exist.

View File

@ -87,12 +87,19 @@ private ElasticsearchOperations operations;
IndexCoordinates index = IndexCoordinates.of("sample-index");
SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(matchAllQuery())
.withFilter(boolFilter().must(termFilter("id", documentId)))
.build();
Query query = NativeQuery.builder()
.withQuery(q -> q
.matchAll(ma -> ma))
.withFilter( q -> q
.bool(b -> b
.must(m -> m
.term(t -> t
.field("id")
.value(documentId))
)))
.build();
Page<SampleEntity> sampleEntities = operations.searchForPage(searchQuery, SampleEntity.class, index);
SearchHits<SampleEntity> sampleEntities = operations.search(query, SampleEntity.class, index);
----
====
@ -107,13 +114,15 @@ This is internally used by Spring Data Elasticsearch to provide the implementati
----
IndexCoordinates index = IndexCoordinates.of("sample-index");
SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(matchAllQuery())
.withFields("message")
.withPageable(PageRequest.of(0, 10))
.build();
Query searchQuery = NativeQuery.builder()
.withQuery(q -> q
.matchAll(ma -> ma))
.withFields("message")
.withPageable(PageRequest.of(0, 10))
.build();
SearchHitsIterator<SampleEntity> stream = elasticsearchTemplate.searchForStream(searchQuery, SampleEntity.class, index);
SearchHitsIterator<SampleEntity> stream = elasticsearchOperations.searchForStream(searchQuery, SampleEntity.class,
index);
List<SampleEntity> sampleEntities = new ArrayList<>();
while (stream.hasNext()) {
@ -124,23 +133,28 @@ stream.close();
----
====
There are no methods in the `SearchOperations` API to access the scroll id, if it should be necessary to access this, the following methods of the `ElasticsearchRestTemplate` can be used:
There are no methods in the `SearchOperations` API to access the scroll id, if it should be necessary to access this,
the following methods of the `AbstractElasticsearchTemplate` can be used (this is the base implementation for the
different `ElasticsearchOperations` implementations:
====
[source,java]
----
@Autowired ElasticsearchRestTemplate template;
@Autowired ElasticsearchOperations operations;
AbstractElasticsearchTemplate template = (AbstractElasticsearchTemplate)operations;
IndexCoordinates index = IndexCoordinates.of("sample-index");
SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(matchAllQuery())
.withFields("message")
.withPageable(PageRequest.of(0, 10))
.build();
Query query = NativeQuery.builder()
.withQuery(q -> q
.matchAll(ma -> ma))
.withFields("message")
.withPageable(PageRequest.of(0, 10))
.build();
SearchScrollHits<SampleEntity> scroll = template.searchScrollStart(1000, searchQuery, SampleEntity.class, index);
SearchScrollHits<SampleEntity> scroll = template.searchScrollStart(1000, query, SampleEntity.class, index);
String scrollId = scroll.getScrollId();
List<SampleEntity> sampleEntities = new ArrayList<>();

View File

@ -6,6 +6,7 @@
* Upgrade to Java 17 baseline
* Upgrade to Spring Framework 6
* Use the new Elasticsearch client library
[[new-features.4-4-0]]
== New in Spring Data Elasticsearch 4.4

View File

@ -30,36 +30,10 @@ There is support for automatic creation of indices and writing the mappings when
====
[[elasticsearch.operations.resttemplate]]
== ElasticsearchRestTemplate
The `ElasticsearchRestTemplate` is an implementation of the `ElasticsearchOperations` interface using the <<elasticsearch.clients.rest>>.
.ElasticsearchRestTemplate configuration
====
[source,java]
----
@Configuration
public class RestClientConfig extends AbstractElasticsearchConfiguration {
@Override
public RestHighLevelClient elasticsearchClient() { <1>
return RestClients.create(ClientConfiguration.localhost()).rest();
}
// no special bean creation needed <2>
}
----
<1> Setting up the <<elasticsearch.clients.rest>>.
<2> The base class `AbstractElasticsearchConfiguration` already provides the `elasticsearchTemplate` bean.
====
[[elasticsearch.operations.usage]]
== Usage examples
As both `ElasticsearchTemplate` and `ElasticsearchRestTemplate` implement the `ElasticsearchOperations` interface, the code to use them is not different.
The example shows how to use an injected `ElasticsearchOperations` instance in a Spring REST controller.
The decision, if this is using the `TransportClient` or the `RestClient` is made by providing the corresponding Bean with one of the configurations shown above.
.ElasticsearchOperations usage
====
@ -150,7 +124,7 @@ An Iterator returned by the streaming functions of the `SearchOperations` interf
[[elasticsearch.operations.queries]]
== Queries
Almost all of the methods defined in the `SearchOperations` and `ReactiveSearchOperations` interface take a `Query` parameter that defines the query to execute for searching. `Query` is an interface and Spring Data Elasticsearch provides three implementations: `CriteriaQuery`, `StringQuery` and `NativeSearchQuery`.
Almost all of the methods defined in the `SearchOperations` and `ReactiveSearchOperations` interface take a `Query` parameter that defines the query to execute for searching. `Query` is an interface and Spring Data Elasticsearch provides three implementations: `CriteriaQuery`, `StringQuery` and `NativeQuery`.
[[elasticsearch.operations.criteriaquery]]
=== CriteriaQuery
@ -238,21 +212,28 @@ SearchHits<Person> searchHits = operations.search(query, Person.class);
Using `StringQuery` may be appropriate if you already have an Elasticsearch query to use.
[[elasticsearch.operations.nativesearchquery]]
=== NativeSearchQuery
[[elasticsearch.operations.nativequery]]
=== NativeQuery
`NativeSearchQuery` is the class to use when you have a complex query, or a query that cannot be expressed by using the `Criteria` API, for example when building queries and using aggregates.
It allows to use all the different `QueryBuilder` implementations from the Elasticsearch library therefore named "native".
`NativeQuery` is the class to use when you have a complex query, or a query that cannot be expressed by using the `Criteria` API, for example when building queries and using aggregates.
It allows to use all the different `co.elastic.clients.elasticsearch._types.query_dsl.Query` implementations from the Elasticsearch library therefore named "native".
The following code shows how to search for persons with a given firstname and for the found documents have a terms aggregation that counts the number of occurences of the lastnames for these persons:
====
[source,java]
----
Query query = new NativeSearchQueryBuilder()
.addAggregation(terms("lastnames").field("lastname").size(10)) //
.withQuery(QueryBuilders.matchQuery("firstname", firstName))
.build();
Query query = NativeQuery.builder()
.withAggregation("lastNames", Aggregation.of(a -> a
.terms(ta -> ta.field("last-name").size(10))))
.withQuery(q -> q
.match(m -> m
.field("firstName")
.query(firstName)
)
)
.withPageable(pageable)
.build();
SearchHits<Person> searchHits = operations.search(query, Person.class);
----

View File

@ -19,7 +19,7 @@ import co.elastic.clients.elasticsearch._types.aggregations.Aggregate;
/**
* Class to combine an Elasticsearch {@link co.elastic.clients.elasticsearch._types.aggregations.Aggregate} with its
* name. Necessary as the Elasticsearch Aggregate does not know i"s name.
* name. Necessary as the Elasticsearch Aggregate does not know its name.
*
* @author Peter-Josef Meisch
* @since 4.4

View File

@ -28,7 +28,6 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.lucene.queryparser.flexible.standard.QueryParserUtil;
import org.springframework.data.elasticsearch.annotations.FieldType;
import org.springframework.data.elasticsearch.core.query.Criteria;
import org.springframework.data.elasticsearch.core.query.Field;
@ -184,7 +183,7 @@ class CriteriaQueryProcessor {
Criteria.OperationKey key = entry.getKey();
Object value = key.hasValue() ? entry.getValue() : null;
String searchText = value != null ? QueryParserUtil.escape(value.toString()) : "UNKNOWN_VALUE";
String searchText = value != null ? escape(value.toString()) : "UNKNOWN_VALUE";
Query.Builder queryBuilder = new Query.Builder();
switch (key) {
@ -358,11 +357,32 @@ class CriteriaQueryProcessor {
sb.append(' ');
}
sb.append('"');
sb.append(QueryParserUtil.escape(item.toString()));
sb.append(escape(item.toString()));
sb.append('"');
}
}
return sb.toString();
}
/**
* Returns a String where those characters that TextParser expects to be escaped are escaped by a preceding
* <code>\</code>. Copied from Apachae 2 licensed org.apache.lucene.queryparser.flexible.standard.QueryParserUtil
* class
*/
public static String escape(String s) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
// These characters are part of the query syntax and must be escaped
if (c == '\\' || c == '+' || c == '-' || c == '!' || c == '(' || c == ')' || c == ':' || c == '^' || c == '['
|| c == ']' || c == '\"' || c == '{' || c == '}' || c == '~' || c == '*' || c == '?' || c == '|' || c == '&'
|| c == '/') {
sb.append('\\');
}
sb.append(c);
}
return sb.toString();
}
}

View File

@ -332,7 +332,7 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate {
}
@Override
protected <T> SearchScrollHits<T> searchScrollStart(long scrollTimeInMillis, Query query, Class<T> clazz,
public <T> SearchScrollHits<T> searchScrollStart(long scrollTimeInMillis, Query query, Class<T> clazz,
IndexCoordinates index) {
Assert.notNull(query, "query must not be null");
@ -345,7 +345,7 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate {
}
@Override
protected <T> SearchScrollHits<T> searchScrollContinue(String scrollId, long scrollTimeInMillis, Class<T> clazz,
public <T> SearchScrollHits<T> searchScrollContinue(String scrollId, long scrollTimeInMillis, Class<T> clazz,
IndexCoordinates index) {
Assert.notNull(scrollId, "scrollId must not be null");
@ -368,7 +368,7 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate {
}
@Override
protected void searchScrollClear(List<String> scrollIds) {
public void searchScrollClear(List<String> scrollIds) {
Assert.notNull(scrollIds, "scrollIds must not be null");

View File

@ -89,11 +89,6 @@ public class NativeQueryBuilder extends BaseQueryBuilder<NativeQuery, NativeQuer
return this;
}
public NativeQueryBuilder withFilter(@Nullable Query filter) {
this.filter = filter;
return this;
}
public NativeQueryBuilder withQuery(Function<Query.Builder, ObjectBuilder<Query>> fn) {
Assert.notNull(fn, "fn must not be null");
@ -101,6 +96,18 @@ public class NativeQueryBuilder extends BaseQueryBuilder<NativeQuery, NativeQuer
return withQuery(fn.apply(new Query.Builder()).build());
}
public NativeQueryBuilder withFilter(@Nullable Query filter) {
this.filter = filter;
return this;
}
public NativeQueryBuilder withFilter(Function<Query.Builder, ObjectBuilder<Query>> fn) {
Assert.notNull(fn, "fn must not be null");
return withFilter(fn.apply(new Query.Builder()).build());
}
public NativeQueryBuilder withAggregation(String name, Aggregation aggregation) {
Assert.notNull(name, "name must not be null");

View File

@ -32,7 +32,16 @@ import co.elastic.clients.elasticsearch._types.mapping.RuntimeFieldType;
import co.elastic.clients.elasticsearch._types.mapping.TypeMapping;
import co.elastic.clients.elasticsearch._types.query_dsl.Like;
import co.elastic.clients.elasticsearch.cluster.HealthRequest;
import co.elastic.clients.elasticsearch.core.*;
import co.elastic.clients.elasticsearch.core.BulkRequest;
import co.elastic.clients.elasticsearch.core.DeleteByQueryRequest;
import co.elastic.clients.elasticsearch.core.DeleteRequest;
import co.elastic.clients.elasticsearch.core.GetRequest;
import co.elastic.clients.elasticsearch.core.IndexRequest;
import co.elastic.clients.elasticsearch.core.MgetRequest;
import co.elastic.clients.elasticsearch.core.MsearchRequest;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.UpdateByQueryRequest;
import co.elastic.clients.elasticsearch.core.UpdateRequest;
import co.elastic.clients.elasticsearch.core.bulk.BulkOperation;
import co.elastic.clients.elasticsearch.core.bulk.CreateOperation;
import co.elastic.clients.elasticsearch.core.bulk.IndexOperation;
@ -42,7 +51,6 @@ import co.elastic.clients.elasticsearch.core.search.Highlight;
import co.elastic.clients.elasticsearch.core.search.Rescore;
import co.elastic.clients.elasticsearch.core.search.SourceConfig;
import co.elastic.clients.elasticsearch.indices.*;
import co.elastic.clients.elasticsearch.indices.ExistsRequest;
import co.elastic.clients.elasticsearch.indices.update_aliases.Action;
import co.elastic.clients.json.JsonData;
import co.elastic.clients.json.JsonpDeserializer;
@ -1022,8 +1030,6 @@ class RequestConverter {
Assert.notNull(query, "query must not be null");
Assert.notNull(indexCoordinates, "indexCoordinates must not be null");
elasticsearchConverter.updateQuery(query, clazz);
SearchRequest.Builder builder = new SearchRequest.Builder();
prepareSearchRequest(query, clazz, indexCoordinates, builder, forCount, useScroll);
@ -1052,8 +1058,7 @@ class RequestConverter {
) //
.body(bb -> bb //
.query(getQuery(param.query, param.clazz))//
.seqNoPrimaryTerm(persistentEntity.hasSeqNoPrimaryTermProperty())
.version(true)
.seqNoPrimaryTerm(persistentEntity.hasSeqNoPrimaryTermProperty()).version(true)
// todo #2156 add remaining flags for body
) //
);

View File

@ -417,29 +417,17 @@ public abstract class AbstractElasticsearchTemplate implements ElasticsearchOper
return search(query, clazz, getIndexCoordinatesFor(clazz));
}
/*
* internal use only, not for public API
*/
abstract protected <T> SearchScrollHits<T> searchScrollStart(long scrollTimeInMillis, Query query, Class<T> clazz,
abstract public <T> SearchScrollHits<T> searchScrollStart(long scrollTimeInMillis, Query query, Class<T> clazz,
IndexCoordinates index);
/*
* internal use only, not for public API
*/
abstract protected <T> SearchScrollHits<T> searchScrollContinue(String scrollId, long scrollTimeInMillis,
Class<T> clazz, IndexCoordinates index);
abstract public <T> SearchScrollHits<T> searchScrollContinue(String scrollId, long scrollTimeInMillis, Class<T> clazz,
IndexCoordinates index);
/*
* internal use only, not for public API
*/
protected void searchScrollClear(String scrollId) {
public void searchScrollClear(String scrollId) {
searchScrollClear(Collections.singletonList(scrollId));
}
/*
* internal use only, not for public API
*/
abstract protected void searchScrollClear(List<String> scrollIds);
abstract public void searchScrollClear(List<String> scrollIds);
// endregion

View File

@ -1,2 +1,2 @@
version.spring-data-elasticsearch=${project.version}
version.elasticsearch-client=${elasticsearch-rhlc}
version.elasticsearch-client=${elasticsearch-java}

View File

@ -87,29 +87,29 @@ public class DevTests {
ElasticsearchClient client = imperativeElasticsearchClient;
String index = "testindex";
String index = "testindex";
var p = new Product("p1", 42.0);
var p = new Product("p1", 42.0);
client.index(ir -> ir //
.index(index)//
.document(p));
client.index(ir -> ir //
.index(index)//
.document(p));
client.indices().flush(f -> f.index(index));
client.indices().flush(f -> f.index(index));
RuntimeField runtimeField = RuntimeField.of(rf -> rf //
.type(RuntimeFieldType.Double) //
.script(Script.of(s -> s //
.inline(i -> i. //
source("emit(doc['price'].value * 1.19)") //
) //
)) //
); //
RuntimeField runtimeField = RuntimeField.of(rf -> rf //
.type(RuntimeFieldType.Double) //
.script(Script.of(s -> s //
.inline(i -> i. //
source("emit(doc['price'].value * 1.19)") //
) //
)) //
); //
client.search(sr -> sr //
.index(index) //
.runtimeMappings("priceWithTax", Collections.singletonList(runtimeField)), //
Person.class); //
client.search(sr -> sr //
.index(index) //
.runtimeMappings("priceWithTax", Collections.singletonList(runtimeField)), //
Person.class); //
}
static class ReactiveClient {