go-ElasticSearch TypedClient学习笔记
ElasticSearch
Elasticsearch(ES)是一个基于
Lucene构建的开源、分布式、
RESTful接口的全文搜索引擎。
Elasticsearch还是一个分布式文档数据库,其中每个字段均可被索引,而且每个字段的数据均可被搜索,
ES能够横向扩展至数以百计的服务器存储以及处理**PB**级的数据。可以在极短的时间内存储、搜索和分析大量的数据。通常作为具有复杂搜索场景情况下的核心发动机。根据
DB-Engines的排名显示,
Elasticsearch`是最受欢迎的企业搜索引擎。
go-ealsticsearch
随着官方客户端的发布和逐渐成熟,原来社区维护的客户端
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.