Рубрики
Без рубрики

Руководство по Elasticsearch в Java

Краткое и практическое руководство по Elasticsearch на Java.

Автор оригинала: baeldung.

1. Обзор

В этой статье мы рассмотрим некоторые ключевые концепции, связанные с полнотекстовыми поисковыми системами, с особым акцентом на Elasticsearch.

Поскольку это статья, ориентированная на Java, мы не собираемся давать подробное пошаговое руководство по настройке Elasticsearch и показывать, как он работает под капотом. Вместо этого мы будем ориентироваться на клиент Java и на то, как использовать основные функции, такие как index , delete , get и search .

2. Настройка

Для простоты мы будем использовать образ docker для нашего экземпляра Elasticsearch, через экземпляр Elasticsearch, прослушивающий порт 9200, будет делать .

Мы начинаем с запуска нашего экземпляра Elasticsearch:

docker run -d --name es762 -p 9200:9200 -e "discovery.type=single-node" elasticsearch:7.6.2

По умолчанию Elasticsearch прослушивает порт 9200 для предстоящих HTTP-запросов. Мы можем убедиться, что он успешно запущен, открыв http://localhost:9200/ URL в вашем любимом браузере:

{
  "name" : "M4ojISw",
  "cluster_name" : "docker-cluster",
  "cluster_uuid" : "CNnjvDZzRqeVP-B04D3CmA",
  "version" : {
    "number" : "7.6.2",
    "build_flavor" : "default",
    "build_type" : "docker",
    "build_hash" : "2f4c224",
    "build_date" : "2020-03-18T23:22:18.622755Z",
    "build_snapshot" : false,
    "lucene_version" : "8.4.0",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.8.0-beta1"
  },
  "tagline" : "You Know, for Search"
}

3. Конфигурация Maven

Теперь, когда у нас есть наш базовый кластер Elasticsearch, давайте сразу перейдем к Java-клиенту. Прежде всего, мы должны иметь следующую зависимость Maven , объявленную в вашем pom.xml файл:


    org.elasticsearch
    elasticsearch
    7.6.2

Вы всегда можете проверить последние версии, размещенные в Maven Central, по ссылке, предоставленной ранее.

4. Java API

Прежде чем мы перейдем прямо к тому, как использовать основные функции Java API, нам нужно инициировать Сброс клиента высокого уровня :

ClientConfiguration clientConfiguration =
    ClientConfiguration.builder().connectedTo("localhost:9200").build();
RestHighLevelClient client = RestClients.create(clientConfiguration).rest();

4.1. Индексация документов

Функция index() позволяет хранить произвольный документ JSON и делать его доступным для поиска:

@Test
public void givenJsonString_whenJavaObject_thenIndexDocument() {
  String jsonObject = "{\"age\":10,\"dateOfBirth\":1471466076564,"
    +"\"fullName\":\"John Doe\"}";
  IndexRequest request = new IndexRequest("people");
  request.source(jsonObject, XContentType.JSON);
  
  IndexResponse response = client.index(request, RequestOptions.DEFAULT);
  String index = response.getIndex();
  long version = response.getVersion();
    
  assertEquals(Result.CREATED, response.getResult());
  assertEquals(1, version);
  assertEquals("people", index);
}

Обратите внимание, что для создания и обработки документов можно использовать любую библиотеку Java JSON . Если вы не знакомы ни с одним из них, вы можете использовать помощники Elasticsearch для создания собственных документов JSON :

XContentBuilder builder = XContentFactory.jsonBuilder()
  .startObject()
  .field("fullName", "Test")
  .field("dateOfBirth", new Date())
  .field("age", "10")
  .endObject();

  IndexRequest indexRequest = new IndexRequest("people");
  indexRequest.source(builder);

  IndexResponse response = client.index(indexRequest, RequestOptions.DEFAULT);
  assertEquals(Result.CREATED, response.getResult());

4.2. Запрос Индексированных Документов

Теперь, когда у нас есть типизированный документ JSON с возможностью поиска, мы можем продолжить поиск с помощью метода search() :

SearchRequest searchRequest = new SearchRequest();
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHit[] searchHits = response.getHits().getHits();
List results = 
  Arrays.stream(searchHits)
    .map(hit -> JSON.parseObject(hit.getSourceAsString(), Person.class))
    .collect(Collectors.toList());

Результаты , возвращаемые методом search () , называются Хитами , каждый Hit относится к документу JSON, соответствующему поисковому запросу.

В этом случае список results содержит все данные, хранящиеся в кластере. Обратите внимание, что в этом примере мы используем библиотеку FastJson для преобразования JSON Строк в объекты Java.

Мы можем улучшить запрос, добавив дополнительные параметры, чтобы настроить запрос с помощью методов Query Builders :

SearchSourceBuilder builder = new SearchSourceBuilder()
  .postFilter(QueryBuilders.rangeQuery("age").from(5).to(15));

SearchRequest searchRequest = new SearchRequest();
searchRequest.searchType(SearchType.DFS_QUERY_THEN_FETCH);
searchRequest.source(builder);

SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);

4.3. Извлечение и удаление документов

Методы get() и delete () позволяют получить или удалить документ JSON из кластера, используя его идентификатор:

GetRequest getRequest = new GetRequest("people");
getRequest.id(id);

GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);
// process fields
    
DeleteRequest deleteRequest = new DeleteRequest("people");
deleteRequest.id(id);

DeleteResponse deleteResponse = client.delete(deleteRequest, RequestOptions.DEFAULT);

Синтаксис довольно прост, вам просто нужно указать индекс рядом с идентификатором объекта.

5. Примеры построителей запросов

Класс Query Builders предоставляет множество статических методов, используемых в качестве динамических сопоставителей для поиска определенных записей в кластере. При использовании метода search() для поиска конкретных документов JSON в кластере мы можем использовать построители запросов для настройки результатов поиска.

Вот список наиболее распространенных применений API Query Builders .

Метод matchAllQuery() возвращает объект QueryBuilder , соответствующий всем документам в кластере:

QueryBuilder matchAllQuery = QueryBuilders.matchAllQuery();

Запрос range() соответствует документам, в которых значение поля находится в определенном диапазоне:

QueryBuilder matchDocumentsWithinRange = QueryBuilders
  .rangeQuery("price").from(15).to(100)

Предоставляя имя поля – например, Полное имя и соответствующее значение – например, John Doe , метод matchQuery() сопоставляет весь документ с этим точным значением поля:

QueryBuilder matchSpecificFieldQuery= QueryBuilders
  .matchQuery("fullName", "John Doe");

Мы также можем использовать метод multiMatchQuery() для создания многополевой версии запроса соответствия:

QueryBuilder matchSpecificFieldQuery= QueryBuilders.matchQuery(
  "Text I am looking for", "field_1", "field_2^3", "*_field_wildcard");

Мы можем использовать символ каретки (^) для увеличения определенных полей .

В нашем примере field_2 имеет значение boost, равное трем, что делает его более важным, чем другие поля. Обратите внимание, что можно использовать подстановочные знаки и запросы регулярных выражений, но с точки зрения производительности остерегайтесь потребления памяти и задержки времени отклика при работе с подстановочными знаками, потому что что-то вроде *_apples может оказать огромное влияние на производительность.

Коэффициент важности используется для упорядочения результирующего набора обращений, возвращаемых после выполнения метода s earch () .

Если вы более знакомы с синтаксисом запросов Lucene, вы можете использовать метод simple Query String Query() для настройки поисковых запросов:

QueryBuilder simpleStringQuery = QueryBuilders
  .simpleQueryStringQuery("+John -Doe OR Janette");

Как вы, вероятно, догадываетесь, мы можем использовать синтаксис синтаксического анализатора запросов Lucene для создания простых, но мощных запросов . Вот некоторые основные операторы, которые можно использовать вместе с операторами И/ИЛИ/НЕ для построения поисковых запросов:

  • Требуемый оператор ( + ): требует, чтобы определенный фрагмент текста существовал где-то в полях документа.
  • Оператор запрета ( ): исключает все документы, содержащие ключевое слово, объявленное после символа ( ).

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

В этой краткой статье мы рассмотрели, как использовать API Java Elasticsearch для выполнения некоторых общих функций, связанных с полнотекстовыми поисковыми системами.

Вы можете ознакомиться с примером, приведенным в этой статье в проекте GitHub .