字段兼容

This commit is contained in:
unknown 2026-03-28 19:15:27 +08:00
parent 48b4d89510
commit d1e2366a4d
2 changed files with 315 additions and 33 deletions

View File

@ -25,7 +25,7 @@ import (
"github.com/elastic/go-elasticsearch/v8/esapi"
)
const ESIndex = "books-from-mysql-v2"
const ESIndex = "books-from-mysql-v3"
// ESBookResponse 用于返回给Java客户端的格式ID为简单的int64
type ESBookResponse struct {

View File

@ -15,6 +15,8 @@ import (
jsoniter "github.com/json-iterator/go"
"io"
"log"
"mime/multipart"
"net/http"
"strconv"
"strings"
"time"
@ -117,8 +119,8 @@ func (svc *BookService) SearchBookBaseInfo(request *request.BookSearchRequest) (
}
// ========== 构建查询条件 ==========
svc.buildISuitCondition(queryBuilder, request.IsSuit)
svc.buildIsReturnCondition(queryBuilder, request.IsReturn)
//svc.buildISuitCondition(queryBuilder, request.IsSuit)
//svc.buildIsReturnCondition(queryBuilder, request.IsReturn)
svc.buildIsFilterCondition(queryBuilder, request.IsFilter, request.ShopType)
svc.buildCategoryTypeCondition(queryBuilder, request.CategoryType)
svc.buildCategoryCondition(queryBuilder, request.Category)
@ -268,11 +270,51 @@ func (svc *BookService) UpdateBookFieldsByISBN(request *request.BookUpdateReques
var scriptParts []string
params := make(map[string]interface{})
//svc.AddFilterSet(request.ISBN)
// 判断 is_suit 是否已传递,如果没传则自动检测
if _, exists := request.Data["is_suit"]; !exists {
if isSuitValue, exists := request.Data["is_suit"]; exists {
// 定义一个辅助函数来检查值是否为 1
isOne := func(v interface{}) bool {
switch val := v.(type) {
case int:
return val == 1
case int8:
return val == 1
case int16:
return val == 1
case int32:
return val == 1
case int64:
return val == 1
case float32:
return val == 1.0
case float64:
return val == 1.0
case string:
return val == "1"
default:
return false
}
}
// 如果手动传递了 is_suit检查是否为 1
if isOne(isSuitValue) {
params["is_filter"] = "100100"
scriptParts = append(scriptParts, fmt.Sprintf("ctx._source.is_filter = params.is_filter;"))
log.Printf("[UpdateBookFieldsByISBN] 检测到 is_suit=1自动设置 is_filter=100100 | ISBN=%s | 原始类型:%T",
request.ISBN, isSuitValue)
}
} else {
// 未传递 is_suit自动检测并设置
params["is_suit"] = map[bool]int{true: 1, false: 0}[es.CheckBookSuit(book.BookName.Value)]
isSuitValue := map[bool]int{true: 1, false: 0}[es.CheckBookSuit(book.BookName.Value)]
params["is_suit"] = isSuitValue
scriptParts = append(scriptParts, fmt.Sprintf("ctx._source.is_suit = params.is_suit;"))
// 如果 is_suit 为 1同时更新 is_filter 为 100100
if isSuitValue == 1 {
params["is_filter"] = "100100"
scriptParts = append(scriptParts, fmt.Sprintf("ctx._source.is_filter = params.is_filter;"))
log.Printf("[UpdateBookFieldsByISBN] 自动检测到 is_suit=1设置 is_filter=100100 | ISBN=%s", request.ISBN)
}
}
for field, value := range request.Data {
@ -300,6 +342,12 @@ func (svc *BookService) UpdateBookFieldsByISBN(request *request.BookUpdateReques
},
},
}
fmt.Println("[DEBUG] ES UpdateByQuery Request Body:", body)
//return &UpdateBookResult{
// ISBN: request.ISBN,
// Updated: 1,
// Fields: request.Data,
//}, nil
payload, _ := json.Marshal(body)
res, err := svc.esClient.Client.UpdateByQuery(
[]string{es.ESIndex},
@ -330,7 +378,7 @@ func (svc *BookService) UpdateBookFieldsByISBN(request *request.BookUpdateReques
// 同步 Redis
_ = svc.SyncRedisByISBN(request.ISBN, "update")
//svc.AddFilterSet(request.ISBN)
return &UpdateBookResult{
ISBN: request.ISBN,
Updated: parsed.Updated,
@ -338,6 +386,113 @@ func (svc *BookService) UpdateBookFieldsByISBN(request *request.BookUpdateReques
}, nil
}
// AddFilterSet 添加过滤集合POST form-data
//func (svc *BookService) AddFilterSet(isbn string) error {
// fmt.Println("AddFilterSet start")
// url := "https://erp.buzhiyushu.cn/zhishu/filterSet"
//
// // 创建 JSON 请求体
// jsonData := map[string]interface{}{
// "filterType": "1",
// "limitationType": "0",
// "addWay": "0",
// "addTxt": isbn,
// "sort": "0,3",
// }
//
// jsonBody, err := json.Marshal(jsonData)
// if err != nil {
// return fmt.Errorf("序列化 JSON 失败:%v", err)
// }
//
// fmt.Println("[AddFilterSet] 创建 JSON 请求体", isbn)
//
// // 创建 HTTP 请求
// httpReq, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonBody))
// if err != nil {
// return fmt.Errorf("创建 HTTP 请求失败:%v", err)
// }
//
// // 设置请求头
// httpReq.Header.Set("Content-Type", "application/json")
//
// // 发送请求
// client := &http.Client{
// Timeout: 30 * time.Second,
// }
//
// resp, err := client.Do(httpReq)
// if err != nil {
// return fmt.Errorf("发送 HTTP 请求失败:%v", err)
// }
// fmt.Println("[AddFilterSet] 响应状态:%d", resp.StatusCode)
// defer resp.Body.Close()
//
// // 读取响应
// respBody, err := io.ReadAll(resp.Body)
// if err != nil {
// return fmt.Errorf("读取响应失败:%v", err)
// }
//
// log.Printf("[AddFilterSet] 响应状态:%d | 响应内容:%s", resp.StatusCode, string(respBody))
//
// return nil
//}
// AddFilterSet 添加过滤集合POST form-data
func (svc *BookService) AddFilterSet(isbn string) error {
fmt.Println("AddFilterSet start")
url := "http://103.236.91.138:8888/api/addFilterSet"
// 创建 multipart form
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
fmt.Println("[AddFilterSet] 创建 multipart form", isbn)
// 添加表单字段
_ = writer.WriteField("filterType", "1")
_ = writer.WriteField("limitationType", "0")
_ = writer.WriteField("addWay", "6")
_ = writer.WriteField("addTxt", isbn)
_ = writer.WriteField("createBy", "1")
_ = writer.WriteField("tenantId", "000000")
_ = writer.WriteField("sort", "0,3")
err := writer.Close()
if err != nil {
return fmt.Errorf("关闭 multipart writer 失败:%v", err)
}
// 创建 HTTP 请求
httpReq, err := http.NewRequest("POST", url, body)
if err != nil {
return fmt.Errorf("创建 HTTP 请求失败:%v", err)
}
httpReq.Header.Set("Content-Type", writer.FormDataContentType())
// 发送请求
client := &http.Client{
Timeout: 30 * time.Second,
}
resp, err := client.Do(httpReq)
fmt.Println("[AddFilterSet] 发送 HTTP 请求", resp)
if err != nil {
return fmt.Errorf("发送 HTTP 请求失败:%v", err)
}
fmt.Println("[AddFilterSet] 响应状态:%d", resp.StatusCode)
defer resp.Body.Close()
// 读取响应
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return fmt.Errorf("读取响应失败:%v", err)
}
log.Printf("[AddFilterSet] 响应状态:%d | 响应内容:%s", resp.StatusCode, string(respBody))
return nil
}
// UpdateBookCatIdByISBNHandler 更新图书字段
func (svc *BookService) UpdateBookCatIdByISBNHandler(request *request.BookUpdateRequest) (*UpdateBookResult, error) {
// 先确认 ISBN 是否存在
@ -1010,11 +1165,45 @@ func (svc *BookService) buildISuitCondition(builder *ESQueryBuilder, isSuit stri
}
log.Printf("[DEBUG] is_suit val=%q", isSuit)
if num, err := strconv.Atoi(isSuit); err == nil {
if num == 0 {
valueQuery := map[string]interface{}{
"term": map[string]interface{}{
"is_suit": 0,
},
}
//TODO 兼容 null 值
nullQuery := map[string]interface{}{
"bool": map[string]interface{}{
"must_not": []map[string]interface{}{
{
"exists": map[string]interface{}{
"field": "is_suit",
},
},
},
},
}
//TODO 兼容 空串
emptyQuery := map[string]interface{}{
"term": map[string]interface{}{
"is_suit": "",
},
}
builder.AddBoolQuery("must", []map[string]interface{}{
{
"bool": map[string]interface{}{
"should": []map[string]interface{}{valueQuery, nullQuery, emptyQuery},
},
},
})
log.Printf("[DEBUG] is_suit=0兼容 null 值")
} else {
builder.AddQuery(&QueryCondition{
Field: "is_suit",
Value: num,
Type: "term",
})
}
} else {
log.Printf("[ERROR] is_suit Atoi error: %v", err)
}
@ -1027,11 +1216,45 @@ func (svc *BookService) buildIsReturnCondition(builder *ESQueryBuilder, isReturn
}
log.Printf("[DEBUG] is_return val=%q", isReturn)
if num, err := strconv.Atoi(isReturn); err == nil {
if num == 0 {
valueQuery := map[string]interface{}{
"term": map[string]interface{}{
"is_return": 0,
},
}
//TODO 兼容 null 值
nullQuery := map[string]interface{}{
"bool": map[string]interface{}{
"must_not": []map[string]interface{}{
{
"exists": map[string]interface{}{
"field": "is_return",
},
},
},
},
}
//TODO 兼容 空串
emptyQuery := map[string]interface{}{
"term": map[string]interface{}{
"is_return": "",
},
}
builder.AddBoolQuery("must", []map[string]interface{}{
{
"bool": map[string]interface{}{
"should": []map[string]interface{}{valueQuery, nullQuery, emptyQuery},
},
},
})
log.Printf("[DEBUG] is_return=0兼容 null 值")
} else {
builder.AddQuery(&QueryCondition{
Field: "is_return",
Value: num,
Type: "term",
})
}
} else {
log.Printf("[ERROR] is_return Atoi error: %v", err)
}
@ -1063,11 +1286,48 @@ func (svc *BookService) buildIsFilterCondition(builder *ESQueryBuilder, isFilter
return
}
if isFilter == "2" {
wildcardQuery := map[string]interface{}{
"wildcard": map[string]interface{}{
"is_filter": pattern,
},
}
//TODO 兼容 null 值
nullQuery := map[string]interface{}{
"bool": map[string]interface{}{
"must_not": []map[string]interface{}{
{
"exists": map[string]interface{}{
"field": "is_filter",
},
},
},
},
}
//TODO 兼容 空串
emptyQuery := map[string]interface{}{
"term": map[string]interface{}{
"is_filter": "",
},
}
builder.AddBoolQuery("must", []map[string]interface{}{
{
"bool": map[string]interface{}{
"should": []map[string]interface{}{wildcardQuery, nullQuery, emptyQuery},
},
},
})
log.Printf("[DEBUG] is_filter=2兼容 null 值 | pattern=%s", pattern)
} else {
builder.AddQuery(&QueryCondition{
Field: "is_filter",
Type: "wildcard",
Pattern: pattern,
})
}
}
// buildCategoryTypeCondition 构建 categoryType 查询条件
@ -1187,6 +1447,33 @@ func (svc *BookService) buildTotalSaleRangeCondition(builder *ESQueryBuilder, to
if len(parts) == 2 {
minVal, _ := strconv.Atoi(parts[0])
maxVal, _ := strconv.Atoi(parts[1])
// 如果查询范围包含 00-999999需要同时匹配 null 值
if minVal == 0 {
// 使用 bool should 查询:匹配范围内值 OR 字段为 null/不存在
rangeQuery := map[string]interface{}{
"range": map[string]interface{}{
"total_sale": map[string]interface{}{
"gte": minVal,
"lte": maxVal,
},
},
}
nullQuery := map[string]interface{}{
"bool": map[string]interface{}{
"must_not": []map[string]interface{}{
{
"exists": map[string]interface{}{
"field": "total_sale",
},
},
},
},
}
builder.AddBoolQuery("should", []map[string]interface{}{rangeQuery, nullQuery})
} else {
// 普通范围查询,不包含 null 值
builder.AddQuery(&QueryCondition{
Field: "total_sale",
Type: "range",
@ -1194,6 +1481,7 @@ func (svc *BookService) buildTotalSaleRangeCondition(builder *ESQueryBuilder, to
LTE: maxVal,
})
}
}
}
// buildNumericRangeConditions 构建数值范围查询条件
@ -1270,12 +1558,6 @@ func (svc *BookService) buildNumericRangeConditions(builder *ESQueryBuilder, req
LTE: maxVal,
})
}
//builder.AddQuery(&QueryCondition{
// Field: esField,
// Type: "range",
// GTE: minVal,
// LTE: maxVal,
//})
}
}
}