Elasticsearch клиент для Swift (iOS/macOS)
Elasticsearch — это мощная распределённая поисковая и аналитическая система, построенная на Apache Lucene. Для интеграции с мобильными и десктопными приложениями на Swift (iOS/macOS) существует специализированный клиент Elasticsearch Swift. Эта библиотека предоставляет удобный API для выполнения поисковых запросов, индексации данных, агрегаций и управления кластером прямо из приложений Apple.
Основные возможности библиотеки
- Полнотекстовый поиск — поддержка всех типов запросов Elasticsearch (match, term, bool, fuzzy и др.)
- CRUD-операции — создание, чтение, обновление и удаление документов в индексах
- Агрегации — построение сложных аналитических отчётов (terms, range, date_histogram и т.д.)
- Пакетная обработка — bulk-операции для массовой загрузки данных
- Поддержка асинхронности — работа через async/await и Combine
- SSL/TLS и аутентификация — безопасное подключение к кластеру
Установка
Добавьте библиотеку через Swift Package Manager. В Xcode выберите File → Add Packages и введите URL репозитория:
https://github.com/elastic/elasticsearch-swift.git
Либо добавьте зависимость в Package.swift:
dependencies: [
.package(url: "https://github.com/elastic/elasticsearch-swift.git", from: "1.0.0")
]
Инициализация клиента
Создайте экземпляр ElasticsearchClient с указанием хоста и порта Elasticsearch:
import Elasticsearch
let client = ElasticsearchClient(
host: "http://localhost:9200",
username: "elastic",
password: "changeme"
)
Для подключения к облачному Elastic Cloud используйте конструктор с URL и API-ключом:
let client = ElasticsearchClient(
cloudID: "my-cluster:dXM...",
apiKey: "base64EncodedApiKey"
)
Индексация документов
Создадим простую модель пользователя и проиндексируем её:
struct User: Codable {
let name: String
let email: String
let age: Int
}
let user = User(name: "Алексей", email: "alex@example.com", age: 30)
Task {
let response = try await client.index(
index: "users",
id: "1",
body: user
)
print("Документ создан: \(response.result)")
}
Поиск документов
Поиск пользователей по имени с использованием match-запроса:
let searchQuery: [String: Any] = [
"query": [
"match": [
"name": "Алексей"
]
]
]
Task {
let response = try await client.search(
index: "users",
body: searchQuery
)
if let hits = response.hits?.hits {
for hit in hits {
if let source = hit.source as? [String: Any] {
print("Найден: \(source["name"] ?? "")")
}
}
}
}
Агрегации
Построим гистограмму по возрасту пользователей:
let aggregationQuery: [String: Any] = [
"size": 0,
"aggs": [
"age_ranges": [
"range": [
"field": "age",
"ranges": [
["to": 20],
["from": 20, "to": 40],
["from": 40]
]
]
]
]
]
Task {
let response = try await client.search(
index: "users",
body: aggregationQuery
)
if let buckets = response.aggregations?["age_ranges"] as? [String: Any] {
print("Результаты агрегации: \(buckets)")
}
}
Обновление и удаление
Обновление возраста пользователя:
let updateBody: [String: Any] = [
"doc": [
"age": 31
]
]
Task {
let response = try await client.update(
index: "users",
id: "1",
body: updateBody
)
print("Обновлено: \(response.result)")
}
Удаление документа:
Task {
let response = try await client.delete(
index: "users",
id: "1"
)
print("Удалено: \(response.result)")
}
Пакетная загрузка (Bulk)
Массовая индексация нескольких документов:
let users = [
User(name: "Мария", email: "maria@example.com", age: 25),
User(name: "Иван", email: "ivan@example.com", age: 35)
]