Перейти к основному содержимому

Jest — Java-клиент Elasticsearch

· 7 мин. чтения

1. Введение

Любой, кто работал с Elasticsearch , знает, что создание запросов с использованием их поискового API RESTful может быть утомительным и подверженным ошибкам.

В этом руководстве мы рассмотрим Jest , HTTP-клиент Java для Elasticsearch. В то время как Elasticsearch предоставляет собственный Java-клиент, Jest предлагает более гибкий API и более простые интерфейсы для работы с .

2. Зависимость от Maven

Первое, что нам нужно сделать, это импортировать библиотеку Jest в наш POM:

<dependency>
<groupId>io.searchbox</groupId>
<artifactId>jest</artifactId>
<version>6.3.1</version>
</dependency>

Версии для Jest аналогичны версиям основного продукта Elasticsearch . Это помогает обеспечить совместимость между клиентом и сервером.

При включении зависимости Jest соответствующая библиотека Elasticsearch будет включена в качестве транзитивной зависимости.

3. Использование клиента Jest

В этом разделе мы рассмотрим использование клиента Jest для выполнения общих задач с Elasticsearch.

Чтобы использовать клиент Jest, мы просто создаем объект JestClient , используя JestClientFactory . Эти объекты дороги в создании и потокобезопасны , поэтому мы создадим экземпляр singleton, который можно будет использовать в нашем приложении:

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();
}

Это создаст клиент Jest, подключенный к клиенту Elasticsearch, работающему локально. Хотя этот пример подключения тривиален, Jest также имеет полную поддержку прокси, SSL, аутентификации и даже обнаружения узлов .

Класс JestClient является универсальным и имеет всего несколько общедоступных методов. Основной, который мы будем использовать, — это execute , который принимает экземпляр интерфейса Action . Клиент Jest предоставляет несколько классов построителей, которые помогают создавать различные действия, взаимодействующие с Elasticsearch.

Результатом всех вызовов 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. Управление индексами

Чтобы проверить, существует ли индекс, мы используем действие IndicesExists :

JestResult result = jestClient.execute(new IndicesExists.Builder("employees").build())

Для создания индекса мы используем действие CreateIndex :

jestClient.execute(new CreateIndex.Builder("employees").build());

Это создаст индекс с настройками по умолчанию. Мы можем переопределить определенные настройки во время создания индекса:

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());

И создание или изменение псевдонимов также просто с помощью действия 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. Создание документов

Клиент Jest упрощает индексирование или создание новых документов с помощью класса действий Index . Документы в Elasticsearch — это просто данные JSON , и существует несколько способов передать данные JSON клиенту Jest для индексации.

Для этого примера воспользуемся воображаемым документом сотрудника:

{
"name": "Michael Pratt",
"title": "Java Developer",
"skills": ["java", "spring", "elasticsearch"],
"yearsOfService": 2
}

Первый способ представить документ JSON — использовать Java String . Хотя мы можем вручную создать строку JSON, мы должны помнить о правильном форматировании, фигурных скобках и экранировании кавычек.

Поэтому проще использовать библиотеку JSON, такую как Jackson , для построения нашей структуры 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());

Мы также можем использовать карту Java для представления данных 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());

Наконец, клиент Jest может принять любой объект POJO, представляющий индексируемый документ. Допустим, у нас есть класс Employee :

public class Employee {
String name;
String title;
List<String> skills;
int yearsOfService;
}

Мы можем передать экземпляр этого класса непосредственно в конструктор индексов :

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. Чтение документов

Есть два основных способа получить доступ к документу из Elasticsearch с помощью клиента Jest. Во-первых, если мы знаем идентификатор документа, мы можем получить к нему прямой доступ с помощью действия « Получить » :

jestClient.execute(new Get.Builder("employees", "17").build());

Чтобы получить доступ к возвращаемому документу, мы должны вызвать один из различных методов getSource . Мы можем либо получить результат в виде необработанного JSON, либо десериализовать его обратно в DTO:

Employee getResult = jestClient.execute(new Get.Builder("employees", "1").build())
.getSourceAsObject(Employee.class);

Другой способ доступа к документам — использование поискового запроса, реализованного в Jest с помощью действия « Поиск » .

Клиент Jest поддерживает полный запрос DSL Elasticsearch . Как и операции индексирования, запросы выражаются в виде документов JSON, и существует несколько способов выполнения поиска.

Во-первых, мы можем передать строку JSON, представляющую поисковый запрос. Напоминаем, что мы должны позаботиться о том, чтобы строка была правильно экранирована и соответствовала JSON:

String search = "{" +
" \"query\": {" +
" \"bool\": {" +
" \"must\": [" +
" { \"match\": { \"name\": \"Michael Pratt\" }}" +
" ]" +
" }" +
" }" +
"}";
jestClient.execute(new Search.Builder(search).build());

Как и в случае с действием Index выше, мы могли бы использовать библиотеку, такую как Jackson, для создания строки запроса JSON.

Кроме того, мы также можем использовать собственный API действий запроса Elasticsearch. Единственным недостатком этого является то, что наше приложение должно зависеть от полной библиотеки Elasticsearch .

С помощью действия « Поиск » можно получить доступ к соответствующим документам с помощью методов 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. Обновление документов

Jest предоставляет простое действие Update для обновления документов:

employee.setYearOfService(3);
jestClient.execute(new Update.Builder(employee).index("employees").id("1").build());

Он принимает те же представления JSON, что и действие Index , которое мы видели ранее, что упрощает совместное использование кода между двумя операциями.

3.5. Удаление документов

Удаление документа из индекса выполняется с помощью действия Удалить . Для этого требуется только имя индекса и идентификатор документа:

jestClient.execute(new Delete.Builder("17")
.index("employees")
.build());

4. Массовые операции

Клиент Jest также поддерживает массовые операции. Это означает, что мы можем сэкономить время и пропускную способность, одновременно отправляя несколько операций.

Используя действие 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. Асинхронные операции

Клиент Jest также поддерживает асинхронные операции , что означает, что мы можем выполнять любые из вышеперечисленных операций, используя неблокирующий ввод-вывод.

Чтобы вызвать операцию асинхронно, просто используйте метод 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
}
});

Обратите внимание, что помимо действия (в данном случае индексации) для асинхронного потока также требуется JestResultHandler. Клиент Jest вызовет этот объект, когда действие завершится. В интерфейсе есть два метода — complete и failed — которые позволяют обрабатывать либо успех, либо неудачу операции соответственно.

6. Заключение

В этом руководстве мы кратко рассмотрели клиент Jest, Java-клиент RESTful для Elasticsearch.

Хотя мы рассмотрели лишь небольшую часть его функциональности, ясно, что Jest — надежный клиент Elasticsearch. Его беглые классы компоновщика и интерфейсы RESTful упрощают изучение, а его полная поддержка интерфейсов Elasticsearch делает его достойной альтернативой собственному клиенту.

Как всегда, все примеры кода в туториале закончились на GitHub .