连不上 Elasticsearch大概率是用了已归档的olivere/elastic/v7客户端连接ES 8.x或9.x集群,因协议不兼容导致406错误或静默失败;必须改用elastic/go-elasticsearch/v8或v9,且避免混用两个客户端。

连不上 Elasticsearch,不是网络问题,大概率是用了已归档的 olivere/elastic/v7 去连 ES 8.x 或 9.x 集群——协议层直接被拒,返回 406 Not Acceptable 或静默空响应。
用错客户端版本导致请求发不出去
ES 8.0+ 强制 HTTPS、移除 _type、要求 Content-Type: application/json、调整 /_search 路径结构。而 olivere/elastic/v7 完全没适配这些变更,连基础请求头都发不全。
- 新项目必须用
github.com/elastic/go-elasticsearch/v9(ES 9.x)或v8(ES 8.x 主流版本),安装命令:go get github.com/elastic/go-elasticsearch/v9@latest - 别混用两个客户端:同一进程里同时 import
olivere/elastic和elastic/go-elasticsearch,会导致context.Context传参冲突、http.RoundTripper复用异常,出现静默超时 - 初始化后立刻调
es.Info()验证连通性;若报x509: certificate signed by unknown authority,本地开发需显式禁用证书校验
esapi.SearchRequest 必须显式设 Index、Body、Context
官方客户端不补默认值,漏一个字段就等于发了个废请求:返回空 hits、no search context found,甚至 panic。
-
Index:必须为非空[]string{"articles"},禁止传""或"*";生产环境通配符会被 ES 拒收或打满慢日志 -
Body:必须是*bytes.Reader;常见错误是json.Marshal(q)后忘了包一层bytes.NewReader(),导致请求体为空,ES 直接返回400 Bad Request -
Context:必须带超时,例如context.WithTimeout(ctx, 3*time.Second);不设的话 HTTP client 可能卡死在连接池,goroutine 悬停不释放
中文搜不到?分词器、refresh、字段类型三处最容易断链
90% 的“搜不到”不是 Go 代码写错,而是索引侧和查询侧不一致:Kibana 能搜出来,Go 里却为空,基本就是这三处断了。
立即学习“go语言免费学习笔记(深入)”;
- 分词器不一致:索引用了
ik_max_word,但查询 DSL 没加"analyzer": "ik_max_word",ES 默认走standard分词器,“人工智能”被切成“人工”“智能”,自然匹配不上 -
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是指针 - 字段名必须和 mapping 完全一致:
user_id≠userId,查不到不会提示,只会返回空切片 - 如果用
MatchQuery查keyword字段,结果永远为空;该用TermQuery或把字段 mapping 改成text
最易被忽略的是 Body 类型和 Context 超时的组合效应:bytes.NewReader 漏了,400 就来了;Context 没设,整个 goroutine 就挂起,连错误都捕获不到。


















