package es import ( "crypto/tls" "encoding/json" "fmt" "github.com/elastic/go-elasticsearch/v8" "net/http" "strconv" "strings" "time" ) // BookPicObj 用于 book_pic type BookPicObj struct { LocalPath string `json:"localPath"` PddPath string `json:"pddPath"` } // BookPicSObj 用于 book_pic_s type BookPicSObj struct { LocalPath string `json:"localPath"` PddResponse string `json:"pddResponse"` } // BookDefPicObj 用于 book_def_pic type BookDefPicObj struct { LocalPath string `json:"localPath"` PddPath string `json:"pddPath"` } type CatIdObject struct { PinDuoDuoCatId string `json:"pin_duo_duo_cat_id"` // 拼多多分类 ID KongFuZiCatId string `json:"kong_fu_zi_cat_id"` // 孔夫子分类 ID XianYuCatId string `json:"xian_yu_cat_id"` // 闲鱼分类 ID } // FlexibleString 处理可能是字符串或数组的字段 type FlexibleString struct { Value string } // MarshalJSON 实现自定义 JSON 序列化 func (f FlexibleString) MarshalJSON() ([]byte, error) { return json.Marshal(f.Value) } // UnmarshalJSON 实现自定义 JSON 反序列化 func (f *FlexibleString) UnmarshalJSON(data []byte) error { var value string if err := json.Unmarshal(data, &value); err != nil { return err } f.Value = value return nil } type NumberOrString string func (n *NumberOrString) UnmarshalJSON(data []byte) error { s := strings.TrimSpace(string(data)) // 如果是数字(不以引号开头) if len(s) > 0 && s[0] != '"' { *n = NumberOrString(s) return nil } // 普通字符串 var str string if err := json.Unmarshal(data, &str); err != nil { return err } *n = NumberOrString(str) return nil } type Float64OrString float64 func (f *Float64OrString) UnmarshalJSON(b []byte) error { // 去掉空值 if string(b) == "null" || len(b) == 0 { *f = 0 return nil } // 尝试解析为 float var num float64 if err := json.Unmarshal(b, &num); err == nil { *f = Float64OrString(num) return nil } // 尝试解析为 string var str string if err := json.Unmarshal(b, &str); err == nil { if str == "" { *f = 0 return nil } parsed, err := strconv.ParseFloat(str, 64) if err != nil { return err } *f = Float64OrString(parsed) return nil } return fmt.Errorf("无法解析 fix_price: %s", string(b)) } // ESClient 封装 Elasticsearch 客户端 type ESClient struct { Client *elasticsearch.Client } var DefaultClient *ESClient // Init 初始化默认 ES 客户端 func Init(addresses []string, username, password string) error { client, err := NewESClient(addresses, username, password) if err != nil { return err } DefaultClient = client return nil } // NewESClient 初始化客户端 func NewESClient(addresses []string, username, password string) (*ESClient, error) { cfg := elasticsearch.Config{ Addresses: addresses, Username: username, Password: password, Transport: &http.Transport{ TLSClientConfig: &tls.Config{ InsecureSkipVerify: true, }, MaxIdleConnsPerHost: 100, ResponseHeaderTimeout: 60 * time.Second, }, CompressRequestBody: true, } client, err := elasticsearch.NewClient(cfg) if err != nil { return nil, fmt.Errorf("创建 ES 客户端失败: %v", err) } res, err := client.Info() if err != nil { return nil, fmt.Errorf("ES 连接失败: %v", err) } defer res.Body.Close() if res.IsError() { return nil, fmt.Errorf("ES 返回错误: %s", res.String()) } fmt.Println("✅ Elasticsearch 连接成功") return &ESClient{Client: client}, nil }