Go 工程師體系課 012【學習筆記】

在 Go 中整合 Elasticsearch

1. 客戶端函式庫選擇

1.1 主流 Go ES 客戶端

  • olivere/elastic:功能最全面,API 設計優雅,支援 ES 7.x/8.x
  • elastic/go-elasticsearch:官方客戶端,輕量級,更接近原生 REST API
  • go-elasticsearch/elasticsearch:社群維護的官方客戶端分支

1.2 推薦選擇

olivere/elastic 是生產環境首選,原因:

  • 型別安全的查詢建構器
  • 完善的錯誤處理
  • 支援所有 ES 功能(聚合、批次操作、索引管理等)
  • 活躍維護,版本更新及時

2. olivere/elastic 快速入門

2.1 安裝依賴

go mod init your-project
go get github.com/olivere/elastic/v7

2.2 基礎連線

package main

import (
    "context"
    "fmt"
    "log"

    "github.com/olivere/elastic/v7"
)

func main() {
    // 建立客戶端
    client, err := elastic.NewClient(
        elastic.SetURL("http://localhost:9200"),
        elastic.SetSniff(false), // 單節點環境關閉嗅探
        elastic.SetHealthcheck(false), // 關閉健康檢查
    )
    if err != nil {
        log.Fatal(err)
    }
    defer client.Stop()

    // 檢查連線
    info, code, err := client.Ping("http://localhost:9200").Do(context.Background())
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("ES 版本: %s, 狀態碼: %d\n", info.Version.Number, code)
}

2.3 連線配置選項

client, err := elastic.NewClient(
    elastic.SetURL("http://localhost:9200", "http://localhost:9201"), // 多節點
    elastic.SetBasicAuth("username", "password"), // 認證
    elastic.SetSniff(true), // 自動發現節點
    elastic.SetHealthcheckInterval(10*time.Second), // 健康檢查間隔
    elastic.SetMaxRetries(3), // 最大重試次數
    elastic.SetRetryStatusCodes(502, 503, 504), // 重試狀態碼
    elastic.SetGzip(true), // 啟用壓縮
    elastic.SetErrorLog(log.New(os.Stderr, "ES ", log.LstdFlags)), // 錯誤日誌
    elastic.SetInfoLog(log.New(os.Stdout, "ES ", log.LstdFlags)), // 資訊日誌
)

3. 索引管理

3.1 建立索引

// 建立索引
createIndex, err := client.CreateIndex("products").
    BodyString(`{
        "settings": {
            "number_of_shards": 1,
            "number_of_replicas": 1
        },
        "mappings": {
            "properties": {
                "title": {
                    "type": "text",
                    "analyzer": "ik_smart",
                    "fields": {
                        "keyword": {
                            "type": "keyword"
                        }
                    }
                },
                "price": {"type": "double"},
                "status": {"type": "keyword"},
                "created_at": {"type": "date"}
            }
        }
    }`).
    Do(context.Background())
if err != nil {
    log.Fatal(err)
}
fmt.Printf("索引建立結果: %v\n", createIndex.Acknowledged)

3.2 檢查索引是否存在

exists, err := client.IndexExists("products").Do(context.Background())
if err != nil {
    log.Fatal(err)
}
fmt.Printf("索引存在: %v\n", exists)

3.3 刪除索引

deleteIndex, err := client.DeleteIndex("products").Do(context.Background())
if err != nil {
    log.Fatal(err)
}
fmt.Printf("索引刪除結果: %v\n", deleteIndex.Acknowledged)

4. 文件操作

4.1 定義文件結構

type Product struct {
    ID        string    `json:"id"`
    Title     string    `json:"title"`
    Price     float64   `json:"price"`
    Status    string    `json:"status"`
    CreatedAt time.Time `json:"created_at"`
    Tags      []string  `json:"tags"`
}

4.2 新增文件

// 新增單個文件
product := Product{
    ID:        "1",
    Title:     "iPhone 15 Pro",
    Price:     7999.0,
    Status:    "active",
    CreatedAt: time.Now(),
    Tags:      []string{"phone", "apple", "premium"},
}

put1, err := client.Index().
    Index("products").
    Id("1").
    BodyJson(product).
    Do(context.Background())
if err != nil {
    log.Fatal(err)
}
fmt.Printf("文件索引結果: %s\n", put1.Result)

4.3 取得文件

// 根據 ID 取得文件
get1, err := client.Get().
    Index("products").
    Id("1").
    Do(context.Background())
if err != nil {
    log.Fatal(err)
}

if get1.Found {
    var product Product
    err = json.Unmarshal(get1.Source, &product)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("取得文件: %+v\n", product)
}

4.4 更新文件

// 部分更新
update, err := client.Update().
    Index("products").
    Id("1").
    Doc(map[string]interface{}{
        "price": 7599.0,
    }).
    Do(context.Background())
if err != nil {
    log.Fatal(err)
}
fmt.Printf("更新結果: %s\n", update.Result)

4.5 刪除文件

delete, err := client.Delete().
    Index("products").
    Id("1").
    Do(context.Background())
if err != nil {
    log.Fatal(err)
}
fmt.Printf("刪除結果: %s\n", delete.Result)

5. 批次操作

5.1 批次索引

bulkRequest := client.Bulk()

products := []Product{
{ID: "2", Title: "Samsung Galaxy S24", Price: 5999.0, Status: "active", CreatedAt: time.Now()},
{ID: "3", Title: "MacBook Pro M3", Price: 12999.0, Status: "active", CreatedAt: time.Now()},
{ID: "

主題測試文章,只做測試使用。發佈者:Walker,轉轉請注明出處:https://www.walker-learn.xyz/archives/4785

(0)
Walker的頭像Walker
上一篇 2025年11月25日 12:00
下一篇 2025年11月25日 10:00

相關推薦

  • Go工程師體系課 008【學習筆記】

    訂單及購物車 先從庫存服務中將 srv 的服務程式碼框架複製過來,搜尋取代對應的名稱(order_srv) 加密技術基礎 對稱式加密(Symmetric Encryption) 原理: 使用同一個金鑰進行加密和解密 就像一把鑰匙,既能鎖門也能開門 加密速度快,適合大量資料傳輸 使用情境: 本機檔案加密 資料庫內容加密 大量資料傳輸時的內容加密 內部系統間的快速通…

    個人 2025年11月25日
    28200
  • Go 工程師體系課 004【學習筆記】

    需求分析 後台管理系統 商品管理 商品列表 商品分類 品牌管理 品牌分類 訂單管理 訂單列表 使用者資訊管理 使用者列表 使用者地址 使用者留言 輪播圖管理 電商系統 登入頁面 首頁 商品搜尋 商品分類導覽 輪播圖展示 推薦商品展示 商品詳情頁 商品圖片展示 商品描述 商品規格選擇 加入購物車 購物車 商品列表 數量調整 刪除商品 結帳功能 使用者中心 訂單中心 我的…

    2025年11月25日
    28800
  • 向世界揮手,擁抱無限可能 🌍✨

    站得更高,看得更遠 生活就像一座座高樓,我們不斷向上攀登,不是為了炫耀高度,而是為了看到更廣闊的風景。圖中的兩位女孩站在城市之巔,伸展雙手,徬彿在迎接世界的無限可能。這不僅是一次俯瞰城市的旅程,更是對自由和夢想的禮讚。 勇敢探索,突破邊界 每個人的生活都是一場冒險,我們生而自由,就該去探索未知的風景,去經歷更多的故事。或許路途中會有挑戰,但正是那些攀爬的瞬間…

    個人 2025年2月26日
    1.4K00
  • Go工程師體系課 009【學習筆記】

    其他一些功能 個人中心 收藏 管理收貨地址(增刪改查) 留言 複製inventory_srv--> userop_srv 查詢替換所有的inventory Elasticsearch 深度解析文件 1. 什麼是Elasticsearch Elasticsearch是一個基於Apache Lucene建構的分散式、RESTful搜尋和分析引擎,能夠快速地…

    個人 2025年11月25日
    33900
  • 深入理解ES6 002【學習筆記】

    字串與正規表達式 字串與正規表達式 JavaScript 字串一直都是基於 16 位元字元編碼(UTF-16)建構而成。每 16 位元的序列是一個編碼單元(code unit),代表一個字元。length、charAt() 等字串屬性與方法都是基於這個編碼單元建構的。Unicode 的目標是為世界上每一個字元提供全球唯一的識別碼。如果我們將字元長度限制在 16 位元,碼位數量將不…

    個人 2025年3月8日
    2.0K00