123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389 |
- package es
- import (
- "bytes"
- "context"
- "encoding/json"
- "eta_mini_ht_api/common/component/config"
- logger "eta_mini_ht_api/common/component/log"
- "eta_mini_ht_api/common/contants"
- "github.com/elastic/go-elasticsearch/v7"
- "github.com/elastic/go-elasticsearch/v7/esapi"
- "io"
- "strings"
- "sync"
- )
- type ESBase interface {
- GetId() string
- }
- var (
- esOnce sync.Once
- esClient *ESClient
- )
- type ESClient struct {
- esOp *elasticsearch.Client
- }
- type SearchType string
- const (
- MatchAll = "match_all"
- Match = "match"
- Range = "range"
- )
- func GetInstance() *ESClient {
- esOnce.Do(func() {
- // 检查是否成功获取到RedisConfig实例,没有配置则不进行redis初始化
- if esConf, ok := config.GetConfig(contants.ES).(*config.ESConfig); ok {
- logger.Info("初始化es")
- // 这里可以添加初始化Redis的逻辑
- esClient = newEs(esConf)
- }
- })
- return esClient
- }
- func (es *ESClient) es() *elasticsearch.Client {
- return es.esOp
- }
- func newEs(config *config.ESConfig) *ESClient {
- elasticsearch.NewDefaultClient()
- client, err := elasticsearch.NewClient(
- elasticsearch.Config{
- Addresses: []string{config.GetUrl()},
- // A list of Elasticsearch nodes to use.
- Username: config.GetUserName(),
- Password: config.GetPassword(), // Password for HTTP Basic Authentication.
- },
- )
- if err != nil {
- logger.Error("连接ES失败:%v", err)
- panic("启动es失败")
- }
- return &ESClient{esOp: client}
- }
- func init() {
- if GetInstance() == nil {
- panic("初始化es失败")
- }
- logger.Info("es初始化成功")
- }
- // BulkInsert 批量创建文档
- func (es *ESClient) BulkInsert(indexName string, docs []ESBase) (err error) {
- // 创建批量请求
- bulkBody := new(bytes.Buffer)
- for _, doc := range docs {
- enc := json.NewEncoder(bulkBody)
- if err = enc.Encode(map[string]interface{}{
- "index": map[string]interface{}{
- "_index": indexName,
- "_id": doc.GetId(),
- },
- }); err != nil {
- logger.Error("生成es批处理请求参数失败: %s", err)
- }
- if err = enc.Encode(doc); err != nil {
- logger.Error("生成es批处理文档失败: %s", err)
- }
- }
- bulkReq := esapi.BulkRequest{
- Body: bytes.NewReader(bulkBody.Bytes()),
- Refresh: "true",
- }
- res, err := bulkReq.Do(context.Background(), es.esOp)
- if err != nil {
- logger.Error("es批处理创建失败: %s", err)
- }
- defer res.Body.Close()
- if res.IsError() {
- var e map[string]interface{}
- if err = json.NewDecoder(res.Body).Decode(&e); err != nil {
- logger.Error("解析es应答失败: %v", err)
- } else {
- // Print the response status and error information.
- logger.Error("es请求失败: %s: %v\n", res.Status(), err)
- }
- }
- return
- }
- type ESResponse struct {
- Took int `json:"took"`
- TimedOut bool `json:"timed_out"`
- Hits Hits `json:"hits"`
- _Shards ShardsInfo `json:"_shards"`
- }
- type Hits struct {
- Total TotalHits `json:"total"`
- MaxScore float64 `json:"max_score"`
- Hits []Hit `json:"hits"`
- }
- type TotalHits struct {
- Value int `json:"value"`
- Relation string `json:"relation"`
- }
- type Hit struct {
- Index string `json:"_index"`
- Type string `json:"_type"`
- ID string `json:"_id"`
- Score float64 `json:"_score"`
- Source json.RawMessage `json:"_source"`
- Highlight json.RawMessage `json:"highlight"`
- }
- type ShardsInfo struct {
- Total int `json:"total"`
- Successful int `json:"successful"`
- Skipped int `json:"skipped"`
- Failed int `json:"failed"`
- }
- type ESQueryRequest struct {
- IndexName string
- From int
- Size int
- Key string
- Column string
- Sorts []string
- Type SearchType
- RangeColumn string
- Max interface{}
- Min interface{}
- }
- func (req *ESQueryRequest) CreateESQueryRequest(index string, column string, key string, from int, size int, sorts []string, searchType SearchType) *ESQueryRequest {
- return &ESQueryRequest{
- IndexName: index,
- Type: searchType,
- From: from,
- Size: size,
- Key: key,
- Column: column,
- Sorts: sorts,
- }
- }
- func (req *ESQueryRequest) Range(from int64, to int64, column string) *ESQueryRequest {
- req.RangeColumn = column
- req.Max = to
- req.Min = from
- return req
- }
- func (req *ESQueryRequest) parseJsonQuery() (queryMap map[string]interface{}) {
- switch req.Type {
- case MatchAll:
- queryMap = map[string]interface{}{
- "query": map[string]interface{}{
- "match_all": map[string]interface{}{},
- },
- }
- return
- case Match:
- queryMap = map[string]interface{}{
- "query": map[string]interface{}{
- "match": map[string]interface{}{
- req.Column: req.Key,
- },
- },
- "highlight": map[string]interface{}{
- "fields": map[string]interface{}{
- req.Column: map[string]interface{}{},
- },
- "pre_tags": []string{"<span style='color:red'>"},
- "post_tags": []string{"</span>"},
- },
- }
- return
- case Range:
- queryMap = map[string]interface{}{
- "query": map[string]interface{}{
- "match": map[string]interface{}{
- req.Column: req.Key,
- },
- },
- "highlight": map[string]interface{}{
- "fields": map[string]interface{}{
- req.Column: map[string]interface{}{},
- },
- "pre_tags": []string{"<span style='color:red'>"},
- "post_tags": []string{"</span>"},
- },
- "post_filter": map[string]interface{}{
- "range": map[string]interface{}{
- req.RangeColumn: map[string]interface{}{
- "gte": req.Min,
- "lte": req.Max,
- },
- },
- },
- }
- return
- default:
- queryMap = map[string]interface{}{}
- return
- }
- }
- // /*
- // *
- //
- // 搜索
- //
- // indexName 访问索引名
- // query 搜索条件
- // from 开始搜索位置
- // size 搜索条数
- // sort 排序
- // */
- func (es *ESClient) Search(params *ESQueryRequest) (response ESResponse, err error) {
- queryMap := params.parseJsonQuery()
- jsonQuery, _ := json.Marshal(queryMap)
- request := esapi.SearchRequest{
- Index: []string{params.IndexName},
- Body: strings.NewReader(string(jsonQuery)),
- From: ¶ms.From,
- Size: ¶ms.Size,
- Sort: params.Sorts,
- }
- res, err := request.Do(context.Background(), esClient.esOp)
- defer res.Body.Close()
- if err != nil {
- logger.Error("es查询失败: %s", err)
- }
- if res.IsError() {
- var e map[string]interface{}
- if err = json.NewDecoder(res.Body).Decode(&e); err != nil {
- logger.Error("解析es应答失败: %v", err)
- } else {
- // Print the response status and error information.
- logger.Error("es请求失败: %s: %v\n", res.Status(), err)
- }
- }
- body, err := io.ReadAll(res.Body)
- if err != nil {
- logger.Error("获取es应答失败: %v", err)
- }
- return parseESResponse(body)
- }
- func parseESResponse(body []byte) (ESResponse, error) {
- var response ESResponse
- if err := json.Unmarshal(body, &response); err != nil {
- return ESResponse{}, err
- }
- for _, hit := range response.Hits.Hits {
- var source map[string]interface{}
- if err := json.Unmarshal(hit.Source, &source); err != nil {
- return ESResponse{}, err
- }
- }
- return response, nil
- }
- func (es *ESClient) GetSource(hits Hits) []Hit {
- return hits.Hits
- }
- //
- ///*
- //*
- //添加es
- //indexName 索引名
- //id es的id
- //body es的值
- //*/
- //func EsAdd(indexName string, id string, body map[string]interface{}) bool {
- // req := httplib.Post(esUrl + indexName + "/_doc/" + id)
- // req.JSONBody(body)
- // _, err := req.String()
- // if err != nil {
- // fmt.Println("elasticsearch is error ", err)
- // return false
- // }
- // return true
- //}
- //
- ///*
- //*
- //修改es
- //indexName 索引名
- //id es的id
- //body es的值
- //*/
- //func EsUpdate(indexName string, id string, body map[string]interface{}) bool {
- // bodyData := map[string]interface{}{
- // "doc": body,
- // }
- // req := httplib.Post(esUrl + indexName + "/_doc/" + id + "/_update")
- // req.JSONBody(bodyData)
- // _, err := req.String()
- // if err != nil {
- // fmt.Println("elasticsearch is error ", err)
- // return false
- // }
- // return true
- //}
- //
- ///*
- //*
- //删除
- //indexName 索引名
- //id es的id
- //*/
- //func EsDelete(indexName string, id string) bool {
- // req := httplib.Delete(esUrl + indexName + "/_doc/" + id)
- // _, err := req.String()
- // if err != nil {
- // fmt.Println("elasticsearch is error ", err)
- // return false
- // }
- // return true
- //
- //}
- //
- //func CreateIndex(indexName string) error {
- // resp, err := esClient.es().Indices.
- // Create(indexName).
- // Do(context.Background())
- // if err != nil {
- // logger.Error("创建ES索引失败:%v", err)
- // return err
- // }
- // fmt.Printf("index:%#v\n", resp.Index)
- // return nil
- //}
- // DeleteIndex 删除索引
- //func DeleteIndex(indexName string) error {
- // _, err := esClient.es().Indices. // 表明是对索引的操作,而Index则表示是要操作具体索引下的文档
- // Delete(indexName).
- // Do(context.Background())
- // if err != nil {
- // fmt.Printf("delete index failed,err:%v\n", err)
- // return err
- // }
- // fmt.Printf("delete index successed,indexName:%s", indexName)
- // return nil
- //}
- //
- //// CreateDocument 创建文档
- //func CreateDocument(indexName string, id string, doc interface{}) {
- // // 添加文档
- // resp, err := esClient.esOp.Index(indexName).Id(id).Document(doc).Do(context.Background())
- // if err != nil {
- // logger.Error("indexing document failed, err:%v\n", err)
- // return
- // }
- // logger.Info("result:%#v\n", resp.Result)
- // return
- //}
|