必须用 elastic/go-elasticsearch/v9;es 8.0+ 移除了 _type、强制 https、修改 _search 路径、要求 content-type: application/json,olivere/elastic/v7 未适配导致静默 406 或空响应。

用哪个客户端版本才不会连不上
新项目必须用 elastic/go-elasticsearch/v9,olivere/elastic/v7 在 ES 8.0+ 上根本发不出有效请求——不是报错,而是静默返回 406 Not Acceptable 或空 hits。ES 8.x 移除了 _type、强制 HTTPS、改了 /_search 路径、要求 Content-Type: application/json,而 v7 完全没适配这些变更。
常见现象:client.Search().Do(ctx) 看似成功,但 res.StatusCode 是 406,res.Body 里有提示 “Content-Type header is missing or invalid”,但封装层吞掉了这个响应体,你只看到 “error: bad request”。
-
ES 7.10–7.17→ 可用olivere/elastic/v7(仅限存量迁移) -
ES 8.0+(包括刚装的 8.15 / 9.0)→ 必须用elastic/go-elasticsearch/v9 - 混用两个客户端 →
context.Context传参冲突、http.RoundTripper复用异常,可能 goroutine 悬停
esapi.SearchRequest 必须填哪三个字段
esapi.SearchRequest 不补默认值,漏一个就等于发了个废请求:返回空 hits、no search context found 或 panic。最常漏的是 Body 类型不对、Index 为空、Context 没超时。
-
Index:不能为""或"*";生产环境禁止通配符,ES 可能拒收或打满慢日志;必须明确传[]string{"lessons"} -
Body:必须是*bytes.Reader;常见错误是json.Marshal()后忘了包一层bytes.NewReader(),导致请求体为空,ES 返回400 Bad Request -
Context:必须带超时,例如context.WithTimeout(ctx, 3*time.Second);不设的话 HTTP client 可能卡死在连接池,goroutine 悬停
正确写法示例:
req := esapi.SearchRequest{
Index: []string{"lessons"},
Body: bytes.NewReader([]byte(`{"query":{"match":{"title":"go语言基础"}}}`)),
Context: context.WithTimeout(ctx, 3*time.Second),
}
res, err := req.Do(client)
中文查不到?先盯住 analyzer 和字段类型
90% 的“搜不到”不是 query 写错,而是索引侧配置和写入行为不一致。语言学习类数据(如课程标题、词汇释义)对分词器极其敏感。
- 写入时用了
ik_max_word分词器,但查询 DSL 没加"analyzer": "ik_max_word"→ ES 默认走standard分词器,“人工智能”被切成 “人工”“智能”,而 IK 会切出 “人工智能” 这个完整词项 -
title字段 mapping 是keyword,却用match查 →keyword不分词,match查不了;该用term查询 - 字段名大小写/下划线不匹配:mapping 里是
lesson_title,但 query 里写了lessonTitle→ 结果为空,ES 不自动转换
查之前务必跑:GET /lessons/_mapping,确认字段类型、analyzer 和是否启用 index。
解析 hit.Source 时最容易 panic
ES 返回的文档内容在 hit._source 下,不是 JSON 根对象。直接 json.Unmarshal(raw, &Lesson{}) 会失败或字段为空。
- 正确做法是调
hit.Source方法:err := json.Unmarshal(*hit.Source, &lesson),注意*hit.Source是指针 -
hit.Source可能为nil(比如设置了_source: false),得先判空 - 结构体字段 tag 必须和 mapping 对齐:
json:"title"对应 mapping 中的"title",不能写成json:"Title"
别省那几行代码去复用全局 *elasticsearch.Client 单例——语言学习场景常有课程搜索、词汇搜索、用户笔记搜索等不同业务域,建议按索引隔离 client 实例,防止某一路慢查询拖垮全部。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











