import (
"context"
"encoding/json"
"fmt"
"github.com/elastic/go-elasticsearch/v8"
"github.com/elastic/go-elasticsearch/v8/esapi"
"github.com/elastic/go-elasticsearch/v8/esutil"
"log"
"strings"
)
type ClientManager struct {
client *elasticsearch.Client
once sync.Once
}
func (cm *ClientManager) GetClient() *elasticsearch.Client {
cm.once.Do(func() {
cfg := elasticsearch.Config{
Addresses: []string{"http://localhost:9200"},
}
es, err := elasticsearch.NewClient(cfg)
if err != nil {
log.Fatalf("Error creating the client: %s", err)
}
cm.client = es
})
return cm.client
}
var defaultManager = &ClientManager{}
func GetDefaultClient() *elasticsearch.Client {
return defaultManager.GetClient()
}
// 创建索引
func CreateIndex(ctx context.Context, es *elasticsearch.Client, indexName string) error {
body := map[string]interface{}{
"mappings": map[string]interface{}{
"properties": map[string]interface{}{
"name": map[string]interface{}{"type": "text"},
},
},
}
jsonBody, err := json.MarshalIndent(body, "", " ")
if err != nil {
return fmt.Errorf("error marshaling index mapping: %w", err)
}
res, err := es.Indices.Create(
indexName,
es.Indices.Create.WithContext(ctx),
es.Indices.Create.WithBody(jsonBody),
)
if err != nil {
return fmt.Errorf("error creating the index: %w", err)
}
defer res.Body.Close()
return nil
}
// 删除索引
func DeleteIndex(ctx context.Context, es *elasticsearch.Client, indexName string) error {
res, err := es.Indices.Delete(
[]string{indexName},
es.Indices.Delete.WithContext(ctx),
)
if err != nil {
return fmt.Errorf("error deleting the index: %w", err)
}
defer res.Body.Close()
return nil
}
// 插入数据
func InsertData(ctx context.Context, es *elasticsearch.Client, indexName string, users []User) error {
var buf strings.Builder
for _, user := range users {
meta := []byte(fmt.Sprintf(`{"index":{"_id":"%d"}}%s`, user.ID, "\n"))
data, err := json.Marshal(user)
if err != nil {
return fmt.Errorf("error encoding the user: %w", err)
}
buf.Grow(len(meta) + len(data))
buf.Write(meta)
buf.Write(data)
buf.WriteByte('\n')
}
res, err := esutil.BulkIndex(
ctx,
esutil.BulkIndex.WithClient(es),
esutil.BulkIndex.WithIndex(indexName),
esutil.BulkIndex.WithBody(strings.NewReader(buf.String())),
)
if err != nil {
return fmt.Errorf("error indexing the documents: %w", err)
}
defer res.Body.Close()
return nil
}
// 数据的结构体
type SearchResult struct {
ID int `json:"id"`
Name string `json:"name"`
}
// 查询数据
func SearchData(ctx context.Context, es *elasticsearch.Client, indexName string, query string) ([]SearchResult, error) {
res, err := es.Search(
es.Search.WithContext(ctx),
es.Search.WithIndex(indexName),
es.Search.WithBody(strings.NewReader(query)),
es.Search.WithTrackTotalHits(true),
)
if err != nil {
return nil, fmt.Errorf("error getting response: %w", err)
}
defer res.Body.Close()
var r struct {
Hits struct {
Hits []struct {
ID string `json:"_id"`
Source json.RawMessage `json:"_source"`
} `json:"hits"`
} `json:"hits"`
}
if err := json.NewDecoder(res.Body).Decode(&r); err != nil {
return nil, fmt.Errorf("error parsing the response body: %w", err)
}
results := make([]SearchResult, len(r.Hits.Hits))
for i, hit := range r.Hits.Hits {
if err := json.Unmarshal(hit.Source, &results[i]); err != nil {
return nil, fmt.Errorf("error unmarshaling search result %d: %w", i, err)
}
}
return results, nil
}
// 修改数据
func UpdateData(ctx context.Context, es *elasticsearch.Client, indexName string, updateData []UpdateResult) error {
var buf strings.Builder
for _, update := range updateData {
meta := []byte(fmt.Sprintf(`{"update":{"_id":"%s"}}%s`, update.ID, "\n"))
data, err := json.Marshal(map[string]map[string]string{"doc": {"name": update.Name}})
if err != nil {
return fmt.Errorf("error encoding the update data: %w", err)
}
buf.Grow(len(meta) + len(data))
buf.Write(meta)
buf.Write(data)
buf.WriteByte('\n')
}
res, err := esutil.Bulk(
ctx,
es.Bulk.WithIndex(indexName),
es.Bulk.WithBody(strings.NewReader(buf.String())),
es.Bulk.WithRefresh("true"),
)
if err != nil {
return fmt.Errorf("error updating the data: %w", err)
}
defer res.Body.Close()
return nil
}
// 删除数据
func DeleteData(ctx context.Context, es *elasticsearch.Client, indexName string, documentID string) error {
meta := []byte(fmt.Sprintf(`{"delete":{"_id":"%s"}}%s`, documentID, "\n"))
res, err := esutil.Bulk(
ctx,
esutil.Bulk.WithClient(es),
esutil.Bulk.WithIndex(indexName),
esutil.Bulk.WithBody(strings.NewReader(string(meta))),
)
if err!= nil {
return fmt.Errorf("error deleting the document: %w", err)
}
defer res.Body.Close()
return nil
}
fun main(){
es := GetDefaultClient()
}