优化选品中心
This commit is contained in:
parent
f1503b6490
commit
7f14b6cf53
@ -31,27 +31,27 @@ func GetESFieldConfig() *ESFieldConfig {
|
||||
"fix_price": true,
|
||||
"content": true,
|
||||
"is_suit": true,
|
||||
"day_sale_7": true,
|
||||
"day_sale_15": true,
|
||||
"day_sale_30": true,
|
||||
"day_sale_60": true,
|
||||
"day_sale_90": true,
|
||||
"day_sale_180": true,
|
||||
"day_sale_365": true,
|
||||
"this_year_sale": true,
|
||||
"last_year_sale": true,
|
||||
"total_sale": true,
|
||||
"buy_counts": true,
|
||||
"sell_counts": true,
|
||||
"is_illegal": true,
|
||||
"is_return": true,
|
||||
"is_filter": true,
|
||||
"update_time": true,
|
||||
"page_count": true,
|
||||
"word_count": true,
|
||||
"book_format": true,
|
||||
"cat_id": true,
|
||||
"other": true, // 允许更新 other 字段
|
||||
//"day_sale_7": true,
|
||||
//"day_sale_15": true,
|
||||
//"day_sale_30": true,
|
||||
//"day_sale_60": true,
|
||||
//"day_sale_90": true,
|
||||
//"day_sale_180": true,
|
||||
//"day_sale_365": true,
|
||||
//"this_year_sale": true,
|
||||
//"last_year_sale": true,
|
||||
//"total_sale": true,
|
||||
//"buy_counts": true,
|
||||
//"sell_counts": true,
|
||||
"is_illegal": true,
|
||||
"is_return": true,
|
||||
"is_filter": true,
|
||||
"update_time": true,
|
||||
//"page_count": true,
|
||||
//"word_count": true,
|
||||
//"book_format": true,
|
||||
"cat_id": true,
|
||||
"other": true, // 允许更新 other 字段
|
||||
},
|
||||
|
||||
AllowAdd: map[string]bool{
|
||||
|
||||
399
es/es_search.go
399
es/es_search.go
@ -162,6 +162,10 @@ func (book *ESBook) ConvertToResponse() ESBookResponse {
|
||||
publicationTime := book.PublicationTime
|
||||
if publicationTime == "" || publicationTime == "0" || publicationTime == "0000-00-00" {
|
||||
publicationTime = time.Unix(0, 0).Format("2006-01")
|
||||
} else {
|
||||
if timeVal, err := strconv.ParseInt(publicationTime, 10, 64); err == nil {
|
||||
publicationTime = strconv.FormatInt(timeVal-5364000000, 10)
|
||||
}
|
||||
}
|
||||
return ESBookResponse{
|
||||
ID: book.ID,
|
||||
@ -243,18 +247,18 @@ type ESBook struct {
|
||||
Content string `json:"content,omitempty"`
|
||||
IsSuit int `json:"is_suit,omitempty"`
|
||||
// ⭐ 新增的字段
|
||||
DaySale7 int `json:"day_sale_7,omitempty"`
|
||||
DaySale15 int `json:"day_sale_15,omitempty"`
|
||||
DaySale30 int `json:"day_sale_30,omitempty"`
|
||||
DaySale60 int `json:"day_sale_60,omitempty"`
|
||||
DaySale90 int `json:"day_sale_90,omitempty"`
|
||||
DaySale180 int `json:"day_sale_180,omitempty"`
|
||||
DaySale365 int `json:"day_sale_365,omitempty"`
|
||||
ThisYearSale int `json:"this_year_sale,omitempty"`
|
||||
LastYearSale int `json:"last_year_sale,omitempty"`
|
||||
TotalSale int `json:"total_sale,omitempty"`
|
||||
BuyCounts int64 `json:"buy_counts,omitempty"`
|
||||
SellCounts int64 `json:"sell_counts,omitempty"`
|
||||
DaySale7 int `json:"day_sale_7"`
|
||||
DaySale15 int `json:"day_sale_15"`
|
||||
DaySale30 int `json:"day_sale_30"`
|
||||
DaySale60 int `json:"day_sale_60"`
|
||||
DaySale90 int `json:"day_sale_90"`
|
||||
DaySale180 int `json:"day_sale_180"`
|
||||
DaySale365 int `json:"day_sale_365"`
|
||||
ThisYearSale int `json:"this_year_sale"`
|
||||
LastYearSale int `json:"last_year_sale"`
|
||||
TotalSale int `json:"total_sale"`
|
||||
BuyCounts int64 `json:"buy_counts"`
|
||||
SellCounts int64 `json:"sell_counts"`
|
||||
BookPicObj map[string]interface{} `json:"book_pic_obj,omitempty"`
|
||||
BookPicObjS map[string]interface{} `json:"book_pic_obj_s,omitempty"`
|
||||
UpdateTime NumberOrString `json:"update_time,omitempty"`
|
||||
@ -1487,11 +1491,6 @@ func (svc *ESSearchService) SearchBookBaseInfoES(c *gin.Context) ([]ESBook, int,
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
//if res.IsError() {
|
||||
// raw, _ := io.ReadAll(res.Body)
|
||||
// fmt.Printf("[ERROR] ES error body: %s\n", string(raw))
|
||||
// return nil, 0, fmt.Errorf("ES error: %s", string(raw))
|
||||
//}
|
||||
// 读取响应
|
||||
var buf bytes.Buffer
|
||||
// 使用CopyBuffer可以重用缓冲区
|
||||
@ -1522,11 +1521,6 @@ func (svc *ESSearchService) SearchBookBaseInfoES(c *gin.Context) ([]ESBook, int,
|
||||
if err := _json.Unmarshal(rawData, &parsed); err != nil {
|
||||
return nil, 0, fmt.Errorf("JSON解析失败: %v, 原始数据: %s", err, string(rawData[:min(200, len(rawData))]))
|
||||
}
|
||||
//var parsed esHitsWrapper
|
||||
//if err := json.NewDecoder(res.Body).Decode(&parsed); err != nil {
|
||||
// fmt.Printf("[ERROR] JSON Decode error: %v\n", err)
|
||||
// return nil, 0, err
|
||||
//}
|
||||
list := make([]ESBook, 0, len(parsed.Hits.Hits))
|
||||
for _, hit := range parsed.Hits.Hits {
|
||||
list = append(list, hit.Source)
|
||||
@ -1545,7 +1539,7 @@ func (svc *ESSearchService) BatchGetBookBaseInfoES(c *gin.Context) ([]ESBook, in
|
||||
"bookName": "book_name",
|
||||
"bookPic": "book_pic",
|
||||
"publication_times": "publication_time",
|
||||
//"isSuit": "is_suit",
|
||||
"isSuit": "is_suit",
|
||||
}
|
||||
|
||||
// ===== saleSelect 对应字段映射 =====
|
||||
@ -1588,7 +1582,7 @@ func (svc *ESSearchService) BatchGetBookBaseInfoES(c *gin.Context) ([]ESBook, in
|
||||
continue
|
||||
}
|
||||
// 不作为查询条件的字段
|
||||
if key == "page" || key == "pageSize" || key == "per_page" || key == "saleSelect" || key == "picType" || key == "shopType" || key == "isSuit" || key == "is_return" {
|
||||
if key == "page" || key == "pageSize" || key == "per_page" || key == "saleSelect" || key == "picType" || key == "shopType" {
|
||||
continue
|
||||
}
|
||||
|
||||
@ -1678,35 +1672,6 @@ func (svc *ESSearchService) BatchGetBookBaseInfoES(c *gin.Context) ([]ESBook, in
|
||||
"is_filter": pattern,
|
||||
},
|
||||
}
|
||||
if val == "2" {
|
||||
cond = map[string]interface{}{
|
||||
"bool": map[string]interface{}{
|
||||
"should": []map[string]interface{}{
|
||||
// 情况 1: is_filter 字段null
|
||||
{
|
||||
"bool": map[string]interface{}{
|
||||
"must_not": []map[string]interface{}{
|
||||
{"exists": map[string]interface{}{"field": "is_filter"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
// 情况 2: is_filter 空串
|
||||
{
|
||||
"term": map[string]interface{}{
|
||||
"is_filter": "",
|
||||
},
|
||||
},
|
||||
// 情况 3: is_filter 字段存在且匹配 wildcard 模式
|
||||
{
|
||||
"wildcard": map[string]interface{}{
|
||||
"is_filter": pattern,
|
||||
},
|
||||
},
|
||||
},
|
||||
"minimum_should_match": 1,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
must = append(must, cond)
|
||||
fmt.Printf("[DEBUG] must += %v\n", cond)
|
||||
@ -1841,32 +1806,7 @@ func (svc *ESSearchService) BatchGetBookBaseInfoES(c *gin.Context) ([]ESBook, in
|
||||
},
|
||||
},
|
||||
}
|
||||
if minVal == 0 {
|
||||
cond = map[string]interface{}{
|
||||
"bool": map[string]interface{}{
|
||||
"should": []map[string]interface{}{
|
||||
// 情况 1: buy_counts 字段不存在或为 null
|
||||
{
|
||||
"bool": map[string]interface{}{
|
||||
"must_not": []map[string]interface{}{
|
||||
{"exists": map[string]interface{}{"field": "buy_counts"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
// 情况 2: buy_counts 在范围内
|
||||
{
|
||||
"range": map[string]interface{}{
|
||||
"buy_counts": map[string]interface{}{
|
||||
"gte": minVal,
|
||||
"lte": maxVal,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"minimum_should_match": 1,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
must = append(must, cond)
|
||||
fmt.Printf("[DEBUG] must += %v\n", cond)
|
||||
continue
|
||||
@ -1901,38 +1841,80 @@ func (svc *ESSearchService) BatchGetBookBaseInfoES(c *gin.Context) ([]ESBook, in
|
||||
},
|
||||
},
|
||||
}
|
||||
if minVal == 0 {
|
||||
cond = map[string]interface{}{
|
||||
"bool": map[string]interface{}{
|
||||
"should": []map[string]interface{}{
|
||||
// 情况 1: total_sale 字段不存在或为 null
|
||||
{
|
||||
"bool": map[string]interface{}{
|
||||
"must_not": []map[string]interface{}{
|
||||
{"exists": map[string]interface{}{"field": "total_sale"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
// 情况 2: total_sale 在范围内
|
||||
{
|
||||
"range": map[string]interface{}{
|
||||
"total_sale": map[string]interface{}{
|
||||
"gte": minVal,
|
||||
"lte": maxVal,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"minimum_should_match": 1,
|
||||
},
|
||||
}
|
||||
}
|
||||
//if minVal == 0 {
|
||||
// cond = map[string]interface{}{
|
||||
// "bool": map[string]interface{}{
|
||||
// "should": []map[string]interface{}{
|
||||
// // 情况 1: total_sale 字段不存在或为 null
|
||||
// {
|
||||
// "bool": map[string]interface{}{
|
||||
// "must_not": []map[string]interface{}{
|
||||
// {"exists": map[string]interface{}{"field": "total_sale"}},
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// // 情况 2: total_sale 在范围内
|
||||
// {
|
||||
// "range": map[string]interface{}{
|
||||
// "total_sale": map[string]interface{}{
|
||||
// "gte": minVal,
|
||||
// "lte": maxVal,
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// "minimum_should_match": 1,
|
||||
// },
|
||||
// }
|
||||
//}
|
||||
must = append(must, cond)
|
||||
fmt.Printf("[DEBUG] must += %v\n", cond)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// ===== page_count 范围查询 =====
|
||||
if key == "page_count" {
|
||||
parts := strings.Split(val, ",")
|
||||
if len(parts) == 2 {
|
||||
minVal, _ := strconv.Atoi(parts[0])
|
||||
maxVal, _ := strconv.Atoi(parts[1])
|
||||
|
||||
cond := map[string]interface{}{
|
||||
"range": map[string]interface{}{
|
||||
"page_count": map[string]interface{}{
|
||||
"gte": minVal,
|
||||
"lte": maxVal,
|
||||
},
|
||||
},
|
||||
}
|
||||
must = append(must, cond)
|
||||
fmt.Printf("[DEBUG] must += %v (page_count: %d-%d)\n", cond, minVal, maxVal)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// ===== word_count 范围查询 =====
|
||||
if key == "word_count" {
|
||||
parts := strings.Split(val, ",")
|
||||
if len(parts) == 2 {
|
||||
minVal, _ := strconv.Atoi(parts[0])
|
||||
maxVal, _ := strconv.Atoi(parts[1])
|
||||
|
||||
cond := map[string]interface{}{
|
||||
"range": map[string]interface{}{
|
||||
"word_count": map[string]interface{}{
|
||||
"gte": minVal,
|
||||
"lte": maxVal,
|
||||
},
|
||||
},
|
||||
}
|
||||
must = append(must, cond)
|
||||
fmt.Printf("[DEBUG] must += %v (word_count: %d-%d)\n", cond, minVal, maxVal)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 数值范围 =====
|
||||
if key == "sell_counts" ||
|
||||
strings.HasPrefix(key, "day_sale_") ||
|
||||
@ -1952,32 +1934,7 @@ func (svc *ESSearchService) BatchGetBookBaseInfoES(c *gin.Context) ([]ESBook, in
|
||||
},
|
||||
},
|
||||
}
|
||||
if minVal == 0 {
|
||||
cond = map[string]interface{}{
|
||||
"bool": map[string]interface{}{
|
||||
"should": []map[string]interface{}{
|
||||
// 情况 1: total_sale 字段不存在或为 null
|
||||
{
|
||||
"bool": map[string]interface{}{
|
||||
"must_not": []map[string]interface{}{
|
||||
{"exists": map[string]interface{}{"field": "total_sale"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
// 情况 2: total_sale 在范围内
|
||||
{
|
||||
"range": map[string]interface{}{
|
||||
key: map[string]interface{}{
|
||||
"gte": minVal,
|
||||
"lte": maxVal,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"minimum_should_match": 1,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
must = append(must, cond)
|
||||
fmt.Printf("[DEBUG] must += %v\n", cond)
|
||||
continue
|
||||
@ -2010,7 +1967,6 @@ func (svc *ESSearchService) BatchGetBookBaseInfoES(c *gin.Context) ([]ESBook, in
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Println("key--------------", key)
|
||||
// ===== 默认前缀匹配 =====
|
||||
cond := map[string]interface{}{
|
||||
"prefix": map[string]interface{}{key: val},
|
||||
@ -2053,21 +2009,6 @@ func (svc *ESSearchService) BatchGetBookBaseInfoES(c *gin.Context) ([]ESBook, in
|
||||
body, _ := json.MarshalIndent(query, "", " ")
|
||||
fmt.Printf("[DEBUG] ES Query Body:\n%s\n", string(body))
|
||||
|
||||
// ========== 执行 ES 查询 ==========
|
||||
//res, err := svc.ES.Client.Search(
|
||||
// svc.ES.Client.Search.WithIndex(ESIndex),
|
||||
// svc.ES.Client.Search.WithBody(bytes.NewReader(body)),
|
||||
// svc.ES.Client.Search.WithTrackTotalHits(true),
|
||||
//)
|
||||
//
|
||||
//fmt.Printf("[DEBUG] ES Query Response:\n%s\n", res)
|
||||
//
|
||||
//if err != nil {
|
||||
// fmt.Printf("[ERROR] ES.Client.Search error: %v\n", err)
|
||||
// return nil, 0, err
|
||||
//}
|
||||
//defer res.Body.Close()
|
||||
|
||||
endpoint := c.FullPath()
|
||||
monitoredES := monitor.NewMonitoredESClient(svc.ES.Client, endpoint)
|
||||
|
||||
@ -2403,166 +2344,6 @@ func (svc *ESSearchService) SearchBookByISBNHandler(c *gin.Context) {
|
||||
})
|
||||
}
|
||||
|
||||
// func (svc *ESSearchService) SearchBooksHandler(c *gin.Context) {
|
||||
// isbn := c.Query("isbn")
|
||||
// if isbn == "" {
|
||||
// c.JSON(400, gin.H{"error": "缺少 isbn 参数"})
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// ctx := context.Background()
|
||||
//
|
||||
// db4Client, err := redisClient.GetClientByName("db1")
|
||||
// if err == nil {
|
||||
// val, err := db4Client.Get(ctx, isbn).Result()
|
||||
// if err == nil && val != "" {
|
||||
// log.Printf("[SearchBooksHandler] 从 Redis db1 查询到数据: %s", isbn)
|
||||
// // 使用 RedisBookInfo 结构体解析
|
||||
// var redisBook request.BookInfo
|
||||
// if err := json.Unmarshal([]byte(val), &redisBook); err == nil {
|
||||
// // 转换为 ESBook
|
||||
// esBook := ConvertRedisBookToESBook(&redisBook)
|
||||
// if esBook != nil {
|
||||
// responseData := esBook.ConvertToResponse()
|
||||
// c.JSON(200, gin.H{
|
||||
// "data": responseData,
|
||||
// })
|
||||
// return
|
||||
// }
|
||||
// } else {
|
||||
// log.Printf("[SearchBookByISBNHandler] Redis 数据解析失败:%v", err)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// result, err := svc.SearchBooks(isbn)
|
||||
// if err != nil {
|
||||
// c.JSON(500, gin.H{"error": "ES 查询失败", "details": err.Error()})
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// responseList := make([]ESBookResponse, 0, len(result))
|
||||
// for _, book := range result {
|
||||
// responseList = append(responseList, book.ConvertToResponse())
|
||||
// }
|
||||
//
|
||||
// c.JSON(200, gin.H{
|
||||
// "count": len(result),
|
||||
// "data": responseList,
|
||||
// })
|
||||
// }
|
||||
//func (svc *ESSearchService) SearchBookByISBNHandler(c *gin.Context) {
|
||||
//
|
||||
// isbn := c.Query("isbn")
|
||||
// if isbn == "" {
|
||||
// log.Printf("[SearchBookByISBNHandler] 缺少 isbn 参数")
|
||||
// c.JSON(400, gin.H{"error": "缺少 isbn 参数"})
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// log.Printf("[SearchBookByISBNHandler] 查询 ISBN: %s", isbn)
|
||||
//
|
||||
// ctx := context.Background()
|
||||
//
|
||||
// db4Client, err := redisClient.GetClientByName("db1")
|
||||
// fmt.Println(db4Client)
|
||||
//
|
||||
// if err != nil {
|
||||
// log.Printf("[SearchBookByISBNHandler] 获取 Redis db1 客户端失败: %v", err)
|
||||
// } else {
|
||||
// val, err := db4Client.Get(ctx, isbn).Result()
|
||||
// if err == nil && val != "" {
|
||||
// log.Printf("[SearchBookByISBNHandler] 从 Redis db1 查询到数据: %s", isbn)
|
||||
// // 使用 RedisBookInfo 结构体解析
|
||||
// var redisBook request.BookInfo
|
||||
// if err := json.Unmarshal([]byte(val), &redisBook); err == nil {
|
||||
// // 转换为 ESBook
|
||||
// esBook := ConvertRedisBookToESBook(&redisBook)
|
||||
// if esBook != nil {
|
||||
// responseData := esBook.ConvertToResponse()
|
||||
// c.JSON(200, gin.H{
|
||||
// "data": responseData,
|
||||
// })
|
||||
// return
|
||||
// }
|
||||
// } else {
|
||||
// log.Printf("[SearchBookByISBNHandler] Redis 数据解析失败:%v", err)
|
||||
// }
|
||||
// } else {
|
||||
// log.Printf("[SearchBookByISBNHandler] Redis db1 中未找到 ISBN: %s", isbn)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// result, err := svc.SearchBookByISBN(isbn)
|
||||
// if err != nil {
|
||||
// log.Printf("[SearchBookByISBNHandler] ES 查询失败: %v", err)
|
||||
// c.JSON(500, gin.H{"error": err.Error()})
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// if result == nil {
|
||||
// log.Printf("[SearchBookByISBNHandler] ES 中未找到 ISBN: %s,从孔夫子抓取", isbn)
|
||||
//
|
||||
// apiBook, err := kongfz.GetBookImageByISBN(isbn, "CALF_ELEPHANT_PROXY", "1297757178467602432", "QgQBvP7f")
|
||||
// if err != nil {
|
||||
// log.Printf("[SearchBookByISBNHandler] 孔夫子 API 查询失败: %v", err)
|
||||
// c.JSON(500, gin.H{"error": err.Error()})
|
||||
// return
|
||||
// }
|
||||
// if apiBook == nil || apiBook.Data.ISBN == "" {
|
||||
// log.Printf("[SearchBookByISBNHandler] 孔夫子 API 未找到图书信息 ISBN: %s", isbn)
|
||||
// c.JSON(404, gin.H{"error": "未找到图书信息"})
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// log.Printf("[SearchBookByISBNHandler] 获取到图书信息: %+v", apiBook.Data)
|
||||
//
|
||||
// pddBookPicURL := ""
|
||||
// if apiBook.Data.BookPic != "" {
|
||||
// url, err := image.DownloadAndUploadBookImage(apiBook.Data.BookPic, isbn, "true", apiBook.Data.BookName, "true")
|
||||
// if err != nil {
|
||||
// log.Printf("[SearchBookByISBNHandler] 上传 book_pic 失败: %v", err)
|
||||
// } else {
|
||||
// pddBookPicURL = url
|
||||
// log.Printf("[SearchBookByISBNHandler] 上传 book_pic 成功: %s", url)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// pddBookPicSURL := ""
|
||||
// if apiBook.Data.BookPicS != "" {
|
||||
// url, err := image.DownloadAndUploadBookImage(apiBook.Data.BookPicS, isbn, "true", apiBook.Data.BookName, "true")
|
||||
// if err != nil {
|
||||
// log.Printf("[SearchBookByISBNHandler] 上传 book_pic_s 失败: %v", err)
|
||||
// } else {
|
||||
// pddBookPicSURL = url
|
||||
// log.Printf("[SearchBookByISBNHandler] 上传 book_pic_s 成功: %s", url)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// esBook := ConvertKongfzToESBook(apiBook)
|
||||
//
|
||||
// esBook.BookPicS.PddResponse = pddBookPicSURL
|
||||
// esBook.BookPic.PddPath = pddBookPicURL
|
||||
// //log.Printf("[SearchBookByISBNHandler] 写入 ES: %+v", esBook)
|
||||
//
|
||||
// result, err = svc.AddBookToES(c.Request.Context(), esBook)
|
||||
// if err != nil {
|
||||
// log.Printf("[SearchBookByISBNHandler] 写入 ES 失败: %v", err)
|
||||
// c.JSON(500, gin.H{"error": err.Error()})
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// log.Printf("[SearchBookByISBNHandler] 写入 ES 成功, ISBN: %s", isbn)
|
||||
// } else {
|
||||
// //log.Printf("[SearchBookByISBNHandler] 从 ES 查询到图书: %+v", result)
|
||||
// }
|
||||
//
|
||||
// responseData := result.ConvertToResponse()
|
||||
// c.JSON(200, gin.H{
|
||||
// "data": responseData,
|
||||
// })
|
||||
//}
|
||||
|
||||
// ConvertKongfzToESBook 将第三方接口返回的数据转换为 ESBook 结构
|
||||
func ConvertKongfzToESBook(apiBook *kongfz.BookResponse) *ESBook {
|
||||
if apiBook == nil || apiBook.Data.ISBN == "" {
|
||||
@ -2930,8 +2711,6 @@ func (svc *ESSearchService) UpdateBookSuitByISBNHandler(c *gin.Context) {
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Println(body)
|
||||
|
||||
payload, _ := json.Marshal(body)
|
||||
|
||||
res, err := svc.ES.Client.UpdateByQuery(
|
||||
@ -3019,7 +2798,6 @@ func (svc *ESSearchService) UpdateBookFieldsByISBNHandler(c *gin.Context) {
|
||||
|
||||
// 先确认 ISBN 是否存在
|
||||
book, err := svc.SearchBookByISBN(isbn)
|
||||
fmt.Println("book:", book)
|
||||
if err != nil {
|
||||
c.JSON(500, gin.H{
|
||||
"error": "查询ES失败",
|
||||
@ -3128,7 +2906,6 @@ func (svc *ESSearchService) UpdateBookFieldsByISBN(
|
||||
fmt.Sprintf("ctx._source.%s = params.%s;", field, field))
|
||||
params[field] = value
|
||||
}
|
||||
fmt.Println("scriptParts:", scriptParts)
|
||||
if len(scriptParts) == 0 {
|
||||
return 0, fmt.Errorf("没有有效的字段可更新")
|
||||
}
|
||||
|
||||
11
main.go
11
main.go
@ -184,10 +184,15 @@ func main() {
|
||||
// "zDzSXel3PFwx9=6Ybmqv",
|
||||
//)
|
||||
/** ES2 本地测试 **/
|
||||
//esClient, err := es.NewESClient(
|
||||
// []string{"https://103.236.91.138:9200"},
|
||||
// "elastic",
|
||||
// "7AYdoW=mn3yHZ*3A=Z1x",
|
||||
//)
|
||||
esClient, err := es.NewESClient(
|
||||
[]string{"https://103.236.91.138:9200"},
|
||||
[]string{"http://36.212.1.63:9200"},
|
||||
"elastic",
|
||||
"7AYdoW=mn3yHZ*3A=Z1x",
|
||||
"zDzSXel3PFwx9=6Ybmqva",
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
@ -197,7 +202,7 @@ func main() {
|
||||
esService := es.NewESSearchService(esClient)
|
||||
|
||||
redisClient.AddClient("db4", "36.212.12.247:6379", "long6166@@", 2)
|
||||
redisClient.AddClient("db1", "36.212.12.247:6379", "long6166@@", 1)
|
||||
redisClient.AddClient("db1", "36.212.12.247:6379", "long6166@@", 7)
|
||||
//redisClient.AddClient("test", "127.0.0.1:6379", "", 0)
|
||||
// ===================================================================
|
||||
|
||||
|
||||
@ -34,6 +34,8 @@ type BookSearchRequest struct {
|
||||
LastYearSale string `form:"last_year_sale"` // 去年销量
|
||||
TotalSaleRange string `form:"totalSale_range"` // 总销量范围
|
||||
ID string `form:"id"` // ID
|
||||
PageCount string `form:"page_count"` // 页数
|
||||
WordCount string `form:"word_count"` // 字数
|
||||
}
|
||||
|
||||
// BookUpdateRequest 更新图书请求参数
|
||||
|
||||
423
service/book.go
423
service/book.go
@ -6,15 +6,12 @@ import (
|
||||
"centerBook/es"
|
||||
"centerBook/model/request"
|
||||
"centerBook/tail"
|
||||
"centerBook/util"
|
||||
"centerBook/util/redisClient"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@ -120,8 +117,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)
|
||||
@ -303,6 +300,12 @@ func (svc *BookService) UpdateBookFieldsByISBN(request *request.BookUpdateReques
|
||||
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 不为 1 时,清空 is_filter
|
||||
params["is_filter"] = "000000"
|
||||
scriptParts = append(scriptParts, fmt.Sprintf("ctx._source.is_filter = params.is_filter;"))
|
||||
log.Printf("[UpdateBookFieldsByISBN] 检测到 is_suit!=1,清空 is_filter | ISBN=%s | is_suit 值:%v",
|
||||
request.ISBN, isSuitValue)
|
||||
}
|
||||
} else {
|
||||
// 未传递 is_suit,自动检测并设置
|
||||
@ -319,14 +322,39 @@ func (svc *BookService) UpdateBookFieldsByISBN(request *request.BookUpdateReques
|
||||
}
|
||||
|
||||
for field, value := range request.Data {
|
||||
if field == "is_suit" {
|
||||
continue
|
||||
}
|
||||
// 使用配置检查字段是否允许更新
|
||||
if !fieldConfig.IsAllowUpdate(field) {
|
||||
log.Printf("[UpdateBookFieldsByISBN] 字段 %s 不允许更新,已跳过", field)
|
||||
continue
|
||||
}
|
||||
// 对 publication_time 字段做特殊处理
|
||||
if field == "publication_time" {
|
||||
// 将原始值转换为 int64 并加上 5364000000
|
||||
var pubTime int64
|
||||
switch v := value.(type) {
|
||||
case int:
|
||||
pubTime = int64(v)
|
||||
case int64:
|
||||
pubTime = v
|
||||
case float64:
|
||||
pubTime = int64(v)
|
||||
case string:
|
||||
// 如果是字符串,尝试解析
|
||||
if parsed, err := strconv.ParseInt(v, 10, 64); err == nil {
|
||||
pubTime = parsed
|
||||
}
|
||||
}
|
||||
pubTime += 5364000000
|
||||
params[field] = strconv.FormatInt(pubTime, 10)
|
||||
log.Printf("[UpdateBookFieldsByISBN] publication_time 偏移处理:%v -> %v | ISBN=%s", value, pubTime, request.ISBN)
|
||||
} else {
|
||||
params[field] = value
|
||||
}
|
||||
scriptParts = append(scriptParts,
|
||||
fmt.Sprintf("ctx._source.%s = params.%s;", field, field))
|
||||
params[field] = value
|
||||
}
|
||||
if len(scriptParts) == 0 {
|
||||
return nil, fmt.Errorf("没有有效的更新字段")
|
||||
@ -344,11 +372,6 @@ 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},
|
||||
@ -441,58 +464,58 @@ func (svc *BookService) UpdateBookFieldsByISBN(request *request.BookUpdateReques
|
||||
//}
|
||||
|
||||
// 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
|
||||
}
|
||||
//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) {
|
||||
@ -740,7 +763,10 @@ func (svc *BookService) addBookToES(ctx context.Context, req *es.ESBook) (*es.ES
|
||||
// 处理出版时间,转换为时间戳
|
||||
publicationTimeTimestamp := req.PublicationTime
|
||||
if req.PublicationTime != "" && req.PublicationTime != "0" {
|
||||
publicationTimeTimestamp = strconv.FormatInt(util.ParsePublicationTime(publicationTimeTimestamp), 10)
|
||||
publicationTimeIn64, err := strconv.ParseInt(req.PublicationTime, 10, 64)
|
||||
if err == nil {
|
||||
publicationTimeTimestamp = strconv.FormatInt(publicationTimeIn64+5364000000, 10)
|
||||
}
|
||||
}
|
||||
// 准备数据映射(使用 Go 字段名)
|
||||
dataMap := make(map[string]interface{})
|
||||
@ -789,7 +815,6 @@ func (svc *BookService) addBookToES(ctx context.Context, req *es.ESBook) (*es.ES
|
||||
if req.Other != nil {
|
||||
dataMap["Other"] = req.Other
|
||||
}
|
||||
fmt.Println("dataMap:", dataMap)
|
||||
|
||||
// 使用配置构建 ES 文档(自动转换字段名)
|
||||
doc := es.GetESFieldConfig().BuildESDocument(dataMap)
|
||||
@ -882,7 +907,7 @@ func (svc *BookService) SyncRedisByISBN(isbn string, act string) error {
|
||||
if book.PublicationTime != "" && book.PublicationTime != "0" {
|
||||
publicationTimeIn64, err := strconv.ParseInt(book.PublicationTime, 10, 64)
|
||||
if err == nil {
|
||||
redisBookInfo.PublicationDate = time.Unix(publicationTimeIn64+5364000000, 0).Format("2006-01")
|
||||
redisBookInfo.PublicationDate = time.Unix(publicationTimeIn64-5364000000, 0).Format("2006-01")
|
||||
}
|
||||
}
|
||||
if book.BindingLayout != "" {
|
||||
@ -1166,45 +1191,11 @@ 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",
|
||||
})
|
||||
}
|
||||
builder.AddQuery(&QueryCondition{
|
||||
Field: "is_suit",
|
||||
Value: num,
|
||||
Type: "term",
|
||||
})
|
||||
} else {
|
||||
log.Printf("[ERROR] is_suit Atoi error: %v", err)
|
||||
}
|
||||
@ -1217,45 +1208,11 @@ 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",
|
||||
})
|
||||
}
|
||||
builder.AddQuery(&QueryCondition{
|
||||
Field: "is_return",
|
||||
Value: num,
|
||||
Type: "term",
|
||||
})
|
||||
} else {
|
||||
log.Printf("[ERROR] is_return Atoi error: %v", err)
|
||||
}
|
||||
@ -1286,49 +1243,11 @@ func (svc *BookService) buildIsFilterCondition(builder *ESQueryBuilder, isFilter
|
||||
default:
|
||||
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,
|
||||
})
|
||||
}
|
||||
builder.AddQuery(&QueryCondition{
|
||||
Field: "is_filter",
|
||||
Type: "wildcard",
|
||||
Pattern: pattern,
|
||||
})
|
||||
}
|
||||
|
||||
// buildCategoryTypeCondition 构建 categoryType 查询条件
|
||||
@ -1421,40 +1340,13 @@ func (svc *BookService) buildBuyCountsCondition(builder *ESQueryBuilder, buyCoun
|
||||
if len(parts) == 2 {
|
||||
minVal, _ := strconv.Atoi(parts[0])
|
||||
maxVal, _ := strconv.Atoi(parts[1])
|
||||
// 如果查询范围包含 0(0-999999),需要同时匹配 null 值
|
||||
if minVal == 0 {
|
||||
// 使用 bool should 查询:匹配范围内值 OR 字段为 null/不存在
|
||||
rangeQuery := map[string]interface{}{
|
||||
"range": map[string]interface{}{
|
||||
"buy_counts": 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": "buy_counts",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
builder.AddBoolQuery("should", []map[string]interface{}{rangeQuery, nullQuery})
|
||||
} else {
|
||||
// 普通范围查询,不包含 null 值
|
||||
builder.AddQuery(&QueryCondition{
|
||||
Field: saleField,
|
||||
Type: "range",
|
||||
GTE: minVal,
|
||||
LTE: maxVal,
|
||||
})
|
||||
}
|
||||
// 普通范围查询,不包含 null 值
|
||||
builder.AddQuery(&QueryCondition{
|
||||
Field: saleField,
|
||||
Type: "range",
|
||||
GTE: minVal,
|
||||
LTE: maxVal,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
@ -1476,40 +1368,13 @@ func (svc *BookService) buildTotalSaleRangeCondition(builder *ESQueryBuilder, to
|
||||
if len(parts) == 2 {
|
||||
minVal, _ := strconv.Atoi(parts[0])
|
||||
maxVal, _ := strconv.Atoi(parts[1])
|
||||
// 如果查询范围包含 0(0-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",
|
||||
GTE: minVal,
|
||||
LTE: maxVal,
|
||||
})
|
||||
}
|
||||
// 普通范围查询,不包含 null 值
|
||||
builder.AddQuery(&QueryCondition{
|
||||
Field: "total_sale",
|
||||
Type: "range",
|
||||
GTE: minVal,
|
||||
LTE: maxVal,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -1527,6 +1392,8 @@ func (svc *BookService) buildNumericRangeConditions(builder *ESQueryBuilder, req
|
||||
"ThisYearSale": request.ThisYearSale,
|
||||
"LastYearSale": request.LastYearSale,
|
||||
"PublicationTime": request.PublicationTime,
|
||||
"PageCount": request.PageCount,
|
||||
"WordCount": request.WordCount,
|
||||
}
|
||||
|
||||
esFields := map[string]string{
|
||||
@ -1541,6 +1408,8 @@ func (svc *BookService) buildNumericRangeConditions(builder *ESQueryBuilder, req
|
||||
"ThisYearSale": "this_year_sale",
|
||||
"LastYearSale": "last_year_sale",
|
||||
"PublicationTime": "publication_time",
|
||||
"PageCount": "page_count",
|
||||
"WordCount": "word_count",
|
||||
}
|
||||
|
||||
for fieldName, value := range fields {
|
||||
@ -1549,44 +1418,20 @@ func (svc *BookService) buildNumericRangeConditions(builder *ESQueryBuilder, req
|
||||
}
|
||||
esField := esFields[fieldName]
|
||||
parts := strings.Split(value, ",")
|
||||
fmt.Println("ppp", fieldName, parts)
|
||||
if len(parts) == 2 {
|
||||
minVal, _ := strconv.Atoi(parts[0])
|
||||
maxVal, _ := strconv.Atoi(parts[1])
|
||||
// 如果查询范围包含 0(0-999999),需要同时匹配 null 值
|
||||
if minVal == 0 {
|
||||
// 使用 bool should 查询:匹配范围内值 OR 字段为 null/不存在
|
||||
rangeQuery := map[string]interface{}{
|
||||
"range": map[string]interface{}{
|
||||
esField: 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": esField,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
builder.AddBoolQuery("should", []map[string]interface{}{rangeQuery, nullQuery})
|
||||
} else {
|
||||
// 普通范围查询,不包含 null 值
|
||||
builder.AddQuery(&QueryCondition{
|
||||
Field: esField,
|
||||
Type: "range",
|
||||
GTE: minVal,
|
||||
LTE: maxVal,
|
||||
})
|
||||
if fieldName == "PublicationTime" {
|
||||
minVal += 5364000000
|
||||
maxVal += 5364000000
|
||||
}
|
||||
// 普通范围查询,不包含 null 值
|
||||
builder.AddQuery(&QueryCondition{
|
||||
Field: esField,
|
||||
Type: "range",
|
||||
GTE: minVal,
|
||||
LTE: maxVal,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user