主题
27 · Elasticsearch 搜索
目标:理解倒排索引与「索引文档 / 查询」,用 Go 完成笔记标题+正文的简单搜索。
前置:17 · GORM · 22 · Docker
官方:Elasticsearch Guide · Go:go-elasticsearch
1. 为何 MySQL LIKE 不够
MySQL LIKE '%词%' | Elasticsearch |
|---|---|
| 难走索引、大数据慢 | 倒排索引面向全文 |
| 分词/相关度弱 | Analyzer + BM25 相关度 |
| 联想、高亮、聚合弱 | 搜索产品常见能力 |
Node 对照:elasticsearch JS client / OpenSearch。
本篇用 单节点学习版;生产集群与中文分词(IK)另开专题即可。
2. 核心概念
text
Index(类似库表) → Document(JSON 文档) → Field
写入时:原文 → analyzer → 词项 → 倒排列表(词项 → docId)
查询时:查询串同样分析 → 找候选 → 打分排序1
2
3
2
3
| 词 | 含义 |
|---|---|
| mapping | 字段类型(text / keyword / date…) |
| text vs keyword | 全文可分词 vs 精确聚合/过滤 |
| refresh | 近实时可见(默认约 1s) |
3. Compose(单节点学习)
yaml
es:
image: docker.elastic.co/elasticsearch/elasticsearch:8.15.0
environment:
- discovery.type=single-node
- xpack.security.enabled=false # 仅本地学习
- ES_JAVA_OPTS=-Xms512m -Xmx512m
ports:
- "9200:9200"
# 内存紧张的机器:可改用 OpenSearch 或缩小堆1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
bash
curl http://127.0.0.1:92001
4. 最小可跑 demo
bash
go get github.com/elastic/go-elasticsearch/v81
建索引 + 写入:
go
es, err := elasticsearch.NewDefaultClient() // 默认 localhost:9200
fail(err)
mapping := `{
"mappings": {
"properties": {
"title": { "type": "text" },
"content": { "type": "text" },
"userId": { "type": "keyword" },
"tags": { "type": "keyword" }
}
}
}`
_, _ = es.Indices.Create("notes", es.Indices.Create.WithBody(strings.NewReader(mapping)))
doc := `{"title":"夏天手帐","content":"海边与冰棍","userId":"u1","tags":["travel"]}`
_, err = es.Index("notes", strings.NewReader(doc), es.Index.WithDocumentID("n1"))
fail(err)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
搜索:
go
query := `{
"query": {
"bool": {
"must": [{ "match": { "content": "海边" }}],
"filter": [{ "term": { "userId": "u1" }}]
}
}
}`
res, err := es.Search(
es.Search.WithIndex("notes"),
es.Search.WithBody(strings.NewReader(query)),
)
fail(err)
defer res.Body.Close()1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
同步策略(练手):
text
写 MySQL 成功 → 同步 Index 文档(或 Asynq 异步重建)
删笔记 → Delete 文档1
2
2
5. 动手清单
- [ ]
curl集群 green/yellow 可接受(单节点常 yellow) - [ ] 写入 3 篇笔记文档,按关键词搜到
- [ ]
filter按userId隔离 - [ ] 更新正文后再搜,结果变化
- [ ] 口述:text 与 keyword 何时用哪个
6. 项目驱动
| 场景 | 做法 |
|---|---|
| 手帐全文 / 标签 | title+content match;tags term |
| 搜索联想 | completion / prefix(进阶) |
| 与 Redis | 热搜词 ZSet;结果短缓存 |
中文:默认分词对中文不理想 → 生产常挂 IK;暑假可先英文/空格场景验证链路。
7. 常见坑 + AI 审查
| 坑 | 说明 |
|---|---|
| 本机内存爆 | 堆 512m 仍不够就别硬跑;用云托管或跳过实操读概念 |
| 当数据库用 ES | 主存仍 MySQL;ES 是派生索引 |
只 match_all 当验收 | 必须带 match + filter |
| AI 关闭安全后直接公网暴露 | 仅本地;生产开安全与网络隔离 |
| mapping 事后改类型 | 常需 reindex;设计字段要慎重 |
8. 下一篇
服务间强契约 RPC:
→ 28 · gRPC + ProtoBuf
