Elasticsearch 8.x Java API Client: Transitioning from RestHighLevelClient

Transitioning to the New Java Client

Starting with Elasticsearch 7.15, the RestHighLevelClient was deprecated, making way for the new Elasticsearch Java API Client as the official standard for version 8.0 and beyond. This modern client supports virtually all Elasticsearch APIs (excluding Vector title search and Find structure), natively handles all API data types, and removes the need for raw JSON value properties.

Project Setup

Add the required dependencies to your Maven project:

<dependency>
    <groupId>co.elastic.clients</groupId>
    <artifactId>elasticsearch-java</artifactId>
    <version>8.12.0</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.15.0</version>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.30</version>
    <scope>provided</scope>
</dependency>

Establishing the Connection

To avoid repetitive boilerplate, a utility method can manage the client lifecycle:

public ElasticsearchClient buildClient() throws IOException {
    RestClient restClient = RestClient.builder(new HttpHost("127.0.0.1", 9200, "http")).build();
    ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
    return new ElasticsearchClient(transport);
}

Index Management

Creating an Index

ElasticsearchClient esClient = buildClient();
CreateIndexResponse createResponse = esClient.indices().create(req -> req.index("app_users"));
System.out.println("Index Created: " + createResponse.acknowledged());

Retrieving an Index

ElasticsearchClient esClient = buildClient();
GetIndexResponse getResponse = esClient.indices().get(req -> req.index("app_users"));
System.out.println("Index Mappings: " + getResponse.result());

Deleting an Index

ElasticsearchClient esClient = buildClient();
DeleteIndexResponse deleteResponse = esClient.indices().delete(req -> req.index("app_users"));
System.out.println("Index Deleted: " + deleteResponse.acknowledged());

Document Operations

Define a data structure for the documents:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
    private String fullName;
    private String gender;
    private Integer years;
}

Inserting a Document

ElasticsearchClient esClient = buildClient();
Person person = new Person("Alice Smith", "female", 28);
CreateResponse insertResponse = esClient.create(req -> req
    .index("app_users")
    .id("usr_001")
    .document(person)
);
System.out.println("Insert Result: " + insertResponse.result());

Fetching a Document

ElasticsearchClient esClient = buildClient();
GetResponse<Person> getResponse = esClient.get(req -> req
    .index("app_users")
    .id("usr_001"), 
    Person.class
);
System.out.println("Fetched Document: " + getResponse.source());

Updating a Document

ElasticsearchClient esClient = buildClient();
Map<String, Object> updateFields = Map.of("years", 29);
UpdateResponse<Person> updateResponse = esClient.update(req -> req
    .index("app_users")
    .id("usr_001")
    .doc(updateFields), 
    Person.class
);
System.out.println("Update Result: " + updateResponse.result());

Removing a Document

ElasticsearchClient esClient = buildClient();
DeleteResponse deleteResponse = esClient.delete(req -> req
    .index("app_users")
    .id("usr_001")
);
System.out.println("Delete Result: " + deleteResponse.result());

Bulk Document Insertion

ElasticsearchClient esClient = buildClient();
List<BulkOperation> bulkOps = List.of(
    BulkOperation.of(op -> op.create(cr -> cr.index("app_users").id("usr_002").document(new Person("Bob", "male", 32)))),
    BulkOperation.of(op -> op.create(cr -> cr.index("app_users").id("usr_003").document(new Person("Charlie", "male", 25))))
);
BulkResponse bulkResponse = esClient.bulk(req -> req.index("app_users").operations(bulkOps));
System.out.println("Bulk Insert Errors: " + bulkResponse.errors());

Bulk Document Deletion

ElasticsearchClient esClient = buildClient();
List<BulkOperation> deleteOps = List.of(
    BulkOperation.of(op -> op.delete(dr -> dr.index("app_users").id("usr_002"))),
    BulkOperation.of(op -> op.delete(dr -> dr.index("app_users").id("usr_003")))
);
BulkResponse bulkDeleteResponse = esClient.bulk(req -> req.operations(deleteOps));
System.out.println("Bulk Delete Errors: " + bulkDeleteResponse.errors());

Search Operations

Match All

ElasticsearchClient esClient = buildClient();
SearchResponse<Person> searchResponse = esClient.search(req -> req
    .index("app_users")
    .query(q -> q.matchAll(m -> m)), 
    Person.class
);
searchResponse.hits().hits().forEach(hit -> System.out.println(hit.source()));

Pagination

ElasticsearchClient esClient = buildClient();
SearchResponse<Person> pageResponse = esClient.search(req -> req
    .index("app_users")
    .query(q -> q.matchAll(m -> m))
    .from(0)
    .size(5), 
    Person.class
);
pageResponse.hits().hits().forEach(hit -> System.out.println(hit.source()));

Sorting Results

ElasticsearchClient esClient = buildClient();
SearchResponse<Person> sortResponse = esClient.search(req -> req
    .index("app_users")
    .query(q -> q.matchAll(m -> m))
    .sort(s -> s.field(f -> f.field("years").order(SortOrder.Asc))), 
    Person.class
);
sortResponse.hits().hits().forEach(hit -> System.out.println(hit.source()));

Field Filtering

ElasticsearchClient esClient = buildClient();
SearchResponse<Person> filterResponse = esClient.search(req -> req
    .index("app_users")
    .query(q -> q.matchAll(m -> m))
    .source(src -> src.filter(f -> f.includes("fullName", "years"))), 
    Person.class
);
filterResponse.hits().hits().forEach(hit -> System.out.println(hit.source()));

Boolean Combination Queries

Using must requires all conditions to be met, while should requires at least one to match.

ElasticsearchClient esClient = buildClient();
SearchResponse<Person> boolMustResponse = esClient.search(req -> req
    .index("app_users")
    .query(q -> q.bool(b -> b
        .must(m -> m.match(t -> t.field("years").query(25)))
        .mustNot(mn -> mn.match(t -> t.field("gender").query("male")))
    )), 
    Person.class
);

SearchResponse<Person> boolShouldResponse = esClient.search(req -> req
    .index("app_users")
    .query(q -> q.bool(b -> b
        .should(s -> s.match(t -> t.field("years").query(32)))
        .should(s -> s.match(t -> t.field("gender").query("male")))
    )), 
    Person.class
);

Range Queries

ElasticsearchClient esClient = buildClient();
SearchResponse<Person> rangeResponse = esClient.search(req -> req
    .index("app_users")
    .query(q -> q.range(r -> r.field("years").gte(JsonData.of(25)).lt(JsonData.of(30)))), 
    Person.class
);
rangeResponse.hits().hits().forEach(hit -> System.out.println(hit.source()));

Fuzzy Queries

ElasticsearchClient esClient = buildClient();
SearchResponse<Person> fuzzyResponse = esClient.search(req -> req
    .index("app_users")
    .query(q -> q.fuzzy(f -> f.field("fullName").value("Alce").fuzziness("1"))), 
    Person.class
);
fuzzyResponse.hits().hits().forEach(hit -> System.out.println(hit.source()));

Highlighting Matches

ElasticsearchClient esClient = buildClient();
SearchResponse<Person> highlightResponse = esClient.search(req -> req
    .index("app_users")
    .query(q -> q.term(t -> t.field("fullName").value("Alice")))
    .highlight(h -> h.fields("fullName", f -> f.preTags("<em>").postTags("</em>"))), 
    Person.class
);
highlightResponse.hits().hits().forEach(hit -> System.out.println(hit.highlight()));

Aggregation Queries

ElasticsearchClient esClient = buildClient();
SearchResponse<Person> maxAgeResponse = esClient.search(req -> req
    .index("app_users")
    .aggregations("max_years", a -> a.max(m -> m.field("years"))), 
    Person.class
);
maxAgeResponse.aggregations().get("max_years").max().value();

SearchResponse<Person> groupByAgeResponse = esClient.search(req -> req
    .index("app_users")
    .aggregations("age_distribution", a -> a.terms(t -> t.field("years"))), 
    Person.class
);
groupByAgeResponse.aggregations().get("age_distribution").lterms().buckets().array().forEach(bucket -> 
    System.out.println("Age: " + bucket.key() + ", Count: " + bucket.docCount())
);

Tags: elasticsearch java API Client Elasticsearch 8 Search Engine

Posted on Sat, 13 Jun 2026 16:16:09 +0000 by lesmckeown