连不上ES需检查客户端版本与transport配置:ES 8.15/9.0必须用elastic/go-elasticsearch/v8或v9,禁用HTTP、补全认证、调优连接池;SearchRequest三要素(Index、Body、Context)缺一不可;搜不到中文需核对分词器与字段类型;解析hit.Source须调用hit.Source方法并判空。

连不上 ES?先看客户端版本和 transport 配置
ES 8.15 或 9.0 环境下用 olivere/elastic/v7,client.Search() 会静默返回空结果或 406 Not Acceptable,不是代码写错,是协议断层——ES 8.x 移除了 _type、强制 HTTPS、要求 Content-Type: application/json,而 v7 完全没适配。
必须用 elastic/go-elasticsearch/v8 或 v9(v9 更推荐,已适配 9.0)。初始化时别只写地址:
-
elastic.SetURL("https://localhost:9200")—— HTTP 会直接被拒,必须用 HTTPS -
elastic.SetBasicAuth("elastic", "changeme")—— 漏掉就401 Unauthorized -
elastic.SetTransport(&http.Transport{MaxIdleConns: 100, MaxIdleConnsPerHost: 100})—— 默认连接池太小,高并发下卡在dial tcp: lookup或超时
SearchRequest 三个字段漏一个,请求就废了
esapi.SearchRequest 不补默认值,漏填任何一项都会导致空 hits、no search context found 或 panic。常见错误是只顾写 JSON body,忘了包 bytes.NewReader()。
-
Index:不能为""或"*";生产环境必须明确传[]string{"articles"} -
Body:必须是*bytes.Reader;json.Marshal(q)后必须套一层bytes.NewReader(),否则请求体为空,ES 返回400 Bad Request -
Context:必须带超时,例如context.WithTimeout(ctx, 3*time.Second);不设的话 goroutine 可能悬停在 HTTP 连接池里,fd 泄露
搜不到中文?先查分词器和字段类型
90% 的“搜不到”不是 query 写错,而是索引侧和查询侧不一致。比如用了 ik_max_word 建索引,但 query DSL 没指定 "analyzer": "ik_max_word",ES 默认走 standard 分词器,“人工智能”被切成 “人工”“智能”,自然匹配不上。
立即学习“go语言免费学习笔记(深入)”;
- 查 mapping:运行
GET /your-index/_mapping,确认字段类型是text(全文搜)还是keyword(精确匹配) - 字段类型错配:title 是
keyword类型,却用MatchQuery查 —— 应该用TermQuery - refresh 延迟:刚
Index()完立刻Search(),大概率为空;开发期可临时加Refresh: "true",但批量导入时严禁使用
解析 hit.Source 时 panic?别直接 unmarshal raw
ES 返回的文档内容在 hit._source 下,不是 JSON 根对象。直接 json.Unmarshal(raw, &MyDoc{}) 会失败或字段为空,因为 raw 是整个 hit 对象,含 _id、_score 等元数据。
正确做法是调 hit.Source 方法:
for _, hit := range res.Hits.Hits {
var doc Article
err := json.Unmarshal(hit.Source, &doc)
if err != nil {
// handle error
}
// use doc
}
注意:hit.Source 是 []byte,不是 map[string]interface{};如果设置了 _source: false,hit.Source 会是 nil,得先判空。


















