This commit is contained in:
unknown 2026-04-18 17:20:38 +08:00
parent 7f14b6cf53
commit ec6e27e023
3 changed files with 313 additions and 1 deletions

View File

@ -70,6 +70,49 @@ type ESBookResponse struct {
Other map[string]interface{} `json:"other"` // 扩展字段,用于兼容未来新增字段
}
// ESBookResponseByPSI 用于返回给Java客户端的格式ID为简单的int64
type ESBookResponseByPSI struct {
ID int64 `json:"id"`
BookName string `json:"book_name"`
BookPic map[string]interface{} `json:"book_pic"`
BookPicS map[string]interface{} `json:"book_pic_s"`
BookPicB string `json:"book_pic_b"`
BookPicW map[string]interface{} `json:"book_pic_w"`
BookDefPic map[string]interface{} `json:"book_def_pic"` // 自制官图,临时用
ISBN string `json:"isbn"`
Author string `json:"author"`
Category string `json:"category"`
Publisher string `json:"publisher"`
PublicationTime string `json:"publication_time"`
BindingLayout string `json:"binding_layout"`
FixPrice float64 `json:"fix_price"`
Content string `json:"content"`
IsSuit int `json:"is_suit"`
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"`
BookPicObjS map[string]interface{} `json:"book_pic_obj_s"`
UpdateTime NumberOrString `json:"update_time"`
IsIllegal int `json:"is_illegal"` // 是否非法 示例 000000
IsReturn int `json:"is_return"` // 是否为驳回 示例 0 否 1 是
IsFilter string `json:"is_filter"` // 过滤字段
PageCount NumberOrString `json:"page_count"` // 页数
WordCount NumberOrString `json:"word_count"` // 字数
BookFormat NumberOrString `json:"book_format"` // 多少开
CatId request.CatIdObject `json:"cat_id"` // 类目
Other map[string]interface{} `json:"other"` // 扩展字段,用于兼容未来新增字段
}
// FlexibleString 处理可能是字符串或数组的字段
type FlexibleString struct {
Value string
@ -210,6 +253,71 @@ func (book *ESBook) ConvertToResponse() ESBookResponse {
}
}
// ConvertToResponseByPsi 将ESBook转换为ESBookResponse处理ID字段转换
func (book *ESBook) ConvertToResponseByPsi() ESBookResponseByPSI {
bookPicMap := map[string]interface{}{
"localPath": book.BookPic.LocalPath,
"pddPath": book.BookPic.PddPath,
}
bookPicSMap := map[string]interface{}{
"localPath": book.BookPicS.LocalPath,
"pddResponse": book.BookPicS.PddResponse,
}
bookDefPic := map[string]interface{}{
"localPath": book.BookDefPic.LocalPath,
"pddPath": book.BookDefPic.PddPath,
}
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 ESBookResponseByPSI{
ID: book.ID,
BookName: book.BookName.Value,
BookPic: bookPicMap,
BookPicS: bookPicSMap,
BookPicB: book.BookPicB,
BookPicW: book.BookPicW,
BookDefPic: bookDefPic,
ISBN: book.ISBN,
Author: book.Author,
Category: book.Category,
Publisher: book.Publisher,
PublicationTime: publicationTime,
BindingLayout: book.BindingLayout,
FixPrice: float64(book.FixPrice),
Content: book.Content,
IsSuit: book.IsSuit,
DaySale7: book.DaySale7,
DaySale15: book.DaySale15,
DaySale30: book.DaySale30,
DaySale60: book.DaySale60,
DaySale90: book.DaySale90,
DaySale180: book.DaySale180,
DaySale365: book.DaySale365,
ThisYearSale: book.ThisYearSale,
LastYearSale: book.LastYearSale,
TotalSale: book.TotalSale,
BuyCounts: book.BuyCounts,
SellCounts: book.SellCounts,
BookPicObj: book.BookPicObj,
BookPicObjS: book.BookPicObjS,
UpdateTime: book.UpdateTime,
IsIllegal: book.IsIllegal,
IsReturn: book.IsReturn,
IsFilter: book.IsFilter,
PageCount: book.PageCount,
WordCount: book.WordCount,
BookFormat: book.BookFormat,
CatId: book.CatId,
Other: book.Other,
}
}
// 用于 book_pic
type BookPicObj struct {
LocalPath string `json:"localPath"`
@ -323,7 +431,9 @@ type AddBookFullRequest struct {
type ESSearchService struct {
ES *ESClient
SyncRedisByISBN func(isbn string, act string) error
}
type NumberOrString string
func (n *NumberOrString) UnmarshalJSON(data []byte) error {
@ -2344,6 +2454,110 @@ func (svc *ESSearchService) SearchBookByISBNHandler(c *gin.Context) {
})
}
func (svc *ESSearchService) SearchBookByISBNHandlerToPsi(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()
endpoint := c.FullPath()
// Redis 查询(使用监控)
db1Client, err := redisClient.GetClientByName("db1")
if err == nil {
monitoredRedis := monitor.NewMonitoredRedisClient(db1Client, endpoint)
val, _, err := monitoredRedis.Get(ctx, isbn)
if err == nil && val != "" {
log.Printf("[SearchBookByISBNHandler] 从 Redis db1 查询到数据:%s", isbn)
var redisBook request.BookInfoByPsi
if err := json.Unmarshal([]byte(val), &redisBook); err == nil {
esBook := ConvertRedisBookToESBookByPsi(&redisBook)
if esBook != nil {
responseData := esBook.ConvertToResponseByPsi()
c.JSON(200, gin.H{
"data": responseData,
})
return
}
} else {
log.Printf("[SearchBookByISBNHandler] Redis 数据解析失败:%v", err)
}
}
}
// ES 查询(使用监控)
query := map[string]interface{}{
"query": map[string]interface{}{
"term": map[string]interface{}{
"isbn": isbn,
},
},
"_source": true,
}
body, err := json.Marshal(query)
if err != nil {
log.Printf("[SearchBookByISBNHandler] 构建查询 JSON 失败:%v", err)
c.JSON(500, gin.H{"error": "构建查询失败"})
return
}
req := esapi.SearchRequest{
Index: []string{ESIndex},
Body: bytes.NewReader(body),
TrackTotalHits: true,
Pretty: true,
}
// 创建监控客户端并执行查询
monitoredES := monitor.NewMonitoredESClient(svc.ES.Client, endpoint)
resp, duration, err := monitoredES.Search(ctx, &req)
log.Printf("[SearchBookByISBNHandler] ES 查询耗时:%dms", duration.Milliseconds())
if err != nil {
log.Printf("[SearchBookByISBNHandler] ES 查询失败:%v", err)
c.JSON(500, gin.H{"error": "ES 查询失败:" + err.Error()})
return
}
defer resp.Body.Close()
if resp.IsError() {
log.Printf("[SearchBookByISBNHandler] ES 返回错误:%s", resp.String())
c.JSON(500, gin.H{"error": "ES 返回错误:" + resp.String()})
return
}
var parsed esHitsWrapper
if err := json.NewDecoder(resp.Body).Decode(&parsed); err != nil {
log.Printf("[SearchBookByISBNHandler] 解析 ES 响应失败:%v", err)
c.JSON(500, gin.H{"error": "解析响应失败"})
return
}
var result *ESBook
if len(parsed.Hits.Hits) > 0 {
result = &parsed.Hits.Hits[0].Source
}
if result == nil {
c.JSON(200, gin.H{
"data": nil,
})
return
}
responseData := result.ConvertToResponseByPsi()
c.JSON(200, gin.H{
"data": responseData,
})
}
// ConvertKongfzToESBook 将第三方接口返回的数据转换为 ESBook 结构
func ConvertKongfzToESBook(apiBook *kongfz.BookResponse) *ESBook {
if apiBook == nil || apiBook.Data.ISBN == "" {
@ -3512,6 +3726,10 @@ func (svc *ESSearchService) AddBookToES(ctx context.Context, req *ESBook) (*ESBo
return nil, fmt.Errorf("ES返回错误: %s", res.String())
}
// 同步 Redis
if svc.SyncRedisByISBN != nil {
_ = svc.SyncRedisByISBN(req.ISBN, "update")
}
return &newBook, nil
}
@ -4152,3 +4370,77 @@ func ConvertRedisBookToESBook(redisBook *request.BookInfo) *ESBook {
IsFilter: "000000",
}
}
// ConvertRedisBookToESBookByPsi 将 Redis 中的 BookInfo 转换为 ESBook
func ConvertRedisBookToESBookByPsi(redisBook *request.BookInfoByPsi) *ESBook {
if redisBook == nil || redisBook.Isbn == "" {
return nil
}
// 构建图片对象
carouselUrls := []string{}
if len(redisBook.ImageObject.CarouselUrlArray) > 0 {
carouselUrls = redisBook.ImageObject.CarouselUrlArray
}
liveShootingUrls := []string{}
if len(redisBook.ImageObject.DetailUrlObject.LiveShootingUrl) > 0 {
liveShootingUrls = redisBook.ImageObject.DetailUrlObject.LiveShootingUrl
}
// 提取第一张轮播图作为 book_pic
bookPicPath := ""
if len(carouselUrls) > 0 {
bookPicPath = carouselUrls[0]
}
// 提取第一张实拍图作为 book_pic_s
bookPicSResponse := ""
if len(liveShootingUrls) > 0 {
bookPicSResponse = liveShootingUrls[0]
}
return &ESBook{
ISBN: redisBook.Isbn,
BookName: FlexibleString{Value: redisBook.BookName},
Author: redisBook.Author,
Publisher: redisBook.Publishing,
PublicationTime: redisBook.PublicationDate,
BindingLayout: redisBook.Binding,
PageCount: NumberOrString(strconv.FormatInt(redisBook.PagesCount, 10)),
WordCount: NumberOrString(strconv.FormatInt(redisBook.WordsCount, 10)),
BookFormat: NumberOrString(strconv.FormatInt(redisBook.Format, 10)),
FixPrice: Float64OrString(redisBook.Price),
BookPic: BookPicObj{
LocalPath: "",
PddPath: bookPicPath,
},
BookPicS: BookPicSObj{
LocalPath: "",
PddResponse: bookPicSResponse,
},
BookDefPic: BookDefPicObj{
LocalPath: "",
PddPath: redisBook.ImageObject.DefaultImageUrl,
},
BookPicB: redisBook.ImageObject.WhiteBackgroundUrl,
CatId: redisBook.CatIdObject,
// 销量等字段默认为 0
DaySale7: 0,
DaySale15: 0,
DaySale30: 0,
DaySale60: 0,
DaySale90: 0,
DaySale180: 0,
DaySale365: 0,
ThisYearSale: 0,
LastYearSale: 0,
TotalSale: 0,
BuyCounts: 0,
SellCounts: 0,
IsSuit: redisBook.IsSuit,
IsIllegal: 0,
IsReturn: 0,
IsFilter: "000000",
}
}

View File

@ -311,6 +311,8 @@ func main() {
r.GET("/api/es/searchByISBNLike", esService.SearchBooksHandler) //监控
// ISBN 精确搜索
r.GET("/api/es/searchByISBN", esService.SearchBookByISBNHandler) //监控
// ISBN 精确搜索 为psi提供
r.GET("/api/es/searchByISBNtoPsi", esService.SearchBookByISBNHandlerToPsi) //监控
// 书名搜索
r.GET("/api/es/searchByBookName", esService.SearchBookByBookNameHandler)
// 全字段搜索
@ -321,6 +323,7 @@ func main() {
//------------------------------------------------------------------------
// 初始化控制器 新
bookSearchService := service.NewBookService(esClient)
esService.SyncRedisByISBN = bookSearchService.SyncRedisByISBN
bookController := controller.NewBookController(bookSearchService)
// 根据条件查询 ES 图书信息
r.GET("/api/es/getBookBaseInfoES", bookController.SearchBookBaseInfoHandler)

View File

@ -70,6 +70,23 @@ type BookInfo struct {
CatIdObject CatIdObject `json:"cat_id"` // 分类
}
// BookInfoByPsi 书籍信息结构
type BookInfoByPsi struct {
Isbn string `json:"isbn"` // ISBN
BookName string `json:"book_name"` // 书名
Author string `json:"author"` // 作者
Publishing string `json:"publishing"` // 出版社
PublicationDate string `json:"publication_date"` // 出版时间
Binding string `json:"binding"` // 装帧
PagesCount int64 `json:"pages_count"` // 页数
WordsCount int64 `json:"words_count"` // 字数
Format int64 `json:"format"` // 开本
ImageObject *ImageObject `json:"image_object"` // 图片
Price int64 `json:"price"` // 售价
CatIdObject CatIdObject `json:"cat_id"` // 分类
IsSuit int `json:"is_suit"`
}
// ImageObject 图片对象结构
type ImageObject struct {
CarouselUrlArray []string `json:"carousel_url_array"` // 轮播图