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.Error("查询失败","error",err)
  helper.ResponseJsonError(c, err)
  return
  }
  helper.ResponseJsonData(c,res)
 
 }
 
posted @ 2023-08-04 10:02  柒零壹  阅读(745)  评论(0编辑  收藏  举报