创建索引时mapping和settings必须嵌套在根对象下,v7为{"settings":{},"mappings":{"_doc":{"properties":{}}}},v8为{"settings":{},"mappings":{"properties":{}}}。

创建索引时 mapping 和 settings 必须嵌套,不能平级
很多人写 CreateIndex().BodyJson() 时把 settings 和 mappings 当成同级字段直接塞进 map,结果 ES 返回 400 Bad Request,但错误信息很模糊,容易卡半天。根本原因是 v7/v8 的 API 要求它们必须是根对象下的两个独立 key,且 mappings 在 v8 中已去掉 type 层(不再有 _doc),v7 还保留。
- v7 正确结构:
{"settings": {...}, "mappings": {"_doc": {"properties": {...}}}} - v8 正确结构:
{"settings": {...}, "mappings": {"properties": {...}}} - 字段名含点号(如
user.id)?ES 默认拒绝,得提前在settings里加"index.mapping.dynamic": false或改用object类型包裹 - 别在
init()里初始化 client——Go 的 init 执行顺序不可控,极易引发死锁;放到main()或依赖注入容器里更安全
用 v8 客户端必须显式传 Addresses,否则 panic
v8 的 elasticsearch.NewClient() 不再接受裸 URL 参数,漏掉 elasticsearch.Config{Addresses: []string{"http://localhost:9200"}} 就会空指针 panic,不是连接超时也不是认证失败,而是直接崩在构造阶段。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 启用了 HTTPS 但没配证书?补上
Transport配置:&http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}} - 本地开发想关健康检查省开销?设
Healthcheck: false,但自己得加简单心跳逻辑(比如定期cat /_cluster/health) - 别信文档里“默认 localhost:9200”——v8 没默认值,不传
Addresses就是 nil,panic 是确定行为
PutIndex() 报错 400?先检查索引名合法性
ES 对索引名有硬性限制:不能含大写字母、不能以下划线或点号开头、不能含冒号或反斜杠。而 Go struct 字段常是 UserID、CreatedAt,有人顺手拿它当索引名拼接,一建就 400。
- 索引名建议写死,如
"order_search_v2",升级时建新索引 + 切 alias,别动态拼时间或服务名 - 如果业务主键是
int64,存为 ES 的document ID时务必转成 string(用strconv.FormatInt(id, 10)),避免 Java 客户端解析溢出导致后续 update 失效 - 复用 mapping?优先用 index template,而不是每次
CreateIndex().BodyJson()手写——模板能自动匹配新索引,也防 mapping 写错
字段类型映射不对,搜不到也 update 不了
Go struct tag 写 json:"created_at" 只影响序列化,ES 根本不看这个;它只认 mapping 里定义的 "created_at": {"type": "date", "format": "strict_date_optional_time||epoch_millis"}。类型不匹配,写入可能静默失败或转成字符串,后续范围查询直接失效。
- 上线前务必手动 PUT 一次 mapping,明确指定每个字段类型和 format
-
text字段要精确匹配?加"fields": {"keyword": {"type": "keyword"}}子字段,查时用created_at.keyword - 嵌套字段(如
address.city)必须声明为"type": "nested",否则 inner_hits 不生效,聚合也错
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










