孔夫子分类筛选

This commit is contained in:
unknown 2026-04-30 18:08:43 +08:00
parent 6894d4892d
commit ce1261dcbf
4 changed files with 255 additions and 72 deletions

View File

@ -1692,7 +1692,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" {
if key == "page" || key == "pageSize" || key == "per_page" || key == "saleSelect" || key == "picType" || key == "shopType" || key == "kongfz_include" {
continue
}
@ -1714,7 +1714,6 @@ func (svc *ESSearchService) BatchGetBookBaseInfoES(c *gin.Context) ([]ESBook, in
key = nk
}
//TODO ===== is_suit =====
if key == "is_suit" {
fmt.Printf("[DEBUG] is_suit val=%q\n", val)
if num, err := strconv.Atoi(val); err == nil {
@ -1729,7 +1728,6 @@ func (svc *ESSearchService) BatchGetBookBaseInfoES(c *gin.Context) ([]ESBook, in
continue
}
//TODO ===== is_return =====
if key == "is_return" {
fmt.Printf("[DEBUG] is_return val=%q\n", val)
if num, err := strconv.Atoi(val); err == nil {
@ -1744,7 +1742,6 @@ func (svc *ESSearchService) BatchGetBookBaseInfoES(c *gin.Context) ([]ESBook, in
continue
}
// ===== is_filter =====
// ===== is_filter按 shopType 位匹配)=====
if key == "is_filter" {
fmt.Printf("[DEBUG] is_filter val=%q\n", val)
@ -1951,32 +1948,6 @@ 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,
// },
// }
//}
must = append(must, cond)
fmt.Printf("[DEBUG] must += %v\n", cond)
continue
@ -2025,6 +1996,70 @@ func (svc *ESSearchService) BatchGetBookBaseInfoES(c *gin.Context) ([]ESBook, in
}
}
// ===== kongfz_categories孔夫子分类=====
if key == "kongfz_categories" {
kongfzInclude := c.DefaultQuery("kongfz_include", "1")
// 分割多个分类ID
categories := strings.Split(val, ",")
if len(categories) > 0 {
// 过滤空值
var validCategories []string
for _, catID := range categories {
catID = strings.TrimSpace(catID)
if catID != "" {
validCategories = append(validCategories, catID)
}
}
if len(validCategories) > 0 {
if kongfzInclude == "2" {
// 否查询不包含这些分类的数据must_not
var mustNotQueries []map[string]interface{}
for _, catID := range validCategories {
mustNotQueries = append(mustNotQueries, map[string]interface{}{
"prefix": map[string]interface{}{
"cat_id.kong_fu_zi_cat_id": catID,
},
})
}
if len(mustNotQueries) > 0 {
cond := map[string]interface{}{
"bool": map[string]interface{}{
"must_not": mustNotQueries,
},
}
must = append(must, cond)
fmt.Printf("[DEBUG] must += %v (kongfz exclude: %d categories)\n", cond, len(mustNotQueries))
}
} else {
// 是查询包含这些分类的数据should + minimum_should_match=1
var shouldQueries []map[string]interface{}
for _, catID := range validCategories {
shouldQueries = append(shouldQueries, map[string]interface{}{
"prefix": map[string]interface{}{
"cat_id.kong_fu_zi_cat_id": catID,
},
})
}
if len(shouldQueries) > 0 {
cond := map[string]interface{}{
"bool": map[string]interface{}{
"should": shouldQueries,
"minimum_should_match": 1,
},
}
must = append(must, cond)
fmt.Printf("[DEBUG] must += %v (kongfz include: %d categories)\n", cond, len(shouldQueries))
}
}
}
}
continue
}
// ===== 数值范围 =====
if key == "sell_counts" ||
strings.HasPrefix(key, "day_sale_") ||
@ -2454,6 +2489,88 @@ func (svc *ESSearchService) SearchBookByISBNHandler(c *gin.Context) {
})
}
func (svc *ESSearchService) SearchByISBNByXyCallBack(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()
// 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.ConvertToResponse()
c.JSON(200, gin.H{
"data": responseData,
})
}
func (svc *ESSearchService) SearchBookByISBNHandlerToPsi(c *gin.Context) {
isbn := c.Query("isbn")
if isbn == "" {

View File

@ -311,6 +311,8 @@ func main() {
r.GET("/api/es/searchByISBNLike", esService.SearchBooksHandler) //监控
// ISBN 精确搜索
r.GET("/api/es/searchByISBN", esService.SearchBookByISBNHandler) //监控
// ISBN 精确搜索 为咸鱼商品下架回调
r.GET("/api/es/searchByISBNByXyCallBack", esService.SearchByISBNByXyCallBack) //监控
// ISBN 精确搜索 为psi提供
r.GET("/api/es/searchByISBNtoPsi", esService.SearchBookByISBNHandlerToPsi) //监控
// 书名搜索

View File

@ -2,40 +2,42 @@ package request
// BookSearchRequest ES 搜索图书请求参数
type BookSearchRequest struct {
Page int `form:"page"` // 页码
PageSize int `form:"pageSize"` // 每页数量
PerPage int `form:"per_page"` // 每页数量 (兼容字段)
SaleSelect string `form:"saleSelect"` // 销量筛选类型
PicType string `form:"picType"` // 图片类型
ShopType string `form:"shopType"` // 店铺类型
BookName string `form:"book_name"` // 书名
BookPic string `form:"book_pic"` // 图片筛选
ISBN string `form:"isbn"` // ISBN
Author string `form:"author"` // 作者
Category string `form:"category"` // 分类
CategoryType string `form:"categoryType"` // ISBN分类类型
Publisher string `form:"publisher"` // 出版社
PublicationTime string `form:"publication_time"` // 出版时间
BindingLayout string `form:"binding_layout"` // 装帧
FixPrice string `form:"fix_price"` // 定价
IsSuit string `form:"isSuit"` // 是否套装
IsReturn string `form:"is_return"` // 是否驳回
IsFilter string `form:"is_filter"` // 过滤字段
BuyCounts string `form:"buy_counts"` // 购买次数
SellCounts string `form:"sell_counts"` // 在售数量
DaySale7 string `form:"day_sale_7"` // 7 天销量
DaySale15 string `form:"day_sale_15"` // 15 天销量
DaySale30 string `form:"day_sale_30"` // 30 天销量
DaySale60 string `form:"day_sale_60"` // 60 天销量
DaySale90 string `form:"day_sale_90"` // 90 天销量
DaySale180 string `form:"day_sale_180"` // 180 天销量
DaySale365 string `form:"day_sale_365"` // 365 天销量
ThisYearSale string `form:"this_year_sale"` // 今年销量
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"` // 字数
Page int `form:"page"` // 页码
PageSize int `form:"pageSize"` // 每页数量
PerPage int `form:"per_page"` // 每页数量 (兼容字段)
SaleSelect string `form:"saleSelect"` // 销量筛选类型
PicType string `form:"picType"` // 图片类型
ShopType string `form:"shopType"` // 店铺类型
BookName string `form:"book_name"` // 书名
BookPic string `form:"book_pic"` // 图片筛选
ISBN string `form:"isbn"` // ISBN
Author string `form:"author"` // 作者
Category string `form:"category"` // 分类
CategoryType string `form:"categoryType"` // ISBN分类类型
Publisher string `form:"publisher"` // 出版社
PublicationTime string `form:"publication_time"` // 出版时间
BindingLayout string `form:"binding_layout"` // 装帧
FixPrice string `form:"fix_price"` // 定价
IsSuit string `form:"isSuit"` // 是否套装
IsReturn string `form:"is_return"` // 是否驳回
IsFilter string `form:"is_filter"` // 过滤字段
BuyCounts string `form:"buy_counts"` // 购买次数
SellCounts string `form:"sell_counts"` // 在售数量
DaySale7 string `form:"day_sale_7"` // 7 天销量
DaySale15 string `form:"day_sale_15"` // 15 天销量
DaySale30 string `form:"day_sale_30"` // 30 天销量
DaySale60 string `form:"day_sale_60"` // 60 天销量
DaySale90 string `form:"day_sale_90"` // 90 天销量
DaySale180 string `form:"day_sale_180"` // 180 天销量
DaySale365 string `form:"day_sale_365"` // 365 天销量
ThisYearSale string `form:"this_year_sale"` // 今年销量
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"` // 字数
KongfzCategories string `form:"kongfz_categories"` // 孔夫子分类列表,多个用逗号分隔
KongfzInclude int8 `form:"kongfz_include"` // 是否涵盖1-是2-否
}
// BookUpdateRequest 更新图书请求参数

View File

@ -122,6 +122,7 @@ func (svc *BookService) SearchBookBaseInfo(request *request.BookSearchRequest) (
svc.buildIsFilterCondition(queryBuilder, request.IsFilter, request.ShopType)
svc.buildCategoryTypeCondition(queryBuilder, request.CategoryType)
svc.buildCategoryCondition(queryBuilder, request.Category)
svc.buildKongfzCategoryCondition(queryBuilder, request.KongfzCategories, request.KongfzInclude)
svc.buildBookPicCondition(queryBuilder, request.BookPic, request.PicType)
svc.buildBuyCountsCondition(queryBuilder, request.BuyCounts, saleField)
svc.buildTotalSaleRangeCondition(queryBuilder, request.TotalSaleRange)
@ -298,14 +299,10 @@ func (svc *BookService) UpdateBookFieldsByISBN(request *request.BookUpdateReques
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 不为 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自动检测并设置
@ -317,17 +314,15 @@ func (svc *BookService) UpdateBookFieldsByISBN(request *request.BookUpdateReques
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 {
if field == "is_suit" {
continue
}
// 使用配置检查字段是否允许更新
if !fieldConfig.IsAllowUpdate(field) {
log.Printf("[UpdateBookFieldsByISBN] 字段 %s 不允许更新,已跳过", field)
fmt.Printf("[UpdateBookFieldsByISBN] 字段 %s 不允许更新,已跳过", field)
continue
}
// 对 publication_time 字段做特殊处理
@ -349,7 +344,6 @@ func (svc *BookService) UpdateBookFieldsByISBN(request *request.BookUpdateReques
}
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
}
@ -1514,6 +1508,74 @@ func (svc *BookService) buildDefaultPrefixConditions(builder *ESQueryBuilder, re
}
}
// buildKongfzCategoryCondition 构建孔夫子分类查询条件
func (svc *BookService) buildKongfzCategoryCondition(builder *ESQueryBuilder, kongfzCategories string, kongfzInclude int8) {
if kongfzCategories == "" {
return
}
log.Printf("[DEBUG] kongfz_categories=%s, kongfz_include=%s", kongfzCategories, kongfzInclude)
// 分割多个分类ID
categories := strings.Split(kongfzCategories, ",")
if len(categories) == 0 {
return
}
// 过滤空值
var validCategories []string
for _, catID := range categories {
catID = strings.TrimSpace(catID)
if catID != "" {
validCategories = append(validCategories, catID)
}
}
if len(validCategories) == 0 {
return
}
// 根据 kongfzInclude 参数决定查询逻辑
if kongfzInclude == 2 {
// 否查询不包含这些分类的数据must_not
var mustNotQueries []map[string]interface{}
for _, catID := range validCategories {
mustNotQueries = append(mustNotQueries, map[string]interface{}{
"prefix": map[string]interface{}{
"cat_id.kong_fu_zi_cat_id": catID,
},
})
}
if len(mustNotQueries) > 0 {
builder.AddBoolQuery("must_not", mustNotQueries)
log.Printf("[DEBUG] Added %d kongfz category exclude queries (must_not)", len(mustNotQueries))
}
} else {
// 是查询包含这些分类的数据should + minimum_should_match=1
var shouldQueries []map[string]interface{}
for _, catID := range validCategories {
shouldQueries = append(shouldQueries, map[string]interface{}{
"prefix": map[string]interface{}{
"cat_id.kong_fu_zi_cat_id": catID,
},
})
}
if len(shouldQueries) > 0 {
// 将 should 条件包装成内层 bool 对象,作为 must 条件添加
innerBoolQuery := map[string]interface{}{
"bool": map[string]interface{}{
"should": shouldQueries,
"minimum_should_match": 1,
},
}
builder.AddBoolQuery("must", []map[string]interface{}{innerBoolQuery})
log.Printf("[DEBUG] Added kongfz category include query as nested bool in must (should match at least 1)")
}
}
}
// NewESQueryBuilder 创建 ES 查询构建器
func NewESQueryBuilder() *ESQueryBuilder {
return &ESQueryBuilder{