孔夫子分类筛选
This commit is contained in:
parent
6894d4892d
commit
ce1261dcbf
177
es/es_search.go
177
es/es_search.go
@ -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 == "" {
|
||||
|
||||
2
main.go
2
main.go
@ -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) //监控
|
||||
// 书名搜索
|
||||
|
||||
@ -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 更新图书请求参数
|
||||
|
||||
@ -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{
|
||||
|
||||
Loading…
Reference in New Issue
Block a user