1. Introduction
1.绪论
Anyone who has worked with Elasticsearch knows that building queries using their RESTful search API can be tedious and error-prone.
任何使用过Elasticsearch的人都知道,使用其RESTful search API构建查询可能是非常繁琐和容易出错的。
In this tutorial, we’ll look at Jest, an HTTP Java client for Elasticsearch. While Elasticsearch provides its own native Java client, Jest provides a more fluent API and easier interfaces to work with.
在本教程中,我们将了解Jest,这是Elasticsearch的一个HTTP Java客户端。虽然Elasticsearch提供了它自己的本地Java客户端,但Jest提供了更流畅的API和更容易操作的接口。
2. Maven Dependency
2.Maven的依赖性
The first thing we need to do is import the Jest library into our POM:
我们需要做的第一件事是将Jest库导入我们的POM中。
<dependency>
<groupId>io.searchbox</groupId>
<artifactId>jest</artifactId>
<version>6.3.1</version>
</dependency>
The versioning for Jest follows that of the main Elasticsearch product. This helps ensure compatibility between client and server.
Jest的版本划分与Elasticsearch的主要产品一致。这有助于确保客户端和服务器之间的兼容性。
By including the Jest dependency, the corresponding Elasticsearch library will be included as a transitive dependency.
通过包括Jest的依赖关系,相应的Elasticsearch库将作为一个反式依赖关系被包括在内。
3. Using Jest Client
3.使用Jest客户端
In this section, we’ll look at using the Jest client to perform common tasks with Elasticsearch.
在本节中,我们将看看如何使用Jest客户端来执行Elasticsearch的常见任务。
To use the Jest client, we simply create a JestClient object using the JestClientFactory. These objects are expensive to create and are thread-safe, so we’ll create a singleton instance that can be shared throughout our application:
要使用Jest客户端,我们只需使用 JestClientFactory创建一个JestClient对象。这些对象的创建成本很高,而且是线程安全的,所以我们将创建一个单机实例,可以在整个应用程序中共享。
public JestClient jestClient() {
JestClientFactory factory = new JestClientFactory();
factory.setHttpClientConfig(
new HttpClientConfig.Builder("http://localhost:9200")
.multiThreaded(true)
.defaultMaxTotalConnectionPerRoute(2)
.maxTotalConnection(10)
.build());
return factory.getObject();
}
This will create a Jest client connected to an Elasticsearch client running locally. While this connection example is trivial, Jest also has full support for proxies, SSL, authentication, and even node discovery.
这将创建一个连接到本地运行的Elasticsearch客户端的Jest客户端。虽然这个连接例子很琐碎,但Jest也完全支持代理、SSL、认证,甚至是节点发现。
The JestClient class is generic and only has a handful of public methods. The main one we’ll use is execute, which takes an instance of the Action interface. The Jest client provides several builder classes to help create different actions that interact with Elasticsearch.
JestClient类是通用的,只有少数几个公共方法。我们将使用的主要方法是execute,它需要一个Action接口的实例。Jest客户端提供了几个构建器类,以帮助创建与Elasticsearch交互的不同动作。
The result of all Jest calls is an instance of JestResult. We can check for success by calling isSucceeded. For unsuccessful actions, we can call getErrorMessage to get more detail:
所有Jest调用的结果是JestResult的一个实例。我们可以通过调用isSucceeded来检查是否成功。对于不成功的操作,我们可以调用getErrorMessage来获得更多细节。
JestResult jestResult = jestClient.execute(new Delete.Builder("1").index("employees").build());
if (jestResult.isSucceeded()) {
System.out.println("Success!");
}
else {
System.out.println("Error: " + jestResult.getErrorMessage());
}
3.1. Managing Indices
3.1.管理指数
To check if an index exists, we use the IndicesExists action:
为了检查一个索引是否存在,我们使用IndicesExists动作。
JestResult result = jestClient.execute(new IndicesExists.Builder("employees").build())
To create an index, we use the CreateIndex action:
为了创建一个索引,我们使用CreateIndex动作。
jestClient.execute(new CreateIndex.Builder("employees").build());
This will create an index with default settings. We can override specific settings during index creation:
这将创建一个具有默认设置的索引。我们可以在创建索引时覆盖特定的设置。
Map<String, Object> settings = new HashMap<>();
settings.put("number_of_shards", 11);
settings.put("number_of_replicas", 2);
jestClient.execute(new CreateIndex.Builder("employees").settings(settings).build());
And creating or changing aliases is also simple using the ModifyAliases action:
使用ModifyAliases动作,创建或改变别名也很简单。
jestClient.execute(new ModifyAliases.Builder(
new AddAliasMapping.Builder("employees", "e").build()).build());
jestClient.execute(new ModifyAliases.Builder(
new RemoveAliasMapping.Builder("employees", "e").build()).build());
3.2. Creating Documents
3.2.创建文件
The Jest client makes it easy to index – or create – new documents using the Index action class. Documents in Elasticsearch are just JSON data, and there are multiple ways to pass JSON data to the Jest client for indexing.
Jest客户端使用Index动作类,可以很容易地索引–或创建–新文档。Elasticsearch中的文档只是JSON数据,有多种方法可以将JSON数据传递给Jest客户端进行索引。
For this example, let’s use an imaginary Employee document:
在这个例子中,让我们使用一个假想的雇员文件。
{
"name": "Michael Pratt",
"title": "Java Developer",
"skills": ["java", "spring", "elasticsearch"],
"yearsOfService": 2
}
The first way to represent a JSON document is by using a Java String. While we can manually create the JSON string, we have to be mindful of proper formatting, braces, and escaping quote characters.
表示JSON文档的第一个方法是使用Java String。虽然我们可以手动创建JSON字符串,但我们必须注意正确的格式化、大括号和转义引号字符。
Therefore, it’s easier to use a JSON library such as Jackson to build our JSON structure and then convert to a String:
因此,使用诸如Jackson之类的JSON库来构建我们的JSON结构,然后转换为String,会更加容易。
ObjectMapper mapper = new ObjectMapper();
JsonNode employeeJsonNode = mapper.createObjectNode()
.put("name", "Michael Pratt")
.put("title", "Java Developer")
.put("yearsOfService", 2)
.set("skills", mapper.createArrayNode()
.add("java")
.add("spring")
.add("elasticsearch"));
jestClient.execute(new Index.Builder(employeeJsonNode.toString()).index("employees").build());
We can also use a Java Map to represent JSON data and pass that to the Index action:
我们还可以使用Java Map来表示JSON数据,并将其传递给Index动作。
Map<String, Object> employeeHashMap = new LinkedHashMap<>();
employeeHashMap.put("name", "Michael Pratt");
employeeHashMap.put("title", "Java Developer");
employeeHashMap.put("yearsOfService", 2);
employeeHashMap.put("skills", Arrays.asList("java", "spring", "elasticsearch"));
jestClient.execute(new Index.Builder(employeeHashMap).index("employees").build());
Finally, the Jest client can accept any POJO that represents the document to index. Let’s say we have an Employee class:
最后,Jest客户端可以接受任何代表要索引的文档的POJO。比方说,我们有一个Employee类。
public class Employee {
String name;
String title;
List<String> skills;
int yearsOfService;
}
We can pass an instance of this class directly to the Index builder:
我们可以将这个类的一个实例直接传递给Index构建器。
Employee employee = new Employee();
employee.setName("Michael Pratt");
employee.setTitle("Java Developer");
employee.setYearsOfService(2);
employee.setSkills(Arrays.asList("java", "spring", "elasticsearch"));
jestClient.execute(new Index.Builder(employee).index("employees").build());
3.3. Reading Documents
3.3.阅读文件
There are two primary ways to access a document from Elasticsearch using Jest client. First, if we know the document ID, we can access it directly using the Get action:
使用Jest客户端从Elasticsearch访问文档有两种主要方式。首先,如果我们知道文档的ID,我们可以使用Get动作直接访问它。
jestClient.execute(new Get.Builder("employees", "17").build());
To access the returned document, we must call one of the various getSource methods. We can either get the result as raw JSON or deserialize it back to a DTO:
要访问返回的文档,我们必须调用各种getSource方法之一。我们可以以原始JSON的形式获取结果,或者将其反序列化为DTO。
Employee getResult = jestClient.execute(new Get.Builder("employees", "1").build())
.getSourceAsObject(Employee.class);
The other way of accessing documents is using a search query, which is implemented in Jest with the Search action.
另一种访问文档的方式是使用搜索查询,这在Jest中通过Search动作实现。
Jest client supports the full Elasticsearch query DSL. Just like indexing operations, queries are expressed as JSON documents, and there are multiple ways to perform searches.
Jest客户端支持完整的Elasticsearch查询DSL。就像索引操作一样,查询被表达为JSON文档,并且有多种方法来执行搜索。
First, we can pass a JSON string that represents the search query. As a reminder, we must take care to ensure the string is properly escaped and is valid JSON:
首先,我们可以传递一个JSON字符串,代表搜索查询。作为提醒,我们必须注意确保该字符串被正确转义,并且是有效的JSON。
String search = "{" +
" \"query\": {" +
" \"bool\": {" +
" \"must\": [" +
" { \"match\": { \"name\": \"Michael Pratt\" }}" +
" ]" +
" }" +
" }" +
"}";
jestClient.execute(new Search.Builder(search).build());
As with the Index action above, we could use a library such as Jackson to build our JSON query string.
与上面的Index动作一样,我们可以使用Jackson这样的库来构建我们的JSON查询字符串。
Additionally, we can also use the native Elasticsearch query action API. The one downside of this is that our application has to depend on the full Elasticsearch library.
此外,我们还可以使用本地Elasticsearch查询动作API。这样做的一个缺点是,我们的应用程序必须依赖完整的Elasticsearch库。
With the Search action, the matching documents can be accessed using the getSource methods. However, Jest also provides the Hit class, which wraps the matching documents and provides metadata about the results. Using the Hit class, we can access additional metadata for each result: score, routing, and explain results, to name a few:
通过Search动作,可以使用getSource方法访问匹配的文档。然而,Jest 还提供了Hit类,它包装了匹配的文档并提供了关于结果的元数据。使用Hit类,我们可以访问每个结果的额外元数据:分数、路由和解释结果,仅举几例。
List<SearchResult.Hit<Employee, Void>> searchResults =
jestClient.execute(new Search.Builder(search).build())
.getHits(Employee.class);
searchResults.forEach(hit -> {
System.out.println(String.format("Document %s has score %s", hit.id, hit.score));
});
3.4. Updating Documents
3.4.更新文件
Jest provides a simple Update action for updating documents:
Jest提供了一个简单的Update动作来更新文档。
employee.setYearOfService(3);
jestClient.execute(new Update.Builder(employee).index("employees").id("1").build());
It accepts the same JSON representations as the Index action we saw earlier, making it easy to share code between the two operations.
它接受与我们之前看到的Index操作相同的JSON表示,使得在这两个操作之间共享代码很容易。
3.5. Deleting Documents
3.5.删除文件
Deleting a document from an index is done using the Delete action. It only requires an index name and document ID:
使用Delete动作可以从索引中删除一个文件。它只需要一个索引名称和文档ID。
jestClient.execute(new Delete.Builder("17")
.index("employees")
.build());
4. Bulk Operations
4.大宗业务
Jest client also supports bulk operations. This means we can save time and bandwidth by sending multiple operations together at the same time.
Jest客户端还支持批量操作。这意味着我们可以通过同时发送多个操作来节省时间和带宽。
Using the Bulk action, we can combine any number of requests into a single call. We can even combine different types of requests together:
使用Bulk动作,我们可以将任何数量的请求合并为一个单一的调用。我们甚至可以将不同类型的请求合并在一起。
jestClient.execute(new Bulk.Builder()
.defaultIndex("employees")
.addAction(new Index.Builder(employeeObject1).build())
.addAction(new Index.Builder(employeeObject2).build())
.addAction(new Delete.Builder("17").build())
.build());
5. Asynchronous Operations
5.异步操作
Jest client also supports asynchronous operations, which means we can perform any of the above operations using non-blocking I/O.
Jest客户端还支持异步操作,这意味着我们可以使用非阻塞的I/O来执行上述任何操作。
To invoke an operation asynchronously, simply use the executeAsync method of the client:
要异步调用一个操作,只需使用客户端的executeAsync方法。
jestClient.executeAsync(
new Index.Builder(employeeObject1).build(),
new JestResultHandler<JestResult>() {
@Override public void completed(JestResult result) {
// handle result
}
@Override public void failed(Exception ex) {
// handle exception
}
});
Note that in addition to the action (indexing in this case), the asynchronous flow also requires a JestResultHandler. The Jest client will call this object when the action has finished. The interface has two methods – completed and failed – that allow handling either success or failure of the operation, respectively.
请注意,除了操作(本例中为索引),异步流程还需要一个JestResultHandler。当操作完成后,Jest客户端将调用该对象。该接口有两个方法–completed和failed–分别允许处理操作的成功或失败。
6. Conclusion
6.结语
In this tutorial, we have looked briefly at the Jest client, a RESTful Java client for Elasticsearch.
在本教程中,我们简要介绍了Jest客户端,这是Elasticsearch的一个RESTful Java客户端。
Although we have only covered a small portion of its functionality, it’s clear that Jest is a robust Elasticsearch client. Its fluent builder classes and RESTful interfaces make it easy to learn, and its full support for Elasticsearch interfaces make it a capable alternative to the native client.
虽然我们只介绍了它的一小部分功能,但很明显,Jest是一个强大的Elasticsearch客户端。它流畅的构建器类和RESTful接口使它很容易学习,它对Elasticsearch接口的全面支持使它成为本地客户端的有力替代。
As always, all of the code examples in the tutorial are over on GitHub.
一如既往,该教程中的所有代码示例都在GitHub上。