عميل Elasticsearch لـ Kotlin: دليل شامل
\n\nElasticsearch هو نظام بحث موزع قوي يعتمد على Lucene. للعمل معه من تطبيقات Kotlin، يُستخدم العميل الرسمي Elasticsearch Java Client، المتوافق تمامًا مع Kotlin نظرًا لقربه من JVM. في هذه المقالة، سنشرح كيفية إعداد العميل، تنفيذ العمليات الأساسية (الفهرسة، البحث، الحذف) واستخدام الإمكانيات المتقدمة مثل التجميعات والتصفية.
\n\nالاتصال والإعداد
\n\nللبدء، أضف التبعية في ملف build.gradle.kts (أو 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\nثم قم بإنشاء العميل:
\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\nالعمليات الأساسية
\n\nفهرسة مستند
\n\nأنشئ data class لتمثيل البيانات:
\n\ndata class Product(\n val id: String,\n val name: String,\n val price: Double,\n val category: String\n)\n\nيتم تنفيذ الفهرسة كالتالي:
\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// مثال على الاستدعاء\nval product = Product("1", "لابتوب", 999.99, "إلكترونيات")\nrunBlocking { indexProduct(product) }\n\nالبحث حسب الحقول
\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\nحذف مستند
\n\nsuspend fun deleteProduct(id: String) {\n client.delete { d ->\n d.index("products")\n .id(id)\n }\n}\n\nالتصفية والتجميعات
\n\nيدعم Elasticsearch الاستعلامات المعقدة. على سبيل المثال، البحث عن المنتجات ضمن نطاق سعري مع تجميع حسب الفئات:
\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 // الحصول على نتائج التجميع\n val categories = response.aggregations()\n ?.get("by_category")\n ?.sterms()\n ?.buckets()\n ?.map { "${it.key()}: ${it.docCount()}" }\n ?: emptyList()\n\n println("الفئات: $categories")\n}\n\nالمعالجة المجمعة (Bulk API)
\n\nللفهرسة الجماعية، استخدم bulk