A newer version is available. Check out the latest documentation.

Release highlights

edit

These are the important new features and changes in minor releases. Every release also updates the Java API Client to the latest API specification. This includes new APIs and bug fixes in the specification of existing APIs.

For a list of detailed changes, including bug fixes, please see the GitHub project realease notes.

Version 8.18

edit

Breaking changes

While we try to limit breaking changes to the minimum between minor versions of the client, all the following changes were necessary to keep the client code in sync with the server code and to fix client side bugs.

  • Removed deprecated LanguageAnalyzer
  • Removed unused NodeReloadError
  • Removed unused SearchApplicationListItem
  • Removed InferenceRequest, InferenceResponse, InferenceResult, InferenceResultVariant as part of a complete refactor of the Inference API
  • SearchRequest,SubmitRequest: indicesBoost field modified from List<Map<String,Double>> to List<NamedValue<Double>>, because the server does not accept more than one value in the map.

    • Old:

      esClient.search(s -> s
          .index("*")
          .indicesBoost(Map.of("index", 1.0))
      ,Void.class);
    • New:

      esClient.search(s -> s
          .index("*")
          .indicesBoost(NamedValue.of("index", 1.0))
      ,Void.class);
  • PutMappingRequest: dynamicTemplates field modified from List<Map<String, DynamicTemplate>> to List<NamedValue<DynamicTemplate>>, same reason as above.
  • DenseVectorIndexOptions: type field modified from String to enum DenseVectorIndexOptionsType
  • DenseVectorProperty:

    • elementType field modified from String to enum DenseVectorElementType
    • similarity field modified from String to enum DenseVectorSimilarity
  • DynamicTemplate: runtime field modified from Property to RuntimeField, fixing a previous wrong mapping of the property.
  • ObjectProperty: subobjects field modified from Boolean to Subobjects
  • TypeMapping: subobjects field modified from Boolean to Subobjects
  • FollowerIndexParameters:

    • maxOutstandingReadRequests field modified from int to Long, now optional
    • maxOutstandingWriteRequests field modified from int to Integer, now optional
    • maxReadRequestOperationCount field modified from int to Integer, now optional
    • maxWriteBufferCount field modified from int to Integer, now optional
    • maxWriteRequestOperationCount field modified from int to Integer, now optional
  • FollowRequest

    • maxOutstandingWriteRequests field modified from Long to Integer
    • maxReadRequestOperationCount field modified from Long to Integer
    • maxWriteBufferCount field modified from Long to Integer
    • maxWriteRequestOperationCount field modified from Long to Integer
  • ScriptsPainlessExecuteRequest: context field modified from String to PainlessContext
  • DataStreamWithLifecycle: lifecycle field modified from DataStreamLifecycle to DataStreamLifecycleWithRollover
  • elasticsearch.search_application.PutRequest: searchApplication field modified from SearchApplication to SearchApplicationParameters
  • TrainedModelDeploymentNodesStats: routingState field modified from TrainedModelAssignmentRoutingTable to TrainedModelAssignmentRoutingStateAndReason

New Features

  • BulkIngester retry policy

    Retry logic can now be enabled allowing the BulkIngester to retry operations that failed with error 429 (too many requests), hoping that the error will recover and the request will go through. Users can configure the desired backoff policy using the backoffPolicy() method in the BulkIngester builder:

    BulkIngester ingester = BulkIngester.of(b -> b
        .client(client)
        ...
        .listener(listener)
        .flushInterval(1000, TimeUnit.MILLISECONDS)
        .backoffPolicy(BackoffPolicy.constantBackoff(50L, 8))

    This is an example of constant backoff, meaning the single failed operation will be retried 8 times every 50 milliseconds.

  • Default class for methods requiring TDocument

    Some requests in the client require a second parameter to define the result class, for example search, meaning the compiler will complain while the query is being written, which can be annoying. We added overload methods that use Void.class as default type, so that the correct type can be eventually added later into writing the query.

    Example with search:

    • Old:

      esClient.search(s -> s
          .index("my-index")
          .query(q -> q
              .matchAll(m -> m)
          )
      ,Object.class);
    • New:

      esClient.search(s -> s
          .index("my-index")
          .query(q -> q
              .matchAll(m -> m)
          )
      );
  • Builder setters overloads with variant type

    Added more setters allowing to build requests with a specific type variant instead of having to use the parent class and then select the desired variant later.

    Example with query, where the query field can now accept a MatchAllQuery (or any other variant) directly:

    • Old:

      esClient.search(s -> s
          .index("my-index")
          .query(q -> q
              .matchAll(m -> m)
          )
      );
    • New:

      esClient.search(s -> s
          .index("my-index")
          .query(MatchAllQuery.of(m -> m))
      );

      Example with aggregations, where the aggregations field can now accept AverageAggregation (or any other variant) directly:

    • Old:

      // using functional builder shortcut
      esClient.search(s -> s
          .aggregations("agg", a -> a
              .avg(av -> av
                  .field("price")
              )
          )
      );
      
      // using Aggregation class builder
      esClient.search(s -> s
          .aggregations("agg", Aggregation.of(ag -> ag
              .avg(av -> av
                  .field("price"))
              )
          )
      );
    • New:

      esClient.search(s -> s
          .aggregations("agg", AverageAggregation.of(av -> av
              .field("price"))
          )
      );

Version 8.17

edit
  • No new feature.

Version 8.16

edit
  • ElasticsearchClient is now Closeable. Closing a client object also closes the underlying transport - #851
  • Added option to make the response body available in case of deserialization error- #886.

    • While it has always been possible to set the log level to trace and have the client print both the json bodies of the requests and responses, it’s often not the best solution because of the large amount of information printed.
    • To enable the feature:

      RestClientOptions options = new RestClientOptions(RequestOptions.DEFAULT, true);
      ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper(), options);
      ElasticsearchClient esClientWithOptions = new ElasticsearchClient(transport);
    • To retrieve the original body from the TransportException that gets thrown in case of deserialization errors:

      try{
          // some code that returns faulty json
      }
      catch (TransportException ex){
          try (RepeatableBodyResponse repeatableResponse = (RepeatableBodyResponse) ex.response()) {
              BinaryData body = repeatableResponse.body();
          }
      }

Version 8.15

edit
  • New Connector API available
  • Fixed bug in BulkIngester - #830
  • Various bug fixes, among which are #844, #847
  • Changed builders for queries that use generic types, for example:

    • Old RangeQuery:

      RangeQuery ra = RangeQuery.of(r -> r  // no distinction between various types (date, term, number)
          .field("day")
          .gte(JsonData.of("2024-06-20"))   // must use custom json for fields because there's no defined type
          .lte(JsonData.of("2024-07-05"))
          .boost(1.0F)
          .format("yyyy-MM-dd")
          .relation(RangeRelation.Contains));
    • New RangeQuery:

      RangeQuery ra = RangeQuery.of(r -> r
          .date(d -> d             // choose query type before
              .field("day")
              .gte("20-06-24")    // field now only accepts valid type for the specified query
              .lte("20-07-24")
              .boost(1.0F)
              .format("yyyy-MM-dd")
              .relation(RangeRelation.Contains)));

Version 8.14

edit
  • No new feature.

Version 8.13

edit
  • Add ES|QL helpers - #763
  • Add an example SpringBoot application - #737

Version 8.12

edit
  • No new feature.

Version 8.11

edit
  • No new feature.

Version 8.10

edit
  • Add instrumentation API and native OpenTelemetry implementation - #588, docs

Version 8.9

edit
  • Refactor RestClientTransport to allow using other http client libraries - #584

Version 8.8

edit
  • Throw a TransportException when an error response cannot be parsed - #579
  • Speed up URL path encoding and remove dependency on httpclient - #576
  • Add buffered lookahead and JsonData implementation for Jackson - #489, #567
  • Expose additional BulkIngester metrics - #513
  • Allow unparsed binary data to be used for ingestion - #508

Version 8.7

edit
  • Add BulkIngester helper - #474, #513, docs
  • Allow unparsed binary data to be used for ingestion - #508, docs
  • Add convenience method BooleanQuery.hasClauses() - #525

Version 8.6

edit
  • Allow using java.lang.reflect.Type in addition to java.lang.Class to define application types for deserialization - #438
  • Add buffered lookahead for Jackson to speed up union deserialization - #489
  • Cache the result of JsonProvider.provider() - #485

Version 8.5

edit

Version 8.4

edit

Version 8.3

edit
  • Add toString() implementation to all value classes - #269

Version 8.2

edit

Version 8.1

edit

Version 8.0

edit
  • Change the JSON-P implementation from Glassfish to Parsson - #63
  • Accept null values in lists - #68