Files
2025-03-03 00:59:52 +08:00

202 lines
4.6 KiB
Go

package zincx
import (
"encoding/json"
"fmt"
"github.com/go-resty/resty/v2"
"net/http"
)
type ZincClient struct {
Client *resty.Client
BaseURL string
Username string
Password string
}
func NewZincClient(BaseURL, Username, Password string) *ZincClient {
Client := resty.New().
SetDebug(false).
SetDisableWarn(true)
return &ZincClient{
Client: Client,
BaseURL: BaseURL,
Username: Username,
Password: Password,
}
}
// 检查索引是否存在 (内部方法)
func (zc *ZincClient) IndexExists(indexName string) (bool, error) {
resp, err := zc.Client.R().
SetBasicAuth(zc.Username, zc.Password).
Head(zc.BaseURL + "/api/index/" + indexName)
if err != nil {
return false, err
}
return resp.StatusCode() == http.StatusOK, nil
}
type IndexMapping struct {
Mappings struct {
Properties map[string]interface{} `json:"properties"`
} `json:"mappings"`
}
func (zc *ZincClient) CreateIndex(indexName string, mapping *IndexMapping) error {
url := fmt.Sprintf("%s/api/index/%s", zc.BaseURL, indexName)
resp, err := zc.Client.R().
SetBasicAuth(zc.Username, zc.Password).
SetHeader("Content-Type", "application/json").
SetBody(mapping).
Put(url)
if err != nil {
return err
}
if resp.StatusCode() != 200 {
return fmt.Errorf("创建索引失败: %s", resp.String())
}
return nil
}
func (zc *ZincClient) IndexDocument(indexName, documentID string, doc interface{}) error {
url := fmt.Sprintf("%s/api/%s/_doc/%s", zc.BaseURL, indexName, documentID)
resp, err := zc.Client.R().
SetBasicAuth(zc.Username, zc.Password).
SetHeader("Content-Type", "application/json").
SetBody(doc).
Put(url)
if err != nil {
return err
}
if resp.StatusCode() != 200 {
return fmt.Errorf("插入文档失败: %s", resp.String())
}
return nil
}
type SearchRequest struct {
Query struct {
Match map[string]interface{} `json:"match"`
} `json:"query"`
}
// 泛型响应结构
type ZincSearchResponse[T any] struct {
Hits struct {
Total struct {
Value int `json:"value"`
} `json:"total"`
Hits []struct {
ID string `json:"_id"`
Source T `json:"_source"`
Score float64 `json:"_score"`
} `json:"hits"`
} `json:"hits"`
}
// 修改 Search 方法签名
func (zc *ZincClient) Search(indexName string, query interface{}, resultType interface{}) (*ZincSearchResponse[interface{}], error) {
url := fmt.Sprintf("%s/api/%s/_search", zc.BaseURL, indexName)
resp, err := zc.Client.R().
SetBasicAuth(zc.Username, zc.Password).
SetHeader("Content-Type", "application/json").
SetBody(query).
SetResult(&ZincSearchResponse[interface{}]{}).
Post(url)
if err != nil {
return nil, err
}
if resp.StatusCode() != 200 {
return nil, fmt.Errorf("搜索失败: %s", resp.String())
}
// 手动反序列化以支持动态类型
var rawResponse ZincSearchResponse[interface{}]
if err := json.Unmarshal(resp.Body(), &rawResponse); err != nil {
return nil, err
}
// 将 Source 转换为目标类型
for i := range rawResponse.Hits.Hits {
data, _ := json.Marshal(rawResponse.Hits.Hits[i].Source)
_ = json.Unmarshal(data, &resultType)
rawResponse.Hits.Hits[i].Source = resultType
}
return &rawResponse, nil
}
type BulkRequest struct {
Index string `json:"index"`
ID string `json:"id"`
Source interface{} `json:"source"`
}
func (zc *ZincClient) BulkIndex(indexName string, docs []BulkRequest) error {
url := fmt.Sprintf("%s/api/_bulk", zc.BaseURL)
body := ""
for _, doc := range docs {
action := fmt.Sprintf(`{ "index": { "_index": "%s", "_id": "%s" } }`, indexName, doc.ID)
source, _ := json.Marshal(doc.Source)
body += action + "\n" + string(source) + "\n"
}
resp, err := zc.Client.R().
SetBasicAuth(zc.Username, zc.Password).
SetHeader("Content-Type", "application/json").
SetBody(body).
Post(url)
if err != nil {
return err
}
if resp.StatusCode() != 200 {
return fmt.Errorf("批量操作失败: %s", resp.String())
}
return nil
}
// 删除文档
func (zc *ZincClient) DeleteDocument(indexName, documentID string) error {
url := fmt.Sprintf("%s/api/%s/_doc/%s", zc.BaseURL, indexName, documentID)
resp, err := zc.Client.R().
SetBasicAuth(zc.Username, zc.Password).
Delete(url)
if err != nil {
return err
}
if resp.StatusCode() != 200 {
return fmt.Errorf("删除文档失败: %s", resp.String())
}
return nil
}
// 删除索引
func (zc *ZincClient) DeleteIndex(indexName string) error {
url := fmt.Sprintf("%s/api/index/%s", zc.BaseURL, indexName)
resp, err := zc.Client.R().
SetBasicAuth(zc.Username, zc.Password).
Delete(url)
if err != nil {
return err
}
if resp.StatusCode() != 200 {
return fmt.Errorf("删除索引失败: %s", resp.String())
}
return nil
}