Golang与Elasticsearch搭配检索运用

一、简介下:

Elasticsearch 是一个高性能、分布式、全文搜索与分析引擎,它的核心优势在于 对结构化和非结构化数据进行高效搜索、统计与分析,远远超出传统关系数据库(如 MySQL)的全文检索能力。

让你能在海量数据中,毫秒级地进行智能搜索和实时分析。

核心模块:全文检索、结构化查询、聚合分析、实时写入/搜索、分布式扩展、高可用性、可视化分析。

常见应用场景 :博客/文档搜索、电商搜索推荐、日志分析、指标分析、审计等

二、运用(举例博客系统中)

text 复制代码
      用户写博客
          ↓
     ➤ https://zhida.zhihu.com/search?content_id=257857562&content_type=Article&match_order=1&q=API+Server&zhida_source=entity (https://zhida.zhihu.com/search?content_id=257857562&content_type=Article&match_order=1&q=Golang&zhida_source=entity)
          ↓
    数据写入 MySQL 数据库
          ↓
    同步写入 Elasticsearch

1)Blog 模型(models/blog.go)

复制代码
type Blog struct {
    ID        int64     `gorm:"primaryKey" json:"id"`
    Title     string    `json:"title"`
    Content   string    `json:"content"`
    Tags      string    `json:"tags"` // JSON string
    Author    string    `json:"author"`
    CreatedAt time.Time `json:"created_at"`
    UpdatedAt time.Time `json:"updated_at"`
}

2)写入博客(MySQL + Elasticsearch 同步)

⚡️services/blog_service.go

复制代码
func CreateBlog(blog *models.Blog) error {
if err := db.Create(blog).Error; err != nil {
return err
    }
return elastic.IndexBlog(blog) // 同步到 ES
}
func UpdateBlog(blog *models.Blog) error {
if err := db.Save(blog).Error; err != nil {
return err
    }
return elastic.IndexBlog(blog) // 重新索引
}
func DeleteBlog(blogID int64) error {
if err := db.Delete(&models.Blog{}, blogID).Error; err != nil {
return err
    }
return elastic.DeleteBlog(blogID)
}

⚡️elastic/client.go

复制代码
var es *elasticsearch.Client

func InitES() {
    cfg := elasticsearch.Config{Addresses: []string{"http://localhost:9200"}}
       //搭配pwd使用 :
       //cfg := elasticsearch.Config{Addresses: []string{eshost}, Username: esname,Password: espwd}
    client, err := elasticsearch.NewClient(cfg)
if err != nil {
        log.Fatalf("ES init error: %v", err)
    }
    es = client
}

func IndexBlog(blog *models.Blog) error {
    body, _ := json.Marshal(blog)
    req := esapi.IndexRequest{
        Index:      "blogs",
        DocumentID: strconv.FormatInt(int64(blog.ID), 10),
        Body:       bytes.NewReader(body),
        Refresh:    "true",
    }
    res, err := req.Do(context.Background(), esct)
    if err != nil {
        return err
    }
    defer res.Body.Close()
    return nil
}
func DeleteBlog(blogID int64) error {
    req := esapi.DeleteRequest{
        Index:      "blogs",
        DocumentID: fmt.Sprintf("%d", blogID),
        Refresh:    "true",
    }
    res, err := req.Do(context.Background(), esct)
    if err != nil {
        return err
    }
    defer res.Body.Close()
    return nil
}

引入官方库

复制代码
go get github.com/elastic/go-elasticsearch/v8

3)数据流转方式

text 复制代码
            用户访问 Web/前端
                  │
        ┌─────────▼──────────┐
        │      Golang 后端服务 │
        └─────────┬──────────┘
                  │
       ┌──────────┼────────────┐
       │                       │
       ▼                       ▼
MySQL 关系型数据库      Elasticsearch 搜索引擎
 ️ 存储结构化数据              存储可检索文档数据
- title                    - title(分词)
- content                  - content(分词 + 高亮)
- created_by               - 拼音/模糊匹配
- tag_id 等业务字段         - 自定义字段聚合、排序

4)搜索实现

复制代码
type BlogHit struct {
    ID     string                 `json:"id"`
    Source map[string]interface{} `json:"source"`
}
// 搜索博客(支持标题和内容)
func SearchBlogs(keyword string) ([]BlogHit, error) {
    query := fmt.Sprintf(`
    {
      "query": {
        "multi_match": {
          "query": "%s",
          "fields": ["title", "content"]
        }
      },
      "highlight": {
        "fields": {
          "title": {},
          "content": {}
        }
      }
    }`, keyword)
    res, err := es.Search(
        esct.Search.WithContext(context.Background()),
        esct.Search.WithIndex("blogs"),
        esct.Search.WithBody(strings.NewReader(query)),
        esct.Search.WithTrackTotalHits(true),
        esct.Search.WithPretty(),
    )
    if err != nil {
        return nil, err
    }
    defer res.Body.Close()
    if res.IsError() {
        return nil, fmt.Errorf("error response from ES: %s", res.String())
    }
    var r struct {
        Hits struct {
            Hits []struct {
                ID     string                 `json:"_id"`
                Source map[string]interface{} `json:"_source"`
            } `json:"hits"`
        } `json:"hits"`
    }
    if err := json.NewDecoder(res.Body).Decode(&r); err != nil {
        return nil, err
    }
    var results []BlogHit
    for _, hit := range r.Hits.Hits {
        results = append(results, BlogHit{
            ID:     hit.ID,
            Source: hit.Source,
        })
    }
    return results, nil
}

IKSSr">可视化执行逻辑图如下

复制代码
[ 用户输入关键词 "golang" ]
          ↓
     [ Vue 前端 ]
          ↓
   /search/blog?q=golang
          ↓
[ Golang 后端调用 ES 查询 + 高亮]
          ↓
[ Elasticsearch 返回文档列表 ]
          ↓
[ Vue 展示博客标题 + 摘要 + 图片 ]

前端调取方式如下

复制代码
//vue调用golang api
axios({
         method: "get",
         url: "http://127.0.0.1:2023/GetSearchBlogs?title="+event,
        })
        .then((res) => {
          if(res.data.data.lists==null){
            //ElMessage.error("没有相关记录")
            searchcount.value=0
            blogData.values=[]
            return
          }else{
             searchcount.value=res.data.lists.length
             blogData.values=res.data.lists
          } 
    })

三、效果演示

四、更多可扩展性

  • 搜索智能:模糊匹配、同义词、拼写纠错、词根分析
  • 实时统计:统计聚合性能强(如 PV、UV、热词排行)
  • 多语言支持:内置中文、英文、日文等分词器(可使用 IK、jieba 等)
  • 高并发场景:使用 Kafka 或rabbitmq做异步同步
相关推荐
YGGP8 小时前
吃透 Golang 基础:Goroutine
后端·golang
Listennnn9 小时前
Go用闭包简化创建 goroutine 和 defer 语句的内部实现
golang
是紫焅呢12 小时前
F接口基础.go
开发语言·后端·青少年编程·golang·visual studio code
IT艺术家-rookie21 小时前
golang--channel的关键特性和行为
开发语言·后端·golang
子恒20051 天前
警惕GO的重复初始化
开发语言·后端·云原生·golang
是紫焅呢1 天前
C函数基础.go
开发语言·后端·青少年编程·golang·学习方法·visual studio code
柯南二号2 天前
用Go写一个飞书机器人定时发送消息的程序
golang·机器人·飞书
是紫焅呢2 天前
D包和模块.go
开发语言·后端·golang·学习方法·visual studio code
Code季风2 天前
跨语言RPC:使用Java客户端调用Go服务端的HTTP-RPC服务
java·网络协议·http·rpc·golang
Code季风2 天前
学习 Protobuf:序列化、反序列化及与 JSON 的对比
学习·rpc·golang·json