必须用elastic/go-elasticsearch/v9连接ES 8.0+(如8.15或9.0),因olivere/elastic/v7未适配协议变更(强制HTTPS、移除_type、要求Content-Type等),导致400/406错误或静默失败;ES 7.x才可用v7。

直接用 elastic/go-elasticsearch/v9,别碰 olivere/elastic/v7 —— 如果你连的是 ES 8.0+(包括刚装的 8.15 或 9.0),v7 客户端根本发不出有效请求,不是代码错,是协议断层导致静默失败:400、406、空 hits 或 context deadline exceeded 都是典型症状。
怎么选对客户端版本?看 ES,不看 Go
ES 版本和 Go 客户端必须严格对齐,混用等于白写:
- ES 7.x(如 7.10–7.17)→ 只能用
olivere/elastic/v7或elastic/go-elasticsearch/v7 - ES 8.0+(含 8.15、9.0)→ 必须用
elastic/go-elasticsearch/v9(注意:v8 已归档,v9 是当前维护主线) - 用
v9连 ES 7.x?会报error decoding response body,字段缺失或类型不匹配 - 用
v7连 ES 8.x?req.Do()返回空结果或 406 Not Acceptable,日志里没线索
esapi.SearchRequest 必须显式设三个字段
官方 v9 客户端不补默认值,漏一个就等于发了个废请求:
-
Index:不能为""或"*";生产环境禁止通配符,ES 可能拒收或打满慢日志;必须传[]string{"products"} -
Body:必须是*bytes.Reader;常见错误是json.Marshal()后忘了包一层bytes.NewReader(),导致请求体为空,ES 返回400 Bad Request -
Context:必须带超时,例如context.WithTimeout(ctx, 3*time.Second);不设的话 HTTP client 可能卡死在连接池,goroutine 悬停
中文搜不到?先查分词器和字段类型
90% 的“搜不到”不是 query 写错,而是索引侧配置和写入行为不一致:
立即学习“go语言免费学习笔记(深入)”;
- 中文分词:索引用了
ik_max_word,但查询 DSL 没加"analyzer": "ik_max_word",ES 默认走standard分词器——“人工智能”被切成 “人工”“智能”,而 IK 会切出完整词项,自然匹配不上 - refresh 延迟:文档写入后默认 1 秒才可搜索;刚
Index()完立刻Search(),大概率为空;开发期可临时加Refresh: "true",但批量导入时严禁使用 - 字段类型错配:
title字段 mapping 是keyword,却用MatchQuery查——keyword不分词,MatchQuery查不了;该用TermQuery
解析 hit.Source 为什么 panic?
ES 返回的文档内容在 hit._source 下,不是 JSON 根对象。直接 json.Unmarshal(raw, &MyDoc{}) 会失败或字段为空:
- 正确做法是调
hit.Source方法:err := json.Unmarshal(*hit.Source, &doc),注意*hit.Source是指针 - 如果用
map[string]interface{}解析,hit.Source是*json.RawMessage类型,需先解引用再json.Unmarshal - 聚合结果更易 panic:
aggregations是嵌套map,字段名必须和返回 key 完全一致(如doc_count不是count);建议用searchResponse.Aggregations方法而非手动取map
最常被忽略的点是:ES 8.0+ 强制 HTTPS、移除 _type、要求 Content-Type: application/json,这些不是可选配置,是协议硬约束。v7 客户端连上去第一眼看着像通了,其实连 /_search 路径都拼错了,只是错误被吞得太深,你得靠抓包才能看到真实请求头。


















