Cliente Elasticsearch para Kotlin: guía completa
\n\nElasticsearch es un potente sistema de búsqueda distribuido basado en Lucene. Para trabajar con él desde aplicaciones Kotlin se utiliza el cliente oficial Elasticsearch Java Client, que es totalmente compatible con Kotlin gracias a su cercanía con la JVM. En este artículo analizaremos cómo configurar el cliente, realizar operaciones básicas (indexación, búsqueda, eliminación) y utilizar capacidades avanzadas como agregaciones y filtrado.
\n\nConexión y configuración
\n\nPara empezar, agregue la dependencia en build.gradle.kts (o build.gradle):
// build.gradle.kts\ndependencies {\n implementation("co.elastic.clients:elasticsearch-java:8.15.0")\n implementation("com.fasterxml.jackson.core:jackson-databind:2.17.0")\n implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.17.0")\n}\n\nLuego cree el cliente:
\n\nimport co.elastic.clients.elasticsearch.ElasticsearchClient\nimport co.elastic.clients.json.jackson.JacksonJsonpMapper\nimport co.elastic.clients.transport.rest_client.RestClientTransport\nimport org.apache.http.HttpHost\nimport org.elasticsearch.client.RestClient\n\nfun createClient(): ElasticsearchClient {\n val restClient = RestClient.builder(\n HttpHost("localhost", 9200, "http")\n ).build()\n\n val transport = RestClientTransport(restClient, JacksonJsonpMapper())\n return ElasticsearchClient(transport)\n}\n\nval client = createClient()\n\nOperaciones básicas
\n\nIndexación de documentos
\n\nCree una data class para representar los datos:
\n\ndata class Product(\n val id: String,\n val name: String,\n val price: Double,\n val category: String\n)\n\nLa indexación se realiza así:
\n\nsuspend fun indexProduct(product: Product) {\n client.index { i ->\n i.index("products")\n .id(product.id)\n .document(product)\n }\n}\n\n// Ejemplo de llamada\nval product = Product("1", "Portátil", 999.99, "Electrónica")\nrunBlocking { indexProduct(product) }\n\nBúsqueda por campos
\n\nsuspend fun searchByName(name: String): List<Product> {\n val response = client.search<Product>({ s ->\n s.index("products")\n .query { q ->\n q.match { m ->\n m.field("name")\n .query(name)\n }\n }\n }, Product::class.java)\n\n return response.hits().hits().map { it.source()!! }\n}\n\nEliminación de documentos
\n\nsuspend fun deleteProduct(id: String) {\n client.delete { d ->\n d.index("products")\n .id(id)\n }\n}\n\nFiltrado y agregaciones
\n\nElasticsearch admite consultas complejas. Por ejemplo, búsqueda de productos en un rango de precios con agregación por categorías:
\n\nsuspend fun searchWithAggregation(minPrice: Double, maxPrice: Double) {\n val response = client.search<Product>({ s ->\n s.index("products")\n .query { q ->\n q.range { r ->\n r.field("price")\n .gte(minPrice.toString())\n .lte(maxPrice.toString())\n }\n }\n .aggregations("by_category") { a ->\n a.terms { t ->\n t.field("category")\n }\n }\n }, Product::class.java)\n\n // Obtenemos los resultados de la agregación\n val categories = response.aggregations()\n ?.get("by_category")\n ?.sterms()\n ?.buckets()\n ?.map { "${it.key()}: ${it.docCount()}" }\n ?: emptyList()\n\n println("Categorías: $categories")\n}\n\nProcesamiento por lotes (Bulk API)
\n\nPara indexación masiva utilice bulk
También en la biblioteca
Planificador de tareas en C# (.NET): Quartz.NET, Hangfire, Coravel
Caching en Java: Redis, Ehcache, Caffeine, Hazelcast — descripción general y ejemplos
Validación de datos en Java: revisión de herramientas y bibliotecas
Registro en Rust: revisión de las mejores bibliotecas y herramientas