go操作elasticsearch示例

guyan0319發表於2021-10-28

這裡我使用elasticsearch官方給的go語言包(go-elasticsearch
go-elasticsearch向前相容,這意味著客戶端支援與更大或同等次要版本的 Elasticsearch 通訊。Elasticsearch 語言客戶端僅向後相容預設發行版,不提供任何保證。

環境介紹:

版本
Elasticsearch:v7.15

安裝

go.mod 檔案中新增

require github.com/elastic/go-elasticsearch/v8 main

或者

git clone --branch main https://github.com/elastic/go-elasticsearch.git $GOPATH/src/github.com/elastic/go-elasticsearch

示例:

新建 es.go 存入 es目錄

package es

import (
    "bytes"
    "context"
    "encoding/json"
    "fmt"
    "github.com/elastic/go-elasticsearch/v8"
    "github.com/elastic/go-elasticsearch/v8/esapi"
    "log"
    "net/http"
)

var EsClient *elasticsearch.Client

func init() {

    cfg := elasticsearch.Config{
         Addresses: []string{
            "http://localhost:9200",
            },
    }
    var err error
    EsClient, err = elasticsearch.NewClient(cfg)
    if err != nil {
        log.Fatalln("Failed to connect to es")
    }
}
func failOnError(err error, msg string) {
    if err != nil {
        log.Fatalf("%s: %s", msg, err)
    }
}

// idx 為空,預設隨機唯一字串
func Index(index, idx string, doc map[string]interface{}) {
    //index:="my_index_name_v1"
    res, err := EsClient.Info()
    fmt.Println(res, err)
    if err != nil {
        log.Fatalf("Error getting response: %s", err)
    }
    var buf bytes.Buffer
    //doc := map[string]interface{}{
    //    "title":   "中國",
    //    "content": "中國早日統一臺灣",
    //    "time":    time.Now().Unix(),
    //    "date":    time.Now(),
    //}
    if err = json.NewEncoder(&buf).Encode(doc); err != nil {
        fmt.Println(err, "Error encoding doc")
        return
    }
    res, err = EsClient.Index(
        index,                              // Index name
        &buf,                               // Document body
        EsClient.Index.WithDocumentID(idx), // Document ID
        // Document ID
        EsClient.Index.WithRefresh("true"), // Refresh
    )
    //res, err = EsClient.Create(index, idx, &buf)
    if err != nil {
        fmt.Println(err, "Error create response")
    }
    defer res.Body.Close()
    fmt.Println(res.String())
    log.Println(res)
}

//struct 型別允許使用更實際的方法,您可以在其中建立一個新結構,將請求配置作為欄位,並使用上下文和客戶端作為引數呼叫 Do() 方法:
func IndexEspi(index, idx string, doc map[string]interface{}) {
    //index:="my_index_name_v1"
    res, err := EsClient.Info()
    fmt.Println(res, err)
    if err != nil {
        log.Fatalf("Error getting response: %s", err)
    }
    var buf bytes.Buffer
    //doc := map[string]interface{}{
    //    "title":   "中國",
    //    "content": "中國早日統一臺灣",
    //    "time":    time.Now().Unix(),
    //    "date":    time.Now(),
    //}
    if err = json.NewEncoder(&buf).Encode(doc); err != nil {
        fmt.Println(err, "Error encoding doc")
        return
    }

    req := esapi.IndexRequest{
        Index:      index,  // Index name
        Body:       &buf,   // Document body
        DocumentID: idx,    // Document ID
        Refresh:    "true", // Refresh
    }

    res, err = req.Do(context.Background(), EsClient)
    if err != nil {
        log.Fatalf("Error getting response: %s", err)
    }
    defer res.Body.Close()
    fmt.Println(res.String())
    log.Println(res)
}
func Search(index string, query map[string]interface{}) {
    res, err := EsClient.Info()
    if err != nil {
        fmt.Println(err, "Error getting response")
    }
    //fmt.Println(res.String())
    // search - highlight
    var buf bytes.Buffer
    //query := map[string]interface{}{
    //    "query": map[string]interface{}{
    //        "match": map[string]interface{}{
    //            "title": title,
    //        },
    //    },
    //    "highlight": map[string]interface{}{
    //        "pre_tags":  []string{"<font color='red'>"},
    //        "post_tags": []string{"</font>"},
    //        "fields": map[string]interface{}{
    //            "title": map[string]interface{}{},
    //        },
    //    },
    //}
    if err := json.NewEncoder(&buf).Encode(query); err != nil {
        fmt.Println(err, "Error encoding query")
    }
    // Perform the search request.
    res, err = EsClient.Search(
        EsClient.Search.WithContext(context.Background()),
        EsClient.Search.WithIndex(index),
        EsClient.Search.WithBody(&buf),
        EsClient.Search.WithTrackTotalHits(true),
        EsClient.Search.WithFrom(0),
        EsClient.Search.WithSize(10),
        EsClient.Search.WithSort("time:desc"),
        EsClient.Search.WithPretty(),
    )
    if err != nil {
        fmt.Println(err, "Error getting response")
    }
    defer res.Body.Close()
    fmt.Println(res.String())
}

//刪除 index 根據 索引名 id

func Delete(index, idx string) {
    //index:="my_index_name_v1"
    res, err := EsClient.Info()
    fmt.Println(res, err)
    if err != nil {
        log.Fatalf("Error getting response: %s", err)
    }
    res, err = EsClient.Delete(
        index, // Index name
        idx,   // Document ID
        EsClient.Delete.WithRefresh("true"),
    )
    if err != nil {
        fmt.Println(err, "Error create response")
    }
    defer res.Body.Close()
    fmt.Println(res.String())
    log.Println(res)
}
func DeleteByQuery(index []string, query map[string]interface{}) {
    res, err := EsClient.Info()
    if err != nil {
        fmt.Println(err, "Error getting response")
    }
    //fmt.Println(res.String())
    // search - highlight
    var buf bytes.Buffer
    //query := map[string]interface{}{
    //    "query": map[string]interface{}{
    //        "match": map[string]interface{}{
    //            "title": title,
    //        },
    //    },
    //    },
    //}
    if err := json.NewEncoder(&buf).Encode(query); err != nil {
        fmt.Println(err, "Error encoding query")
    }
    // Perform the search request.
    res, err = EsClient.DeleteByQuery(
        index,
        &buf,
    )
    if err != nil {
        fmt.Println(err, "Error getting response")
    }
    defer res.Body.Close()
    fmt.Println(res.String())

}
func SearchEsapiSql(query map[string]interface{}) {
    jsonBody, _ := json.Marshal(query)
    req := esapi.SQLQueryRequest{Body: bytes.NewReader(jsonBody)}
    res, _ := req.Do(context.Background(), EsClient)
    defer res.Body.Close()
    fmt.Println(res.String())
}
func SearchHttp(method, url string, query map[string]interface{}) {
    jsonBody, _ := json.Marshal(query)
    req, _ := http.NewRequest(method, url, bytes.NewReader(jsonBody))
    req.Header.Add("Content-type", "application/json")
    res, err := EsClient.Perform(req)
    if err != nil {
        return
    }
    defer res.Body.Close()
    buf := new(bytes.Buffer)
    buf.ReadFrom(res.Body)
    fmt.Println(buf.String())
}

新建 main.go

package main
import "demo/es"
func main() {
    index := "my_index_name_v4"
    //建立索引並設定對映
    //query := map[string]interface{}{
    //    "mappings": map[string]interface{}{
    //        "properties": map[string]interface{}{
    //            "title": map[string]interface{}{
    //                "type": "text",
    //            },
    //            "content": map[string]interface{}{
    //                "type": "text",
    //            },
    //            "location": map[string]interface{}{
    //                "type": "geo_point",
    //            },
    //            "time": map[string]interface{}{
    //                "type": "long",
    //            },
    //            "date": map[string]interface{}{
    //                "type": "date",
    //            },
    //            "age": map[string]interface{}{
    //                "type": "keyword",
    //            },
    //        },
    //    },
    //}
    //url := index
    //注意 對映資訊不能更新
    //es.SearchHttp("PUT", url, query)

    //新增或修改文件,沒有索引建立
    //doc := map[string]interface{}{
    //    "title":    "你好",
    //    "content":  "中國美麗的城市",
    //    "location": "41.015, -75.011",
    //    "time":     time.Now().Unix(),
    //    "date":     time.Now(),
    //    "age":      20,
    //}

    //es.Index(index, "", doc)
    //es.IndexEspi(index, "idx5", doc)
    //刪除索引
    //es.Delete(index, "idx3")
    //query := map[string]interface{}{
    //    "query": map[string]interface{}{
    //        "match": map[string]interface{}{
    //            "title": "vvvvv我愛你!!!!",
    //        },
    //    },
    //}
    //indexArr := []string{index}
    //es.DeleteByQuery(indexArr, query)
    ////搜尋單個欄位
    //query := map[string]interface{}{
    //    "query": map[string]interface{}{
    //        "match": map[string]interface{}{
    //            "title": "我愛你中國",
    //        },
    //    },
    //    "highlight": map[string]interface{}{
    //        "pre_tags":  []string{"<font color='red'>"},
    //        "post_tags": []string{"</font>"},
    //        "fields": map[string]interface{}{
    //            "title": map[string]interface{}{},
    //        },
    //    },
    //}

    //搜尋多個欄位
    //query := map[string]interface{}{
    //    "query": map[string]interface{}{
    //        "multi_match": map[string]interface{}{
    //            "query":  "中國",
    //            "fields": []string{"title", "content"},
    //        },
    //    },
    //    "highlight": map[string]interface{}{
    //        "pre_tags":  []string{"<font color='red'>"},
    //        "post_tags": []string{"</font>"},
    //        "fields": map[string]interface{}{
    //            "title": map[string]interface{}{},
    //        },
    //    },
    //}
    //提高某個欄位權重,可以使用 ^ 字元語法為單個欄位提升權重,在欄位名稱的末尾新增 ^boost ,其中 boost 是一個浮點數:
    //query := map[string]interface{}{
    //    "query": map[string]interface{}{
    //        "multi_match": map[string]interface{}{
    //            "query":  "中國",
    //            "fields": []string{"title", "content^2"},
    //        },
    //    },
    //    "highlight": map[string]interface{}{
    //        "pre_tags":  []string{"<font color='red'>"},
    //        "post_tags": []string{"</font>"},
    //        "fields": map[string]interface{}{
    //            "title": map[string]interface{}{},
    //        },
    //    },
    //}

    //顯示所有的
    //query := map[string]interface{}{
    //    "query": map[string]interface{}{
    //        "match_all": map[string]interface{}{},
    //    },
    //}
    //es.Search(index, query)
    //地理距離過濾器( geo_distance )以給定位置為圓心畫一個圓,來找出那些地理座標落在其中的文件:
    //query := map[string]interface{}{
    //    "query": map[string]interface{}{
    //        "bool": map[string]interface{}{
    //            "must": map[string]interface{}{
    //                "match_all": map[string]interface{}{}, // 這裡不設定其他查詢條件,所以匹配全部文件
    //            },
    //            "filter": map[string]interface{}{
    //                "geo_distance": map[string]interface{}{
    //                    "distance": "100km",
    //                    "location": map[string]interface{}{
    //                        "lat": 40.715,
    //                        "lon": -73.988,
    //                    },
    //                }},
    //        },
    //    },
    //    "sort": map[string]interface{}{ // 設定排序條件
    //        "_geo_distance": map[string]interface{}{ //_geo_distance代表根據距離排序
    //            "location": map[string]interface{}{ //根據location儲存的經緯度計算距離。
    //                "lat": 40.715,  //當前緯度
    //                "lon": -73.988, //當前經度
    //            },
    //            "order": "asc", // asc 表示升序,desc 表示降序
    //        }},
    //}
    //es.Search(index, query)
    //精確值查詢
    //query := map[string]interface{}{
    //    "query": map[string]interface{}{
    //        "match": map[string]interface{}{
    //            "age": "20",
    //        },
    //    },

    //}
    //es.Search(index, query)
    //範圍查詢
    //通過range實現範圍查詢,類似SQL語句中的>, >=, <, <=表示式。
    //gte範圍引數 - 等價於>=
    //lte範圍引數 - 等價於 <=
    //範圍引數可以只寫一個,例如:僅保留 "gte": 10, 則代表 FIELD欄位 >= 10
    //query := map[string]interface{}{
    //    "query": map[string]interface{}{
    //        "range": map[string]interface{}{
    //            "age": map[string]interface{}{
    //                "gte": "19",
    //                "lte": "20",
    //            },
    //        },
    //    },
    //}
    //es.Search(index, query)
    //組合查詢 如果需要編寫類似SQL的Where語句,組合多個欄位的查詢條件,可以使用bool語句。
    //"must": [], // must條件,類似SQL中的and, 代表必須匹配條件
    //"must_not": [], // must_not條件,跟must相反,必須不匹配條件
    //"should": [] // should條件,類似SQL中or, 代表匹配其中一個條件
    query := map[string]interface{}{
        "query": map[string]interface{}{
            "bool": map[string]interface{}{
                "must": []map[string]interface{}{
                    {
                        "match": map[string]interface{}{
                            "age": "19",
                        },
                    },
                    {
                        "match": map[string]interface{}{
                            "title": "中國",
                        },
                    },
                },
            },
        },
    }
    es.Search(index, query)

    //使用mysql的方式來請求
    //query := map[string]interface{}{
    //    "query": "select title from " + index + " where title like '%中國%'", //這裡使用mysql的方式來請求,非常簡單,符合開發習慣,簡化es入門門檻,支援order,支援Limit,那麼排序和分頁就自己寫好了
    //}
    //query := map[string]interface{}{
    //    "query": "select title from " + index + " where title = '中國'", //這裡使用mysql的方式來請求,非常簡單,符合開發習慣,簡化es入門門檻,支援order,支援Limit,那麼排序和分頁就自己寫好了
    //}
    //es.SearchEsapiSql(query)

    //測試分詞
    //query := map[string]interface{}{
    //    "analyzer": "ik_smart", //智慧分詞用:ik_smart,最大化分詞用:ik_max_word
    //    "text":     "中國華人民",
    //}
    //url := index + "_analyze?pretty=true"

    //query := map[string]interface{}{
    //    "query": map[string]interface{}{
    //        "match": map[string]interface{}{
    //            "title": "我愛你中國",
    //        },
    //    },
    //    "highlight": map[string]interface{}{
    //        "pre_tags":  []string{"<font color='red'>"},
    //        "post_tags": []string{"</font>"},
    //        "fields": map[string]interface{}{
    //            "title": map[string]interface{}{},
    //        },
    //    },
    //}
    //url := index + "/_search"

    //es.SearchHttp("GET", url, query)

}

參考資料

https://github.com/elastic/go...
https://www.tizi365.com/archi...
https://www.elastic.co/guide/...

links

  • 目錄
  • 上一節:
  • 下一節:

相關文章