Go语言操作Elasticsearch全流程示例:连接、增删改查

温以宁
温以宁
发布时间:2026-10-15 | 4人浏览过
原创

本文详细演示了如何使用Go语言的 go-elasticsearch 库连接并操作Elasticsearch集群。内容包含完整的初始化连接、文档索引写入、基于布尔逻辑的查询与结果解析、使用Painless脚本进行单条/批量更新,以及单条与批量删除数据的代码示例。

前提准备与客户端连接

在使用Go操作Elasticsearch前,需安装官方推荐的SDK库。在Go项目中引入依赖:

import (
    es8 "github.com/elastic/go-elasticsearch/v8"
)

配置连接信息时,建议将敏感信息(如密码)从代码中剥离。以下示例展示如何构建Client并验证连通性:

conf := es8.Config{
    Addresses: []string{"http://127.0.0.1:9200"}, // 注意:Address应为切片类型
    Username: "elastic",
    Password: "你的实际密码", // 请替换为真实的ES密码
}

client, err := es8.NewClient(conf)
if err != nil {
    log.Fatalf("创建es客户端失败: %v", err)
}

// 验证连接
res, err := client.Info(es8.Info.WithContext(context.Background()))
if err != nil {
    log.Fatalf("连接es失败: %v", err)
}
log.Println("成功连接Elasticsearch")

注意:原文中的 Addresses: "http..." 写法存在类型错误,es8.Config 的 Addresses 字段要求是 []string 类型,且必须添加 context 以符合最新SDK规范。

创建索引与写入数据

Elasticsearch无需预先定义映射(Mapping),首次写入数据时会自动创建索引并动态生成字段类型。这里定义一个结构体用于模拟待写入的数据。

定义模型结构

type Admin struct {
    ID       int    `json:"id"`
    UserName string `json:"user_name"`
    RealName string `json:"real_name"`
    Mobile   string `json:"mobile"`
}

写入单条文档

将结构体序列化为JSON后,通过 Index 方法写入。设置 WithDocumentID 可以指定文档唯一ID,避免自动生成导致的不确定性;WithRefresh("true") 可立即生效搜索结果(生产环境建议设为false以提升性能)。 

admin := Admin{
    ID:       1,
    UserName: "test",
    RealName: "测试用户",
    Mobile:   "15222222222",
}

body, err := json.Marshal(admin)
if err != nil {
    log.Fatal(err)
}

res, err := client.Index(
    "my_index",                          // 索引名称
    bytes.NewReader(body),               // 数据体
    client.Index.WithDocumentID("1"),    // 文档ID
    client.Index.WithRefresh("true"),    // 刷新策略
)
if err != nil {
    log.Fatal(err)
}

搜索数据

构建查询DSL并使用 Search 方法发起请求。对于嵌套较深的返回结果,定义对应的Go结构体有助于类型安全地解析数据。

定义响应结构

type EsResponse struct {
    Hits struct {
        Total struct {
            Value int `json:"value"`
        } `json:"total"`
        Hits []struct {
            Id     string         `json:"_id"`
            Source map[string]any `json:"_source"`
        } `json:"hits"`
    } `json:"hits"`
}

// 简化后的业务返回结构
type ResultData struct {
    TotalCount int              `json:"total_count"`
    Items      []map[string]any `json:"items"`
}

执行搜索

示例使用 bool -> must 组合查询多个字段的精确匹配。注意:若字段类型为 keyword 则使用 match_phrase 或 term,若为 text 则根据分词情况选择。match_phrase 对顺序有严格要求。

query := map[string]any{
    "query": map[string]any{
        "bool": map[string]any{
            "must": []map[string]any{
                {"match_phrase": map[string]any{"user_name": "test"}},
                {"match_phrase": map[string]any{"mobile": "15222222222"}},
            },
        },
    },
}

qBody, _ := json.Marshal(query)
res, err := client.Search(
    client.Search.WithIndex("my_index"),
    client.Search.WithBody(bytes.NewReader(qBody)),
    client.Search.WithPretty(),
)
if err != nil {
    log.Fatal(err)
}

// 解析结果
var response EsResponse
if err := json.NewDecoder(res.Body).Decode(&response); err != nil { ... }

var result ResultData
result.TotalCount = response.Hits.Total.Value
for _, hit := range response.Hits.Hits {
    hit.Item["_id"] = hit.Id // 补充ID到源数据
    result.Items = append(result.Items, hit.Source)
}

修改数据

Elasticsearch支持使用Painless脚本动态修改字段,适合部分字段更新场景。相比全量替换,这种方式更高效。

单条修改

使用 Update 接口配合 Script 语法修改指定ID的文档。

updateScript := map[string]any{
    "script": map[string]any{
        "source": "ctx._source.user_name=params.un; ctx._source.mobile.params.mo",
        "params": map[string]any{
            "un": "updated_test",
            "mo": "15211111111",
        },
        "lang": "painless",
    },
}

uBody, _ := json.Marshal(updateScript)
_, err := client.Update(
    "my_index",          // 索引
    "1",                 // 文档ID
    bytes.NewReader(uBody),
    client.Update.WithRefresh("true"),
)
if err != nil {
    log.Fatal(err)
}

批量修改 (UpdateByQuery)

若需根据条件批量更新数据,使用 UpdateByQuery 接口。

bulkUpdate := map[string]any{
    "query": map[string]any{
        "bool": map[string]any{
            "must": []map[string]any{
                {"match_phrase": map[string]any{"user_name": "test"}},
            },
        },
    },
    "script": map[string]any{
        "source": "ctx._source.mobile='new_mobile';",
        "lang":   "painless",
    },
}

bBody, _ := json.Marshal(bulkUpdate)
_, err := client.UpdateByQuery(
    []string{"my_index"},
    client.UpdateByQuery.WithBody(bytes.NewReader(bBody)),
    client.UpdateByQuery.WithRefresh(true),
)
if err != nil {
    log.Fatal(err)
}

删除数据

删除操作分为针对已知ID的单条删除,以及基于查询条件的批量删除。

单条删除

res, err := client.Delete(
    "my_index",
    "1",
    client.Delete.WithRefresh("true"),
)
if err != nil {
    log.Fatal(err)
}

批量删除

构造查询语句来匹配待删除的记录,效率极高,但需注意确认查询条件以免误删。

delQuery := map[string]any{
    "query": map[string]any{
        "bool": map[string]any{
            "must": []map[string]any{
                {"match_phrase": map[string]any{"mobile": "15222222222"}},
            },
        },
    },
}

dBody, _ := json.Marshal(delQuery)
_, err := client.DeleteByQuery(
    []string{"my_index"},
    bytes.NewReader(dBody),
    client.DeleteByQuery.WithRefresh(true),
)
if err != nil {
    log.Fatal(err)
}

以上就是Go语言操作Elasticsearch全流程(连接、写入、查询、修改、删除)的详细内容,更多关于Go语言集成Elasticsearch实战的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表