Skip to content

在 Go 语言中使用 Elasticsearch(简称 ES)通常通过第三方库来实现,最常用的库是 github.com/elastic/go-elasticsearch,这是官方推荐的 Go 客户端。该库提供了与 Elasticsearch 交互的接口,支持索引、查询、文档管理等常见操作。

1. 安装 go-elasticsearch 客户端

首先需要安装 Elasticsearch 的 Go 客户端:

bash
go get github.com/elastic/go-elasticsearch/v8

2. 使用 Go 与 Elasticsearch 交互

2.1 导入包

go
package main

import (
    "context"
    "fmt"
    "log"

    "github.com/elastic/go-elasticsearch/v8"
)

2.2 创建客户端

你需要创建一个 elasticsearch 客户端来连接你的 Elasticsearch 服务。以下代码演示了如何创建一个连接到本地 Elasticsearch 服务的客户端。

go
func main() {
    // 创建 Elasticsearch 客户端
    cfg := elasticsearch.Config{
        Addresses: []string{"http://localhost:9200"}, // 指定 Elasticsearch 地址
    }
    client, err := elasticsearch.NewClient(cfg)
    if err != nil {
        log.Fatalf("Error creating the client: %s", err)
    }

    // 检查连接是否成功
    res, err := client.Info()
    if err != nil {
        log.Fatalf("Error getting info: %s", err)
    }
    defer res.Body.Close()

    fmt.Println("Connected to Elasticsearch!")
    fmt.Println("Cluster info:", res)
}

3. 常见操作示例

3.1 创建索引

go
func createIndex(client *elasticsearch.Client, indexName string) {
    res, err := client.indices.Create(indexName)
    if err != nil {
        log.Fatalf("Error creating index: %s", err)
    }
    defer res.Body.Close()

    fmt.Printf("Index %s created\n", indexName)
}

3.2 索引文档

你可以使用 Elasticsearch 的 Index API 来创建或更新文档。以下是一个将文档添加到 Elasticsearch 的示例。

go
func indexDocument(client *elasticsearch.Client, indexName, documentID string, document map[string]interface{}) {
    // 转换为 JSON 格式
    docJSON, err := json.Marshal(document)
    if err != nil {
        log.Fatalf("Error marshalling document: %s", err)
    }

    // 索引文档
    res, err := client.Index(
        indexName,
        bytes.NewReader(docJSON),
        client.Index.WithDocumentID(documentID),
        client.Index.WithRefresh("true"),
    )
    if err != nil {
        log.Fatalf("Error indexing document: %s", err)
    }
    defer res.Body.Close()

    fmt.Printf("Document indexed with ID %s\n", documentID)
}

例如:

go
document := map[string]interface{}{
    "title":  "Go Elasticsearch",
    "content": "Elasticsearch is a distributed search engine",
}
indexDocument(client, "posts", "1", document)

3.3 查询文档

查询 Elasticsearch 中的文档通常使用 Search API。下面的代码展示了如何执行一个简单的查询:

go
func searchDocuments(client *elasticsearch.Client, indexName, query string) {
    searchQuery := fmt.Sprintf(`{"query": {"match": {"content": "%s"}}}`, query)
    res, err := client.Search(
        client.Search.WithIndex(indexName),
        client.Search.WithBody(strings.NewReader(searchQuery)),
        client.Search.WithPretty(),
    )
    if err != nil {
        log.Fatalf("Error executing search: %s", err)
    }
    defer res.Body.Close()

    var result map[string]interface{}
    if err := json.NewDecoder(res.Body).Decode(&result); err != nil {
        log.Fatalf("Error parsing search result: %s", err)
    }

    fmt.Println(result)
}

例如:

go
searchDocuments(client, "posts", "Go")

3.4 删除文档

删除文档可以通过 Delete API 来实现,指定文档的 ID 和索引名称。

go
func deleteDocument(client *elasticsearch.Client, indexName, documentID string) {
    res, err := client.Delete(indexName, documentID)
    if err != nil {
        log.Fatalf("Error deleting document: %s", err)
    }
    defer res.Body.Close()

    fmt.Printf("Document with ID %s deleted\n", documentID)
}

3.5 更新文档

你可以使用 Update API 更新现有文档。如果文档不存在,Elasticsearch 会自动创建一个新的文档。

go
func updateDocument(client *elasticsearch.Client, indexName, documentID string, update map[string]interface{}) {
    docJSON, err := json.Marshal(update)
    if err != nil {
        log.Fatalf("Error marshalling update document: %s", err)
    }

    res, err := client.Update(
        indexName,
        documentID,
        bytes.NewReader(docJSON),
        client.Update.WithRefresh("true"),
    )
    if err != nil {
        log.Fatalf("Error updating document: %s", err)
    }
    defer res.Body.Close()

    fmt.Printf("Document with ID %s updated\n", documentID)
}

例如:

go
update := map[string]interface{}{
    "doc": map[string]interface{}{
        "content": "Elasticsearch is awesome!",
    },
}
updateDocument(client, "posts", "1", update)

3.6 批量操作

Elasticsearch 提供了批量操作的 API,可以同时执行多个索引、删除或更新操作。以下是批量索引文档的示例:

go
func bulkIndexDocuments(client *elasticsearch.Client, indexName string, documents []map[string]interface{}) {
    var bulkRequest strings.Builder

    for _, doc := range documents {
        docJSON, err := json.Marshal(doc)
        if err != nil {
            log.Fatalf("Error marshalling document: %s", err)
        }
        bulkRequest.WriteString(fmt.Sprintf(`{"index": {}}\n%s\n`, docJSON))
    }

    res, err := client.Bulk(strings.NewReader(bulkRequest.String()))
    if err != nil {
        log.Fatalf("Error performing bulk operation: %s", err)
    }
    defer res.Body.Close()

    fmt.Println("Bulk operation completed")
}

4. 处理错误

Go 的 Elasticsearch 客户端返回的响应通常包含一个 Error 字段,你可以根据它来检查是否存在错误。以下是处理错误的一个示例:

go
if res.IsError() {
    log.Printf("[%s] Error: %s", res.Status(), res.String())
    return
}

5. 使用 defer 关闭客户端

虽然客户端在程序退出时会自动关闭,但你可以使用 defer 来确保在不再使用时关闭连接。以下是一个例子:

go
func main() {
    // 创建 Elasticsearch 客户端
    cfg := elasticsearch.Config{
        Addresses: []string{"http://localhost:9200"},
    }
    client, err := elasticsearch.NewClient(cfg)
    if err != nil {
        log.Fatalf("Error creating the client: %s", err)
    }
    defer client.Close() // 使用 defer 确保退出时关闭客户端

    // 执行 Elasticsearch 操作...
}

总结

在 Go 中使用 Elasticsearch,github.com/elastic/go-elasticsearch/v8 客户端是一个功能强大的工具,支持常见的索引、查询、更新、删除、批量操作等。基本的操作流程包括:

  1. 创建客户端连接 Elasticsearch。
  2. 使用 Index API 索引文档。
  3. 使用 Search API 查询文档。
  4. 使用 UpdateDelete API 更新或删除文档。
  5. 通过批量 API 执行多个操作。
  6. 通过 defer 关闭客户端连接。

如果你有更多关于 Elasticsearch 或 Go 的问题,随时可以提问!