Elasticsearch Client for Swift (iOS/macOS)
Elasticsearch is a powerful distributed search engine built on top of Apache Lucene. For iOS and macOS developers, the official elasticsearch-swift client is available, providing a convenient interface for working with Elasticsearch from Swift applications. The library fully supports the Elasticsearch REST API, including indexing, search, aggregations, and cluster management.
Installation and Setup
The client is distributed via Swift Package Manager (SPM). To add it to your project:
// In Package.swiftdependencies: [ .package(url: "https://github.com/elastic/elasticsearch-swift.git", from: "8.10.0")]Or via Xcode: File → Add Packages → enter the repository URL. After installation, import the library:
import ElasticsearchMain Features
- Document Indexing — adding, updating, and deleting records in indices.
- Search — full-text, field-specific, with filters and sorting.
- Aggregations — statistical calculations, groupings, histograms.
- Cluster Management — creating/deleting indices, configuring shards and replicas.
- async/await Support — asynchronous requests using the modern Swift Concurrency model.
Usage Example: Connection and Indexing
Let's create a client and index several documents:
import Elasticsearch
let client = ElasticsearchClient( host: "https://your-cluster-url:9200", apiKey: "your-api-key")
struct Book: Codable { let id: String let title: String let author: String let year: Int}
let books = [ Book(id: "1", title: "Swift Programming", author: "John Doe", year: 2023), Book(id: "2", title: "iOS Development", author: "Jane Smith", year: 2024)]
for book in books { let response = try await client.index( index: "books", id: book.id, body: book ) print("Indexed: \\(response.result)")}Search Using Query DSL
Elasticsearch supports a powerful query language. Example of full-text search:
import Elasticsearch
let query: [String: Any] = [ "query": [ "bool": [ "must": [ ["match": ["title": "Swift"]] ], "filter": [ ["range": ["year": ["gte": 2023]]] ] ] ]]
let searchResponse = try await client.search( index: "books", body: query)
if let hits = searchResponse.hits?.hits { for hit in hits { if let source = hit.source { let book = try JSONDecoder().decode(Book.self, from: source) print("Found: \\(book.title) by \\(book.author)") } }}Aggregations for Analytics
Example of counting books by year:
let aggregationQuery: [String: Any] = [ "size": 0, "aggs": [ "by_year": [ "terms": ["field": "year", "size": 10] ] ]]
let aggResponse = try await client.search( index: "books", body: aggregationQuery)
if let buckets = aggResponse.aggregations?["by_year"] as? [String: Any], let bucketList = buckets["buckets"] as? [[String: Any]] { for bucket in bucketList { let year = bucket["key"] as? Int ?? 0 let count = bucket["doc_count"] as? Int ?? 0 print("\\(year): \\(count) books") }}Index Management
Creating and deleting an index with settings:
let settings: [String: Any] = [ "settings": [ "number_of_shards": 2, "number_of_replicas": 1 ], "mappings": [ "pro