golang中使用elasticsearch

本文首發於我的個人博客

這是一篇介紹如何利用golang第三方庫https://github.com/olivere/elastic進行elasticsearch的操作的文章。
文章中並不會介紹非常詳細的API,更側重於作者在工作中的使用經驗和查文檔經驗。文章中主要包括以下內容:

  1. 作者認爲比較重要的API設計理念以及文檔查閱方式
  2. 作者在工作中使用到的elasticsearch的實例,包括從接到需求,查閱文檔,並實現的過程

API設計理念思考

API的分類

在使用elasticsearch的golang Client過程中,我覺得可以將olivere/elastic的常用API分作三類:

  1. 面向elasticsearch的metadata的Service
  2. 面向elasticsearch的data的Service
  3. 面向Query

而這三類分別對應了對elasticsearch的不同類別的操作:

  1. 面向elasticsearch的metadata的Service,主要是對elasticsearch的metadata進行查詢和操作,比如
    • 配置elasticsearch
    • 查詢elasticsearch的狀態,比如集羣狀態,節點數目等
  2. 面向elasticsearch的data的Service,住喲是對elasticsearch內的數據和數據格式進行操作
    1. elasticsearch中的index的metadata進行操作,比如
      1. 查詢是否存在某個index
      2. 創建並配置index
    2. elasticsearch中的index下的document的增刪改操作
  3. 面向Query,主要是對index下的document的查詢操作

分類在代碼中的體現

首先需要說明,在olivere/elastic的所有操作都是依靠生成一個XXXService對象然後XXXService.Do(ctx)來實現的,這裏將他們分成面向Service和麪向Query只是表示後者我們的主要精力都會集中在構造Query上

面向elasticsearch的metadata的Service

面向elasticsearch的metadata的Service,一般是通過建立連接的ESClient,新建出查詢或者操作所需的Service,而後進行操作的模式

比如如下,查詢集羣內es節點數

// 建立連接的Client
esClient, _ := elastic.NewClient()
// 新建出用於操作的Service
clusterHealthClient := elastic.NewClusterHealthService(esClient)
// 查詢,拿到結果
result, _:= clusterHealthClient.Do(context.Background())
fmt.Println(result.NumberOfNodes)

面向elasticsearch的data的Service

面向elasticsearch的data的Service,一般是通過建立連接的ESClient的成員函數直接取得Service,而後進行操作

比如如下,新建索引

// Create a new index.
mapping := `{
    "settings":{
        "number_of_shards":1,
        "number_of_replicas":0
    },
    "mappings":{
        "properties":{
            "tags":{
                "type":"keyword"
            },
            "location":{
                "type":"geo_point"
            },
            "suggest_field":{
                "type":"completion"
            }
        }
    }
}`
ctx := context.Background()
createIndex, _ := esClient.CreateIndex("twitter").BodyString(mapping).Do(ctx)
fmt.Println(createIndex.Index)

面向Query

面向Query,一般是先新建出Query,而後通過client.Search().Index(index).Query(query).Do(ctx)的方式執行查詢操作

比如如下,查詢上一個構造的索引中,tags字段含有test的document

query := elastic.NewBoolQuery()
query = query.Must(elastic.NewTermQuery("tags", "test"))
result, _ := esClient.Search().Index("twitter").Query(query).Do(context.Background())

API文檔的查詢方法

查詢olivere/elastic的文檔,主要有三個來源:

  1. 項目Wiki https://github.com/olivere/elastic/wiki
  2. 源代碼 https://github.com/olivere/elastic
  3. elasticsearch官方文檔 https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html

這三者各有特點:

  1. 項目Wiki
    • 優點:簡單直接,並且會給出相應的操作的示例代碼,上手很快
    • 缺點:示例較簡單,且不全面,面對複雜邏輯/特定邏輯很可能缺乏指導性,或者找不到相關文檔
  2. 源代碼
    • 優點:全面而且本質的東西,掌握了源代碼就掌握了一切
    • 缺點:複雜,費力,考慮投入產出比,幾乎絕無必要源碼級掌握(除非想成爲庫的開發者)
  3. elasticsearch官方文檔
    • 優點:比較齊全的同時仍然是可讀性較高的文檔,難度在項目Wiki和源代碼之間
    • 缺點:沒有直接對應到olivere/elastic的API上,找到elasticsearch的API之後,要回頭再找olivere/elastic的API

一般的查詢方式如下:

  1. 首先明確需求,即到底需要獲得elasticsearch的什麼信息或者對其進行什麼操作
  2. 明確需求後先查閱Wiki,如果有相應的條目,可用的就可以直接用了
  3. Wiki中找不到,那就按照api設計理念思考中描述的進行分類
  4. 分類後有兩條路徑
    1. 源代碼中尋找對應的Service或者Query接口,找到後去elasticsearch文檔驗證
    2. elasticsearch文檔中尋找對應的查詢接口,找到後去olivere/elastic中找對應的接口

當然,合理利用其他資源作爲文檔入口也是有必要的(或許這纔是很多人的首選):

  1. Stack Overflow,啓動!
  2. 輸入關鍵字查詢,能找到合適的問答,就直接採用,不能就返回上述的一般查詢方式

使用實例與解決過程

查詢集羣的健康狀態

過程:

  1. 查閱Wiki,沒有
  2. 查閱源代碼,cluster爲關鍵字查找,找到cluster_health.go,前往註釋中指定的elasticsearch文檔http://www.elastic.co/guide/en/elasticsearch/reference/7.0/cluster-health.html驗證想法
  3. 想法驗證成功,編程

實現text類型的字段的模糊查找

過程:

  1. 查找Wiki,沒有
  2. 源代碼,elasticsearch文檔沒有“模糊查找”相關的部分
  3. stack overflow 搜索 match part of text,找到使用正則表達式查詢RegexQuery的方法
  4. 返回elasticsearch文檔驗證,驗證成功
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章