Elasticsearch REST клиент для Kotlin: руководство по использованию

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Elasticsearch клиент для Kotlin: мощный инструмент для поиска и аналитики

Elasticsearch — это распределённая поисковая и аналитическая система на базе Apache Lucene, которая позволяет быстро выполнять полнотекстовый поиск, агрегации и анализ больших объёмов данных. Для работы с Elasticsearch из Kotlin-приложений существует несколько клиентов, но наиболее современным и рекомендуемым является Elasticsearch Java Client (начиная с версии 7.16) с полной поддержкой Kotlin. В этой статье мы рассмотрим его установку, настройку и основные операции.

Установка и подключение

Для начала добавьте зависимость в ваш build.gradle.kts:

dependencies {
    implementation("co.elastic.clients:elasticsearch-java:8.15.0")
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.17.0")
    implementation("jakarta.json:jakarta.json-api:2.1.3")
}

Для Maven (pom.xml):

<dependency>
    <groupId>co.elastic.clients</groupId>
    <artifactId>elasticsearch-java</artifactId>
    <version>8.15.0</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.module</groupId>
    <artifactId>jackson-module-kotlin</artifactId>
    <version>2.17.0</version>
</dependency>

Создание клиента

Библиотека использует паттерн Builder для конфигурации. Ниже приведён пример создания клиента с подключением к локальному экземпляру Elasticsearch:

import co.elastic.clients.elasticsearch.ElasticsearchClient
import co.elastic.clients.json.jackson.JacksonJsonpMapper
import co.elastic.clients.transport.ElasticsearchTransport
import co.elastic.clients.transport.rest_client.RestClientTransport
import org.apache.http.HttpHost
import org.elasticsearch.client.RestClient

fun createElasticsearchClient(): ElasticsearchClient {
    // Создаём HTTP-клиент (без аутентификации)
    val restClient = RestClient.builder(
        HttpHost("localhost", 9200, "http")
    ).build()

    // Создаём транспорт с JSON-маппером Jackson
    val transport: ElasticsearchTransport = RestClientTransport(
        restClient, 
        JacksonJsonpMapper()
    )

    // И возвращаем готовый клиент
    return ElasticsearchClient(transport)
}

Для продакшн-среды рекомендуется использовать аутентификацию и HTTPS:

val credentialsProvider = BasicCredentialsProvider()
credentialsProvider.setCredentials(
    AuthScope.ANY,
    UsernamePasswordCredentials("elastic", "your_password")
)

val restClient = RestClient.builder(
    HttpHost("your-cluster.com", 9243, "https")
)
.setHttpClientConfigCallback { httpClientBuilder ->
    httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider)
}
.build()

Работа с индексами

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

suspend fun createIndex(client: ElasticsearchClient, indexName: String) {
    val response = client.indices().create { createBuilder ->
        createBuilder
            .index(indexName)
            .mappings { mappings ->
                mappings
                    .properties("title") { prop -> prop.text { it } }
                    .properties("content") { prop -> prop.text { it } }
                    .properties("timestamp") { prop -> prop.date { it } }
            }
    }
    println("Индекс создан: ${response.acknowledged}")
}

CRUD операции с документами

Создание/обновление документа (Index API)

data class Article(
    val title: String,
    val content: String,
    val timestamp: String = java.time.Instant.now().toString()
)

suspend fun indexDocument(client: ElasticsearchClient, indexName: String, id: String, article: Article) {
    val response = client.index { index ->
        index
            .index(indexName)
            .id(id)
            .document(article)
    }
    println("Документ проиндексирован: результат=${response.result()}")
}

Получение документа по ID

suspend fun getDocument(client: ElasticsearchClient, indexName: String, id: String): Article? {
    val response = client.get { get ->
        get
            .index(indexName)
            .id(id)
    }
    return if (response.found()) {
        response.source() as? Article
    } else {
        println("Документ не найден")
        null
    }
}

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

suspend fun deleteDocument(client: ElasticsearchClient, indexName: String, id: String) {
    val response = client.delete { delete ->
        delete
            .index(indexName)
            .id(id)
    }
    println("Документ удалён: результат=${response.result()}")
}

Поиск и запросы

Одна из ключевых возможностей — полнотекстовый поиск. Пример простого поиска по полю content

Рекомендаций