Vapor/Swift Elasticsearch 客户端 🔎

此项目的目标是为 Swift 提供一个全面而易于使用的 Elasticsearch 客户端。Vapor 服务器端框架拥有庞大的社区,因此与 Vapor 集成是合乎逻辑的第一步。 也就是说,这个库应该很容易移植到另一个框架(Perfect、Kitura),甚至可以单独用于命令行实用程序和其他此类用途。

主要优先级是提供索引管理(字段映射、设置、分词器和分析器)、CRUD 支持以及对聚合搜索结果的支持。 目前,这些目标都在某种程度上得到满足。

警告

此项目正处于 интенсивной 开发阶段,公共 API 每周都在变化(没有向后兼容性)。 也就是说,只要您每周勤奋地拉取最新代码,这些更改通常都比较小。

高级功能

Elasticsearch 版本

所有开发和测试都在使用 Elasticsearch 6.x 系列进行。 这对文档类型有影响,因为它们已在 Elasticsearch 6.0 中弃用,并将在 7.0 中删除。 鉴于每个索引的多种类型已成为过去,而此客户端是未来的趋势,因此支持每个索引的多种类型似乎并不合适。 如果使用旧版本的 Elasticsearch,请记住此限制。

📦 安装

Package.swift

Elasticsearch 添加到 Package 依赖项

dependencies: [
    ...,
    .package(url: "https://github.com/ryangrimm/VaporElasticsearch", .branch("master"))
]

以及添加到您的目标(例如 “App”)

targets: [
    ...
    .target(
        name: "App",
        dependencies: [... "Elasticsearch" ...]
    ),
    ...
]

开始使用 🚀

确保在所有需要的地方都导入了 Elasticsearch

import Elasticsearch

添加服务

在您的 configure.swift 文件中添加 ElasticsearchDatabase

let esConfig = ElasticsearchClientConfig(hostname: "localhost", port: 9200)
let es = try ElasticsearchDatabase(config: esConfig)
var databases = DatabasesConfig()
databases.add(database: es, as: .elasticsearch)
services.register(databases)

启用日志记录

var databases = DatabasesConfig()
databases.enableLogging(on: .elasticsearch)
services.register(databases)

简单的搜索示例

struct Document: Codable {

    var id: String
    var title: String
}

func list(_ req: Request) throws -> Future<[Document]> {

	let query = Query(
	    Match(field: "id", value: "42")
	)

	return req.withNewConnection(to: .elasticsearch) { conn in

	    return try conn.search(
		decodeTo: Document.self,
		index: "documents",
		query: SearchContainer(query)
	    )

	}.map(to: [Document].self ) { searchResponse in

	    guard let hits = searchResponse.hits else { return [Document]() }
	    let results = hits.hits.map { $0.source }
	    return results
	}
}

创建索引(带过滤器)

//let client: ElasticsearchClient = ...

let synonymFilter = SynonymFilter(name: "synonym_filter",
	synonyms: ["file, document", "nice, awesome, great"])

let synonymAnalyzer = CustomAnalyzer(
	name: "synonym_analyzer",
	tokenizer: StandardTokenizer(),
	filter: [synonymFilter]))

let index = client.configureIndex(name: "documents")
	.indexSettings(index: IndexSettings(shards: 5, replicas: 1))
	.property(key: "id", type: MapKeyword())
	.property(key: "title", type: MapText(analyzer: synonymAnalyzer))

try index.create()

删除索引

//let client: ElasticsearchClient = ...
try client.deleteIndex(name: "documents")

使用 bulk 插入文档

//let client: ElasticsearchClient = ...

let doc1 = Document(id: 1, title: "hello world")
let doc2 = Document(id: 5, title: "awesome place")

let bulk = client.bulkOperation()
bulk.defaultHeader.index = "documents"

try bulk.create(doc: doc1, id: String(doc1.id))
try bulk.create(doc: doc2, id: String(doc2.id))
// if you want to overwrite documents, use `bulk.index` instead

try bulk.send()