用 Go Typed Client 快速上手 Elasticsearch —— 从建索引到聚合的完整实战

1. 准备工作

bash 复制代码
go get github.com/elastic/go-elasticsearch/v9

小贴士

  • 如果你的集群启用了安全特性,需要在 elasticsearch.Config 中配置 Username/PasswordAPIKey
  • Typed Client 通过 NewTypedClient 创建,内部复用 *http.Client,建议全局单例化,避免频繁建立连接。
go 复制代码
cfg := elasticsearch.Config{
	Addresses: []string{"https://es.local:9200"},
	Username:  "elastic",
	Password:  "mypassword",
	// APIKey: "...", 二选一
}
es, _ := elasticsearch.NewTypedClient(cfg)

2. 创建索引并映射字段

go 复制代码
import (
	"context"
	"github.com/elastic/go-elasticsearch/v9/typedapi/indices/create"
	"github.com/elastic/go-elasticsearch/v9/typedapi/types"
)

_, err := es.Indices.Create("test-index").
	Request(&create.Request{
		Mappings: &types.TypeMapping{
			Properties: map[string]types.Property{
				"price": types.NewIntegerNumberProperty(), // 自动设置 "type":"integer"
			},
		},
	}).
	Do(context.Background())
if err != nil { /* 处理异常 */ }

要点

关键点 说明
types.NewIntegerNumberProperty() Builder 会自动注入 type=integer,避免手写字符串
.Request() 接收强类型结构体,写错字段编译期即报错
.Do(ctx) 统一执行入口,返回 *Responseerror

3. 写入文档

3.1 直接传递结构体(最常用)

go 复制代码
doc := struct {
	Id    int    `json:"id"`
	Name  string `json:"name"`
	Price int    `json:"price"`
}{1, "Foo", 10}

if _, err := es.Index("test-index").
	Request(doc).
	Do(context.Background()); err != nil {
	log.Fatal(err)
}

3.2 传递已序列化的 JSON

go 复制代码
payload := []byte(`{"id":1,"name":"Foo","price":10}`)
_, err := es.Index("test-index").Raw(payload).Do(context.Background())

适用于手动拼装性能敏感 场景,跳过 encoding/json 二次编码。

4. 读取文档

go 复制代码
resp, err := es.Get("test-index", "1").Do(context.Background())
if err != nil { ... }
fmt.Printf("Source=%s\n", resp.Source_)

5. 判断文档是否存在

go 复制代码
ok, err := es.Exists("test-index", "1").IsSuccess(context.Background())
switch {
case err != nil:
	// 请求失败
case ok:
	fmt.Println("文档存在")
default:
	fmt.Println("文档不存在")
}

IsSuccess 通过 HTTP 状态码 判断,内部已处理 404 与重定向。

6. 搜索

6.1 使用强类型 Request 构建 DSL

go 复制代码
import "github.com/elastic/go-elasticsearch/v9/typedapi/search"

resp, err := es.Search().
	Index("test-index").
	Request(&search.Request{
		Query: &types.Query{
			Match: map[string]types.MatchQuery{
				"name": {Query: "Foo"},
			},
		},
	}).
	Do(context.Background())

生成的 DSL

json 复制代码
{
  "query": { "match": { "name": { "query": "Foo" } } }
}

6.2 快速解析命中

go 复制代码
for _, hit := range resp.Hits.Hits {
	var d struct {
		Name  string `json:"name"`
		Price int    `json:"price"`
	}
	if err := json.Unmarshal(hit.Source_, &d); err != nil { ... }
	fmt.Printf("%s => %d\n", d.Name, d.Price)
}

7. 聚合 ------ 求价格总和

go 复制代码
total, err := es.Search().
	Index("test-index").
	Request(&search.Request{
		Size: some.Int(0), // 只要聚合结果,不要文档
		Aggregations: map[string]types.Aggregations{
			"total_prices": {
				Sum: &types.SumAggregation{Field: some.String("price")},
			},
		},
	}).
	Do(context.Background())
if err != nil { ... }

sum := total.Aggregations.Sum("total_prices").Value
fmt.Printf("价格总和:%.0f\n", *sum)
  • some.Int(0)some.String() 是 Typed API 的 可空包装器 ,避免 *int 指针声明的繁琐。
  • 结果通过 Aggregations.Sum("name") 类型安全地取出,无需手写 map 断言。

8. 进阶实践 & 性能建议

  1. 单例客户端 :在 main() 或 DI 容器里初始化一次,复用连接池。
  2. Context 超时 :在高并发场景用 context.WithTimeout 控制慢查询。
  3. Bulk 批量索引 :大规模写入请使用 es.Bulk() + 并行 worker。
  4. 显式 Refresh :测试场景可在写入后 .Refresh("wait_for"),生产环境由索引刷新策略决定。
  5. Typed vs. Raw:Typed API 更安全、可读;Raw/Low-level Client 更灵活。可按模块混用。

9. 小结

  • Typed Request + Builder 让映射、DSL、聚合都拥有 IDE 自动补全和编译期校验。
  • 常见场景(建索引 / CRUD / Search / Aggs)几乎只需一两行链式调用即可搞定。
  • 掌握 some 包 的可空包装器、IsSuccess 以及 Do(ctx) 的范式,能写出既易读又健壮的 Go-ES 代码。

一步到位搭建起 Go × Elasticsearch 的类型安全数据层,让你的业务逻辑远离魔法字符串,尽享编译器的守护!

相关推荐
oqX0Cazj23 分钟前
2026超火Go-Zero实战:从架构原理到高并发接口落地,彻底解决接口超时、雪崩问题
开发语言·架构·golang
开发者联盟league6 小时前
使用jenkins pipeline将项目打包运行在k8s上报错kubectl: Permission denied
java·kubernetes·jenkins
go不是csgo6 小时前
从0到1理解Go熔断器:sony/gobreaker 源码剖析 + 仿TikTok Feed 项目实战
开发语言·后端·golang
江华森6 小时前
Jenkins 运维管理实战博客大纲
运维·jenkins
X1A0RAN6 小时前
解决jenkins(本机部署或容器部署)安全机制【CSP】问题
jenkins·allure报告
烧饼Fighting6 小时前
Jenkins自动化编译部署Spring Boot项目
spring boot·自动化·jenkins
serve the people6 小时前
Elasticsearch(3) show me some examples
大数据·elasticsearch·jenkins
oqX0Cazj27 小时前
Go-Zero数据库事务实战:本地事务+失败自动回滚+生产避坑+简单分布式事务方案
数据库·分布式·golang
右耳朵猫AI7 小时前
Go周刊2026W22 | GoReleaser 2.16、chi 5.3、tldx 1.4、wazero 1.12、Buf 1.70
开发语言·后端·golang
踏着七彩祥云的小丑7 小时前
Go学习第3天:变量+常量+运算符
开发语言·学习·golang·go