go操作ES
Elasticsearch (简称 ES) 是一个基于 Lucene 的开源分布式搜索和分析引擎。它不仅能提供强大的全文检索功能,还能处理结构化数据的聚合分析。
整理了这份涵盖核心概念、环境搭建、常用 API 及 Go 语言实战 的入门教程。
📚 核心概念:ES 术语 vs 关系型数据库
理解这些概念是学习 ES 的第一步,我们可以将其与 MySQL 做类比:
| SQL 术语 | Elasticsearch 术语 | 说明 |
|---|---|---|
| Database (数据库) | Index (索引) | 存储相似文档的容器。 |
| Table (表) | Type (类型) | ES 7.x 已废弃,8.x 已移除。现在统一使用 _doc。 |
| Row (行) | Document (文档) | 具体的 JSON 数据,是 ES 的基本信息单元。 |
| Column (列) | Field (字段) | 文档中的属性。 |
| Schema (模式) | Mapping (映射) | 定义字段类型(如 text, keyword, integer)的元数据。 |
🛠️ 环境搭建 (Docker 推荐)
使用 Docker 是最快的方式。以下命令启动一个单节点的 ES 实例(以 8.x 版本为例):
# 1. 拉取镜像
docker pull docker.elastic.co/elasticsearch/elasticsearch:8.9.0
# 2. 启动容器
docker run -d --name es-node01 \
-p 9200:9200 -p 9300:9300 \
-e "discovery.type=single-node" \
-e "ES_JAVA_OPTS=-Xms1g -Xmx1g" \
-e "xpack.security.enabled=false" \
elasticsearch:8.9.0
注:xpack.security.enabled=false 用于关闭鉴权,方便本地开发调试。
启动后,访问 http://localhost:9200 看到 JSON 响应即表示成功。
⚙️ 常用 REST API 操作
ES 提供基于 HTTP 的 RESTful API。你可以使用 curl 或 Kibana 的 Dev Tools 进行测试。
1. 索引管理 (Index)
创建索引并定义 Mapping
在 ES 中,字段类型非常重要。text 用于全文检索(会被分词),keyword 用于精确匹配(不分词)。
PUT /books
{
"mappings": {
"properties": {
"title": { "type": "text" },
"author": { "type": "keyword" },
"price": { "type": "double" },
"publish_date": { "type": "date" }
}
}
}
删除索引
DELETE /books
2. 文档 CRUD 操作
新增/修改文档
如果 ID 存在则更新,不存在则新增。
POST /books/_doc/1
{
"title": "Elasticsearch 权威指南",
"author": "Clinton Gormley",
"price": 89.90,
"publish_date": "2015-01-01"
}
查询单个文档
GET /books/_doc/1
删除文档
DELETE /books/_doc/1
3. 搜索核心 (Search)
这是 ES 最强大的部分,所有搜索逻辑都写在 query 对象中。
全文检索 (Match Query)
会对输入进行分词。例如搜索 "Elasticsearch 指南",会匹配包含 "Elasticsearch" 或 "指南" 的文档。
GET /books/_search
{
"query": {
"match": {
"title": "Elasticsearch 指南"
}
}
}
精确匹配 (Term Query)
不分词,直接匹配完整值。适用于 keyword、数字、布尔类型。
GET /books/_search
{
"query": {
"term": {
"author": "Clinton Gormley"
}
}
}
范围查询 (Range Query)
GET /books/_search
{
"query": {
"range": {
"price": {
"gte": 50,
"lte": 100
}
}
}
}
组合查询 (Bool Query)
最常用的复杂查询,支持 must (必须满足), filter (过滤,不计算相关性得分), should (可选)。
GET /books/_search
{
"query": {
"bool": {
"must": [
{ "match": { "title": "Elasticsearch" } }
],
"filter": [
{ "range": { "price": { "gte": 80 } } }
]
}
}
}
💻 Go 语言实战
在 Go 中使用 ES,官方推荐的客户端是 github.com/elastic/go-elasticsearch。
1. 初始化客户端
package main
import (
"log"
"strings"
"github.com/elastic/go-elasticsearch/v8"
)
func main() {
cfg := elasticsearch.Config{
Addresses: []string{
"http://localhost:9200", // ES 地址
},
// 如果有用户名密码,在这里配置
// Username: "elastic",
// Password: "password",
}
es, err := elasticsearch.NewClient(cfg)
if err != nil {
log.Fatalf("Error creating the client: %s", err)
}
// 简单的连通性测试
res, err := es.Info()
if err != nil {
log.Fatalf("Error getting response: %s", err)
}
defer res.Body.Close()
log.Println("✅ 连接成功:", res.String())
}
2. 写入文档 (Index)
import (
"bytes"
"encoding/json"
// ... 其他引用
)
// 定义数据结构
type Book struct {
Title string `json:"title"`
Author string `json:"author"`
Price float64 `json:"price"`
}
func indexDoc(es *elasticsearch.Client) {
book := Book{
Title: "Go 语言实战",
Author: "张三",
Price: 59.00,
}
// 将结构体转为 JSON
var buf bytes.Buffer
if err := json.NewEncoder(&buf).Encode(book); err != nil {
log.Fatalf("Error encoding book: %s", err)
}
// 执行写入,ID 设为 "1"
res, err := es.Index(
"books",
&buf,
es.Index.WithDocumentID("1"),
)
if err != nil {
log.Fatalf("Error indexing document: %s", err)
}
defer res.Body.Close()
log.Printf("写入结果: %s", res.String())
}
3. 搜索文档 (Search)
Go 客户端使用 esapi.SearchRequest 来构建查询,通常直接传入 JSON 字符串或使用 strings.NewReader。
func searchDoc(es *elasticsearch.Client) {
// 构建查询 DSL (JSON 格式)
queryStr := `{
"query": {
"bool": {
"must": [
{ "match": { "title": "Go 语言" } }
],
"filter": [
{ "range": { "price": { "gte": 50 } } }
]
}
}
}`
res, err := es.Search(
es.Search.WithIndex("books"),
es.Search.WithBody(strings.NewReader(queryStr)),
es.Search.WithPretty(), // 格式化输出
)
if err != nil {
log.Fatalf("Error search request: %s", err)
}
defer res.Body.Close()
// 打印结果
var r map[string]interface{}
if err := json.NewDecoder(res.Body).Decode(&r); err != nil {
log.Fatalf("Error parsing response body: %s", err)
}
log.Printf("Found %d hits:", int(r["hits"].(map[string]interface{})["total"].(map[string]interface{})["value"].(float64)))
for _, hit := range r["hits"].(map[string]interface{})["hits"].([]interface{}) {
hitMap := hit.(map[string]interface{})
log.Printf(" > ID: %s, Source: %v", hitMap["_id"], hitMap["_source"])
}
}
📌 总结
- ES 是文档型数据库,数据以 JSON 格式存储。
- Mapping 很重要,区分
text(全文搜) 和keyword(精确搜)。 - 查询 DSL 是核心,掌握
match,term,bool,range即可应对 80% 的场景。 - Go 开发 主要是将 JSON 查询语句通过
strings.NewReader传递给官方客户端。

浙公网安备 33010602011771号