go-ElasticSearch TypedClient學習筆記

ElasticSearch

Elasticsearch(ES)是一個基於Lucene構建的開源、分佈式、RESTful接口的全文搜索引擎。Elasticsearch還是一個分佈式文檔數據庫,其中每個字段均可被索引,而且每個字段的數據均可被搜索,ES能夠橫向擴展至數以百計的服務器存儲以及處理**PB**級的數據。可以在極短的時間內存儲、搜索和分析大量的數據。通常作爲具有複雜搜索場景情況下的核心發動機。根據DB-Engines的排名顯示,Elasticsearch`是最受歡迎的企業搜索引擎。

go-ealsticsearch

Elasticsearch 的官方 Go 客戶端go-elasticsearch是由 Elastic 開發、維護和支持的客戶端系列的最新成員之一。 初始版本於 2019 年初發布,並在過去幾年中逐漸成熟,獲得了重試請求、發現集羣節點和各種輔助組件等功能。

隨着官方客戶端的發佈和逐漸成熟,原來社區維護的客戶端olivere/elastic已經逐漸不在維護了。

Typed API

Typed API從簡單開始,到逐步擴展覆蓋更多領域,提升類型安全性和易用性。成爲該客戶端庫的一大特色。

Typed API早在2.19年的V7版本中就出現了,不過一直處於alpha狀態,直到8.7版本,才基本可用。我用的是最新的8.90版,看到TypedApi的介紹,就選擇入坑選擇了。沒想到,還真的坑啊,基本的增刪改還好,稍微複雜的用法只能去找examples和tests代碼,加上自己試驗,連文檔都沒有:(。所以在這裏記錄一下我用到的TypedAPI。

連接EL

 var err error
 esCfg:=es.Config{
   Addresses: []string{"http://192.168.0.134:9200"},
   Username:  "Username",
   Password:  "Password",
 }
 typedClient, err := es.NewTypedClient(esCfg)
 if err != nil {
   log.Fatal("創建TypedClient失敗",err)
 }
 
 //
 ctx:=context.TODO()
 ok,err:=typedClient.Ping().IsSuccess(ctx)
 if err != nil {
   log.Fatal("TypedClient ping失敗",err)
 }
 if !ok{
   log.Fatal("connect to EL server fail!")
 }else{
   log.Println("------- connected success")
 }
 log.Printf( "EL info: %#v",typedClient.Info)
 

EL中的實體類

 type ElKnowledge struct {
  ID          int       `json:"id"`
  KnowledgeID string    `json:"knowledge_id"`
  Title       string    `json:"title"`
  Author      string    `json:"author"`
  Category    string    `json:"category"`
  Keywords    string    `json:"keywords"`
  Content     string    `json:"content"`
  Images      string    `json:"images"`
  Files       string    `json:"files"`
  DAddAt      time.Time `json:"d_add_at"`
  AddAt       string    `json:"add_at"`
  Comments    string    `json:"comments"`
  Scores      string    `json:"scores"`
 }
 func (me *ElKnowledge) SID() string {
  return me.KnowledgeID
 }
 func (me *ElKnowledge) ToJsonRawMessage() json.RawMessage {
  bf, err := json.Marshal(me)
  if err != nil {
  log.Fatalln("[ElKnowledge.ToJson] fail", err)
  }
  return bf
 }
 func (me *ElKnowledge) ToJson() string {
  return string(me.ToJsonRawMessage())
 }
 

 

創建索引

 indexName:="myIndex"
 var ElKnowledgeTypedMapping *types.TypeMapping = &types.TypeMapping{
  Properties: map[string]types.Property{
  "id":           types.NewIntegerNumberProperty(),
  "knowledge_id": types.NewKeywordProperty(),
  "title":        types.NewTextProperty(),
  "category":     types.NewTextProperty(),
  "author":       types.NewTextProperty(),
  "keywords":     types.NewTextProperty(),
  "content":      types.NewTextProperty(),
  "add_at":       types.NewKeywordProperty(),
  "images":       types.NewTextProperty(),
  "files":        types.NewTextProperty(),
  "d_add_at":     types.NewDateProperty(),
  "comments":     types.NewTextProperty(),
  "scores":       types.NewTextProperty(),
  },
 }
 //檢查索引是否存在
 exists,err := typedClient.Indices.Exists(indexName).IsSuccess(ctx)
 if err != nil {
   log.Fatalln ("check index exist failed", err.Error())
 }
 
 //索引不存在則創建索引
 //索引不存在時查詢會報錯,但索引不存在的時候可以直接插入
 if !exists {
   log.Printf("index %s is not exist, to create", indexName)
   cr, err :=typedClient.Indices.Create(indexName).Request(&create.Request{
     Mappings: ElKnowledgeTypedMapping,
  }).Do(ctx)
   if err != nil {
     log.Fatal("create index failed", err.Error())
  }
   log.Println("index creat",cr.Index)
 }

新增

 func  insertKnowledge(doc *ElKnowledge){
  sid:=doc.SID()
  rr,err:=typedClient.Create(indexName,sid).Request(&doc).Do(context.TODO())
  if err!=nil{
  log.Fatal(" Insert new doc fail,",err)
  }
  log.Println(" Insert new doc, result=>",rr.Result.String())
 }
 

按ID查詢

 func  GetKnowledge(sid string)(doc *ElKnowledge,ok bool){
  rr,err:=typedClient.Get(indexName,sid).Do(context.TODO())
  if err!=nil{
  log.Println("[GetKnowledge] fail",err)
  return
  }
  if !rr.Found {return }
  doc,err= ElKnowledgeFromJsonRaw(rr.Source_)
  if err!=nil{
  return
  }
  return doc, true
 }
 

修改

 func  upsertKnowledge(doc *ElKnowledge){  
  useUpsert:=true
  sid:=doc.SID()
  js:=doc.ToJson()
  rr,err:=typedClient.Update(indexName,sid).Request(&update.Request{
  Doc: json.RawMessage(js),
  DocAsUpsert: &useUpsert,
  }).Do(context.TODO())
  if err!=nil{
  log.Println("upsert doc fail,",err)
  panic(err)
  }
  log.Println("upserted success, by way=>",rr.Result.String())
 }

刪除

 func deleteKnowledge(doc *ElKnowledge){
  sid:=doc.SID()
  rr,err:=typedClient.Delete(indexName,sid).Do(context.TODO())
  if err!=nil{
  log.Fatal("Delete doc fail",err)
  }
  log.Println("Deleted, ",rr.Result.String())
 }

 

查詢

 func Search(c *gin.Context) {
  words:=c.Query("words")
  sfrom:=c.Query("from")
  ssize:=c.Query("size")
  from,_:=strconv.Atoi(sfrom)
  size,_:=strconv.Atoi(ssize)
  res,err:=typedClient.Search().Index("yhkb").Request(&search.Request{
  Query: &types.Query{
  Match: map[string]types.MatchQuery{
  "all_content": { Query: words, Operator: &operator.And},
  },
  },
  Sort: []types.SortCombinations{
  types.SortOptions{
  SortOptions: map[string]types.FieldSort{
  "add_at":{Order: &sortorder.Desc,},
  },
  },
  },
  From: &from,
  Size: &size,
  }).Do(context.Background())
 
  if err != nil {
  msg:=""
  if err,ok:=err.(types.ElasticsearchError);ok{
  b,_:=json.Marshal(err)
  msg=string(b)
  }
  err=utils.WrapErrorWith(err,"查詢失敗"+msg)
  slog.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章