This guide details the usage of the official Elasticsearch 6.x Java High-Level REST Client. This client is recommended for versions 6.x and above, requires JDK 1.8+, and offers compatibility across major versions. It includes functionality from the Java Low-Level REST Client for advanced scenarios. The client provides RESTful-style methods for common operations, supporting both synchronous and asynchronous calls.
Initializing the Client
Establishing a connection with the client is straightforward:
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(new HttpHost(elasticIp, elasticPort))
);
Closing the client is equally simple:
if (client != null) {
client.close();
}
Data Operations
1. Indexing Documents
Elasticsearch allows direct data indexing by specifying the index and type. You can provide a unique ID or let Elasticsearch generate one. The Java High-Level REST Client offers three methods for indexing:
Method 1: Using a JSON String
String indexName = "test1";
String typeName = "_doc";
String documentId = "1";
IndexRequest request = new IndexRequest(indexName, typeName, documentId);
String jsonString = "{" +
"\"uid\":\"1234\"," +
"\"phone\":\"12345678909\"," +
"\"msgcode\":\"1\"," +
"\"sendtime\":\"2019-03-14 01:57:04\"," +
"\"message\":\"xuwujing study Elasticsearch\"" +
"}";
request.source(jsonString, XContentType.JSON);
IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);
Method 2: Using a Map
This method automatically converts the Map to JSON format.
String indexName = "test1";
String typeName = "_doc";
String documentId = "1";
IndexRequest request = new IndexRequest(indexName, typeName, documentId);
Map<String, Object> jsonMap = new HashMap<>();
jsonMap.put("uid", 1234);
jsonMap.put("phone", 12345678909L);
jsonMap.put("msgcode", 1);
jsonMap.put("sendtime", "2019-03-14 01:57:04");
jsonMap.put("message", "xuwujing study Elasticsearch");
request.source(jsonMap);
IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);
Method 3: Using XContentBuilder
String indexName = "test1";
String typeName = "_doc";
String documentId = "1";
IndexRequest request = new IndexRequest(indexName, typeName, documentId);
XContentBuilder builder = XContentFactory.jsonBuilder();
builder.startObject();
{
builder.field("uid", 1234);
builder.field("phone", 12345678909L);
builder.field("msgcode", 1);
builder.timeField("sendtime", "2019-03-14 01:57:04");
builder.field("message", "xuwujing study Elasticsearch");
}
builder.endObject();
request.source(builder);
IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);
The Map-based approach (Method 2) is generally recommended for its clarity and ease of use.
2. Creating an Index
While data indexing can implicitly create an index, it's best practice to define indices explicitly with desired configurations (shards, replicas, mappings) to avoid default settings that might not be optimal. Shard count cannot be changed after index creation without reindexing.
private static void createIndex(RestHighLevelClient client) throws IOException {
String typeName = "_doc";
String indexName = "test1";
Map<String, Object> settingsMap = new HashMap<>();
settingsMap.put("number_of_shards", 10);
settingsMap.put("number_of_replicas", 1);
settingsMap.put("refresh_interval", "5s");
Map<String, Object> uidField = new HashMap<>();
uidField.put("type", "long");
Map<String, Object> phoneField = new HashMap<>();
phoneField.put("type", "long");
Map<String, Object> msgcodeField = new HashMap<>();
msgcodeField.put("type", "long");
Map<String, Object> messageField = new HashMap<>();
messageField.put("type", "keyword");
Map<String, Object> sendtimeField = new HashMap<>();
sendtimeField.put("type", "date");
sendtimeField.put("format", "yyyy-MM-dd HH:mm:ss");
Map<String, Object> propertiesMap = new HashMap<>();
propertiesMap.put("uid", uidField);
propertiesMap.put("phone", phoneField);
propertiesMap.put("msgcode", msgcodeField);
propertiesMap.put("message", messageField);
propertiesMap.put("sendtime", sendtimeField);
Map<String, Object> mappingMap = new HashMap<>();
mappingMap.put("properties", propertiesMap);
Map<String, Object> typeMapping = new HashMap<>();
typeMapping.put(typeName, mappingMap);
GetIndexRequest getRequest = new GetIndexRequest();
getRequest.indices(indexName);
boolean exists = client.indices().exists(getRequest, RequestOptions.DEFAULT);
if (exists) {
System.out.println("Index '" + indexName + "' already exists.");
return;
}
CreateIndexRequest request = new CreateIndexRequest(indexName);
request.settings(settingsMap);
request.mapping(typeName, mappingMap); // Use mappingMap directly for the type
request.alias(new Alias("pancm_alias")); // Example alias
CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);
if (createIndexResponse.isAcknowledged()) {
System.out.println("Index '" + indexName + "' created successfully.");
}
}
Note: Always check for index existence before attempting creation.
3. Updating Documents
Elasticsearch offers two update methods: direct update (throws an exception if the document doesn't exist) and upsert (inserts if it doesn't exist). The upsert behavior is generally more convenient.
private static void updateDocument(RestHighLevelClient client) throws IOException {
String indexName = "test1";
String typeName = "_doc";
String documentId = "1";
UpdateRequest updateRequest = new UpdateRequest();
updateRequest.index(indexName);
updateRequest.type(typeName);
updateRequest.id(documentId);
Map<String, Object> updateFields = new HashMap<>();
updateFields.put("uid", 12345);
updateFields.put("phone", 123456789019L);
updateFields.put("msgcode", 2);
updateFields.put("sendtime", "2019-03-14 01:57:04");
updateFields.put("message", "xuwujing updated Elasticsearch");
updateRequest.doc(updateFields);
// Set docAsUpsert to true to insert if the document does not exist
updateRequest.docAsUpsert(true);
client.update(updateRequest, RequestOptions.DEFAULT);
System.out.println("Document update initiated.");
}
Note: docAsUpsert(true) enables insertion if the document is not found.
4. Deleting Documents
By ID
private static void deleteDocumentById(RestHighLevelClient client) throws IOException {
String indexName = "test1";
String typeName = "_doc";
String documentId = "1";
DeleteRequest deleteRequest = new DeleteRequest();
deleteRequest.index(indexName);
deleteRequest.type(typeName);
deleteRequest.id(documentId);
deleteRequest.timeout(TimeValue.timeValueMinutes(2));
deleteRequest.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL); // Ensures changes are visible after delete
DeleteResponse deleteResponse = client.delete(deleteRequest, RequestOptions.DEFAULT);
System.out.println("Delete operation acknowledged: " + deleteResponse.getResult());
}
By Query
private static void deleteDocumentsByQuery(RestHighLevelClient client) throws IOException {
String indexName = "test1";
String typeName = "_doc";
DeleteByQueryRequest request = new DeleteByQueryRequest(indexName, typeName);
// Define deletion criteria using QueryBuilders
request.setQuery(QueryBuilders.termsQuery("uid", 1234));
BulkByScrollResponse bulkResponse = client.deleteByQuery(request, RequestOptions.DEFAULT);
System.out.println("Deleted " + bulkResponse.getDeleted() + " documents.");
}
Querying Documents
Common Query Builders
- Term Query:
QueryBuilders.termQuery(fieldName, value)for exact matches. - Terms Query:
QueryBuilders.termsQuery(fieldName, value1, value2, ...)for matching multiple values. - Range Query:
QueryBuilders.rangeQuery(fieldName).gte(lowerBound).lte(upperBound)for numerical or date ranges. - Exists Query:
QueryBuilders.existsQuery(fieldName)to check if a field has a value. - Wildcard Query:
QueryBuilders.wildcardQuery(fieldName, "\*value\*")for pattern matching (use with caution for performance). - Boolean Query:
BoolQueryBuilderto combine multiple queries usingmust,should,mustNot, andfilter.
1. Match All Query
Retrieves all documents in the specified index.
private static void searchAll(RestHighLevelClient client) throws IOException {
SearchRequest searchRequest = new SearchRequest();
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.matchAllQuery());
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("Total hits for match all: " + searchResponse.getHits().getTotalHits());
}
2. Term Query with Paging and Sorting
A typical search operation combining filtering, pagination, and other settings.
private static void generalSearch(RestHighLevelClient client) throws IOException {
String indexName = "test1";
String typeName = "_doc";
SearchRequest searchRequest = new SearchRequest(indexName);
searchRequest.types(typeName);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
// Define search criteria
sourceBuilder.query(QueryBuilders.termQuery("uid", "1234"));
// Pagination
sourceBuilder.from(0); // Start from the first result
sourceBuilder.size(5); // Number of results per page
// Timeout
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
// Index options
searchRequest.indicesOptions(IndicesOptions.lenientExpandOpen());
// Preference for local shard routing (optional)
searchRequest.preference("_local");
// Sorting (example: descending by score)
// sourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC));
// Sorting by a specific field (example: ascending ID)
// sourceBuilder.sort(new FieldSortBuilder("id").order(SortOrder.ASC));
// Field selection (include/exclude specific fields)
// String[] includeFields = new String[]{"title", "user"};
// String[] excludeFields = new String[]{"_type"};
// sourceBuilder.fetchSource(includeFields, excludeFields);
searchRequest.source(sourceBuilder);
System.out.println("Generated DSL: " + sourceBuilder.toString());
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
// Process search results
searchResponse.getHits().forEach(hit -> {
System.out.println("Search hit: " + hit.getSourceAsMap());
});
}
3. OR Query (using BoolQueryBuilder)
Simulates SQL's WHERE (field1 = val1 OR field1 = val2) AND field2 = val3.
private static void orSearch(RestHighLevelClient client) throws IOException {
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("test1");
searchRequest.types("_doc");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
BoolQueryBuilder shouldClauseBuilder = new BoolQueryBuilder();
shouldClauseBuilder.should(QueryBuilders.termQuery("uid", 1234));
shouldClauseBuilder.should(QueryBuilders.termQuery("uid", 12345));
boolQueryBuilder.must(shouldClauseBuilder); // Must satisfy the 'should' clauses
boolQueryBuilder.must(QueryBuilders.termQuery("phone", "12345678909")); // AND condition
searchSourceBuilder.query(boolQueryBuilder);
searchRequest.source(searchSourceBuilder);
System.out.println("OR Query DSL: " + searchSourceBuilder.toString());
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
searchResponse.getHits().forEach(hit -> {
System.out.println("OR Query Result: " + hit.getSourceAsMap());
});
}
4. Wildcard Query
Similar to SQL's LIKE operator.
private static void likeSearch(RestHighLevelClient client) throws IOException {
String indexName = "test1";
String typeName = "_doc";
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices(indexName);
searchRequest.types(typeName);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
// Message contains 'xu'
boolQueryBuilder.must(QueryBuilders.wildcardQuery("message", "*xu*"));
searchSourceBuilder.query(boolQueryBuilder);
searchRequest.source(searchSourceBuilder);
System.out.println("Wildcard Query DSL: " + searchSourceBuilder.toString());
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
searchResponse.getHits().forEach(hit -> {
System.out.println("Wildcard Query Result: " + hit.getSourceAsMap());
});
}
5. Terms Query (IN Clause)
Equivalent to SQL's IN clause.
private static void inSearch(RestHighLevelClient client) throws IOException {
String indexName = "test1";
String typeName = "_doc";
SearchRequest searchRequest = new SearchRequest(indexName, typeName);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
// uid is one of (1, 2)
sourceBuilder.query(QueryBuilders.termsQuery("uid", 1, 2));
searchRequest.source(sourceBuilder);
System.out.println("IN Query DSL: " + sourceBuilder.toString());
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
searchResponse.getHits().forEach(hit -> {
System.out.println("IN Query Map Result: " + hit.getSourceAsMap());
System.out.println("IN Query String Result: " + hit.getSourceAsString());
});
}
6. Exists Query
Checks if a field contains a value.
private static void existSearch(RestHighLevelClient client) throws IOException {
String indexName = "test1";
String typeName = "_doc";
SearchRequest searchRequest = new SearchRequest(indexName);
searchRequest.types(typeName);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
// Check if 'msgcode' field exists
sourceBuilder.query(QueryBuilders.existsQuery("msgcode"));
searchRequest.source(sourceBuilder);
System.out.println("Exists Query DSL: " + sourceBuilder.toString());
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
searchResponse.getHits().forEach(hit -> {
System.out.println("Exists Query Map Result: " + hit.getSourceAsMap());
});
}
7. Range Query
Used for filtering data within a specified range (e.g., date BETWEEN 'start' AND 'end').
private static void rangeSearch(RestHighLevelClient client) throws IOException {
String indexName = "test1";
String typeName = "_doc";
SearchRequest searchRequest = new SearchRequest(indexName);
searchRequest.types(typeName);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
// Query for 'sendtime' between two dates
sourceBuilder.query(QueryBuilders.rangeQuery("sendtime")
.gte("2019-01-01 00:00:00")
.lte("2019-12-31 23:59:59"));
searchRequest.source(sourceBuilder);
System.out.println("Range Query DSL: " + sourceBuilder.toString());
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
searchResponse.getHits().forEach(hit -> {
System.out.println("Range Query String Result: " + hit.getSourceAsString());
});
}
8. Regexp Query
Performs searches based on regular expressions.
private static void regexpSearch(RestHighLevelClient client) throws IOException {
String indexName = "test1";
String typeName = "_doc";
SearchRequest searchRequest = new SearchRequest(indexName);
searchRequest.types(typeName);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
// Match messages starting with 'xu' followed by a digit
sourceBuilder.query(QueryBuilders.regexpQuery("message", "xu[0-9].*"));
searchRequest.source(sourceBuilder);
System.out.println("Regexp Query DSL: " + sourceBuilder.toString());
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
searchResponse.getHits().forEach(hit -> {
System.out.println("Regexp Query Map Result: " + hit.getSourceAsMap());
});
}
Choosing a Java Client
- For Elasticsearch versions prior to 6.x, consider the JestClient.
- For versions 6.x and later, especially if planning to upgrade to 7.x or beyond, the official Java High-Level REST Client is recommended. Elasticsearch is phasing out the Transport client, which is used by older Spring Data Elasticsearch integrations.