ES 8.0+ 必须用 elastic/go-elasticsearch/v9,因协议断层导致 olivere/elastic/v7 连接失败;常见问题包括索引名非法、body 未用 bytes.NewReader、Context 缺超时、中文分词器未显式指定、multi_match 不支持字段 boost 语法、hit.Source 需解引用、refresh 延迟及字段类型不匹配。

必须用 elastic/go-elasticsearch/v9,olivere/elastic/v7 在 ES 8.0+ 上根本连不上——不是代码写错了,是协议断层导致 400/406 或静默空响应。
为什么 esapi.SearchRequest 总是返回空 hits 或 panic
官方客户端不补默认值,漏设任一关键字段,ES 就当请求无效。常见错误组合:
-
Index传了""或"*":ES 8+ 拒收通配符索引名,生产环境必须显式传[]string{"blogs"} -
Body不是*bytes.Reader:比如json.Marshal()后直接传[]byte,ES 收不到 body,返回 400;正确写法是bytes.NewReader(data) -
Context没带超时:HTTP client 卡在连接池,goroutine 悬停不释放,现象是服务变慢、连接数暴涨
中文多字段加权搜索总不生效
不是 query 写得不对,而是 ES 默认用 standard 分词器查 IK 索引,或 boost 被 multi_match 层级吞掉。真实生效路径:
- 查询 DSL 必须显式指定
"analyzer": "ik_max_word",且字段名与 mapping 完全一致(title≠Title) - 别依赖
multi_match的fields: ["title^3", "content"]:v9 客户端不识别该语法,boost 只在 multi_match 内部起作用 - 真要 title 权重高 3 倍,得用
BoolQuery+Should数组,每个match单独设boost,例如:map[string]interface{}{"match": map[string]interface{}{"title": map[string]interface{}{"query": "golang", "boost": 3.0}}} - 加
"explain": true到请求 body,返回里会带评分拆解,否则看不出是分词错还是 boost 没加载
解析 hit.Source 时 panic 或字段为空
ES 返回的文档内容在 hit._source 下,不是 JSON 根对象。直接 json.Unmarshal(raw, &MyDoc{}) 必然失败。
立即学习“go语言免费学习笔记(深入)”;
-
hit.Source是*json.RawMessage类型指针,必须先解引用:*hit.Source - 正确解码姿势:
err := json.Unmarshal(*hit.Source, &doc),注意前面的* - 如果字段类型不匹配(比如 mapping 里
title是keyword,却用MatchQuery查),也会导致hit.Source为空或字段丢失
最容易被忽略的是 refresh 延迟和字段类型匹配——刚 Index() 完立刻搜,大概率为空;mapping 设成 keyword 却用全文查询,永远命中不了。这些不在 query 侧,而在索引定义和写入流程里。


















