Skip to content

Commit

Permalink
feat: add es client
Browse files Browse the repository at this point in the history
  • Loading branch information
qloog committed Jun 26, 2023
1 parent 437d3bc commit 4194986
Show file tree
Hide file tree
Showing 9 changed files with 548 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## Changelog

## v1.7.1
- feat(es): add elasticsearch client(v7)
- chore(cli): approve gen task command
- chore(response): remove init resp and improve Error

Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ require (
github.com/eapache/go-resiliency v1.1.0 // indirect
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 // indirect
github.com/eapache/queue v1.1.0 // indirect
github.com/elastic/go-elasticsearch/v7 v7.17.10
github.com/foolin/gin-template v0.0.0-20190415034731-41efedfb393b
github.com/frankban/quicktest v1.7.2 // indirect
github.com/fsnotify/fsnotify v1.5.1
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 h1:YEetp8
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/elastic/go-elasticsearch/v7 v7.17.10 h1:TCQ8i4PmIJuBunvBS6bwT2ybzVFxxUhhltAs3Gyu1yo=
github.com/elastic/go-elasticsearch/v7 v7.17.10/go.mod h1:OJ4wdbtDNk5g503kvlHLyErCgQwwzmDtaFC4XyOxXA4=
github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
Expand Down
10 changes: 9 additions & 1 deletion pkg/storage/elasticsearch/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,18 @@ Elasticsearch 是当前比较流行的 搜索框架,这里提供两个库,
- 官方 [https://github.com/elastic/go-elasticsearch](https://github.com/elastic/go-elasticsearch) star: 2700+
- 第三方[https://github.com/olivere/elastic](https://github.com/olivere/elastic) star: 5300+

> 第三方的这个已经不在维护,所以推荐使用官方的
## Compatibility

The client major versions correspond to the compatible Elasticsearch major versions: to connect to Elasticsearch 7.x,
use a 7.x version of the client, to connect to Elasticsearch 6.x, use a 6.x version of the client.

## Reference

- https://medium.com/a-journey-with-go/go-elasticsearch-clients-study-case-dbaee1e02c7
- https://mp.weixin.qq.com/s?__biz=MzkyNzI1NzM5NQ==&mid=2247484756&idx=1&sn=6029ed72391e175ebef3de47bf9290a2&chksm=c22b8308f55c0a1eb0d06f4f5f7404e0ba33f6bb10a86f996dfbbd7b80b952e5bef97ce2344f&cur_album_id=1932372564102709257&scene=189#wechat_redirect
- https://discuss.elastic.co/t/go-elasticsearch-versus-olivere-golang-client/252248
- https://github.com/olivere/elastic/issues/1240
- https://github.com/olivere/elastic/issues/1240
- https://www.elastic.co/guide/en/elasticsearch/reference/7.17/docker.html
- https://studygolang.com/articles/28869
62 changes: 62 additions & 0 deletions pkg/storage/elasticsearch/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package elasticsearch

import (
"crypto/tls"
"encoding/json"
"errors"
"fmt"
"log"
"net"
"net/http"
"time"

es "github.com/elastic/go-elasticsearch/v7"
"github.com/elastic/go-elasticsearch/v7/esapi"
)

var (
ErrEsNotFound = errors.New("es: not found")
)

type EsClient struct {
client *es.Client
}

func NewESClient(hosts []string, username, password string) (client *EsClient, err error) {
c, err := es.NewClient(es.Config{
Addresses: hosts,
Username: username,
Password: password,
Transport: &http.Transport{
MaxIdleConnsPerHost: http.DefaultMaxIdleConnsPerHost,
ResponseHeaderTimeout: 5 * time.Second,
DialContext: (&net.Dialer{Timeout: 5 * time.Second}).DialContext,
TLSClientConfig: &tls.Config{
MinVersion: tls.VersionTLS11,
},
},
})
if err != nil {
log.Fatal(err)
}

return &EsClient{client: c}, nil
}

func (es *EsClient) handleResponse(resp *esapi.Response) (map[string]interface{}, error) {
var (
r map[string]interface{}
)
if resp.StatusCode == 404 {
return r, ErrEsNotFound
}
// Check response status
if resp.IsError() {
return nil, errors.New(resp.String())
}
// Deserialize the response into a map.
if err := json.NewDecoder(resp.Body).Decode(&r); err != nil {
return nil, errors.New(fmt.Sprintf("Error parsing the response body: %s", err))
}
return r, nil
}
191 changes: 191 additions & 0 deletions pkg/storage/elasticsearch/client_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
package elasticsearch

import (
"context"
"log"
"testing"

"github.com/stretchr/testify/assert"
)

var (
esClient *EsClient
ctx context.Context
)

const (
indexName = "test-index"
)

func init() {
var err error
esClient, err = NewESClient([]string{"http://127.0.0.1:9200"}, "", "")
if err != nil {
log.Fatal(err)
}
ctx = context.Background()
}

func TestNewESClient(t *testing.T) {
t.Log(esClient.client.Info())
}

func TestNewESClientWithContext(t *testing.T) {
t.Log(esClient.client.Info(esClient.client.Info.WithContext(context.Background())))
}

func TestCreateIndex(t *testing.T) {
a := assert.New(t)
bodyStr := `{
"mappings" : {
"properties" : {
"id" : {
"index": true,
"type" : "keyword"
},
"age" : {
"index": true,
"type" : "keyword"
},
"nickname" : {
"index": true,
"type" : "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"bio" : {
"index": true,
"type" : "keyword"
}
}
}
}`
resp, err := esClient.CreateIndex(ctx, indexName, bodyStr)
a.Nil(err)
t.Log(resp)

response, err := esClient.client.Indices.Get([]string{indexName})
a.Nil(err)
t.Log(response)
}

func TestGetIndex(t *testing.T) {
a := assert.New(t)
response, err := esClient.GetIndex(ctx, indexName)
a.Nil(err)
t.Log(response)
}

func TestDeleteIndex(t *testing.T) {
a := assert.New(t)
err := esClient.DeleteIndex(ctx, indexName)
a.Nil(err)
}

func TestCreateDocument(t *testing.T) {
a := assert.New(t)
doc := map[string]interface{}{
"id": "1",
"nickname": "Tom",
"age": "18",
"bio": "I am a singer",
}
response, err := esClient.CreateDocument(ctx, indexName, "1", doc)
a.Nil(err)
t.Log(response)
}

func TestGetDocument(t *testing.T) {
a := assert.New(t)
response, err := esClient.GetDocument(ctx, indexName, "1")
a.Nil(err)
t.Log(response)
}

func TestUpdateDocument(t *testing.T) {
a := assert.New(t)
data := map[string]interface{}{
"bio": "I am a teacher",
}
response, err := esClient.UpdateDocument(ctx, indexName, "1", data)
a.Nil(err)
t.Log(response)
}

func TestUpdateDocumentByQuery(t *testing.T) {
a := assert.New(t)
query := map[string]interface{}{
"nickname": "Tom",
}
data := map[string]interface{}{
"bio": "I am a music teacher",
}
response, err := esClient.UpdateDocumentByQuery(ctx, indexName, query, data)
a.Nil(err)
t.Log(response)
}

func TestDeleteDocument(t *testing.T) {
a := assert.New(t)
err := esClient.DeleteDocument(ctx, indexName, "1")
a.Nil(err)
}

// 单个字段的搜索
func TestSearch(t *testing.T) {
a := assert.New(t)
query := map[string]interface{}{
"bool": map[string]interface{}{
"must": []map[string]interface{}{
{
"match": map[string]interface{}{
"nickname": "Tom",
},
},
},
},
}
sort := map[string]interface{}{
"_score": map[string]interface{}{
"order": "desc",
},
}
response, total, err := esClient.Search(ctx, indexName, query, sort, 0, 10)
a.Nil(err)
t.Log(total)
t.Log(response)
}

// 多字段搜索
func TestSearchByMultiField(t *testing.T) {
a := assert.New(t)
query := map[string]interface{}{
"bool": map[string]interface{}{
"must": []map[string]interface{}{
{
"match": map[string]interface{}{
"nickname": "Tom",
},
},
{
"match": map[string]interface{}{
"age": "18",
},
},
},
},
}
sort := map[string]interface{}{
"_score": map[string]interface{}{
"order": "desc",
},
}
response, total, err := esClient.Search(ctx, indexName, query, sort, 0, 10)
a.Nil(err)
t.Log(total)
t.Log(response)
}
Loading

0 comments on commit 4194986

Please sign in to comment.