Commit e2e927e2 by mushishixian

bom相关搜索

parent 8ee0512d
......@@ -14,6 +14,7 @@ urls = http://192.168.2.232:9200,http://192.168.2.232:9200
index_name = future,rochester,tme,verical,element14,digikey,chip1stop,aipco,arrow,alliedelec,avnet,mouser,zhuanmai,peigenesis,powell,rs,buerklin,liexin_ziying
search_supplier = future,rochester,tme,verical,element14,digikey,chip1stop,aipco,arrow,alliedelec,avnet,mouser,peigenesis,powell,rs,buerklin,zhuanmai
hk_delivery_type_supplier = future,rochester,tme,verical,element14,digikey,chip1stop,aipco,arrow,alliedelec,avnet,mouser,peigenesis,powell,rs,buerklin
attr_index = goods_map2
[database]
user_name = root
......
......@@ -14,13 +14,13 @@ func init() {
WithMiddleware(Cors_Middleware()).
WithEndpoint(AutoSpuEndpoint(bomService)).
WithRequest(AutoSpuRequest()).
WithResponse(AutoSpuResponse()).Build("/autospu", "POST")
WithResponse(AutoSpuResponse()).Build("/search/bom/autospu", "POST")
gin_.NewBuilder().WithService(bomService).
WithMiddleware(Check_Middleware()).
WithMiddleware(Cors_Middleware()).
WithEndpoint(RecommendEndpoint(bomService)).
WithRequest(RecommendRequest()).
WithResponse(RecommendResponse()).Build("/recommend", "POST")
WithResponse(RecommendResponse()).Build("/search/bom/recommend", "POST")
}
//获取列表相关
......
package controller
import (
"fmt"
"github.com/gin-gonic/gin"
"search_server/framework/gin_"
"net/http"
"search_server/framework/gin_"
)
//放 通用中间件
//检查服务是否可用
func Check_Middleware() gin_.Middleware {
func Check_Middleware() gin_.Middleware {
return func(next gin_.Endpoint) gin_.Endpoint {
return func(context *gin.Context, request interface{}) (response interface{}, err error) {
fmt.Println("我是中间件.....")
return next(context,request)
return next(context, request)
}
}
}
......@@ -34,7 +32,7 @@ func Cors_Middleware() gin_.Middleware {
c.AbortWithStatus(http.StatusNoContent)
}
// 处理请求
return next(c,request)
return next(c, request)
}
}
}
\ No newline at end of file
}
package common
var KeywordRegular = map[string]string{
//`^(.* )?([\d\.]+)(欧|欧姆|R|r)( .*)?$`: `$1$2Ω$4`,
//`^(.* )?([\d\.]+)(U|u|μ)(.?)( .*)?$`: `$1$2Μ$4$5`,
"COG": "C0G",
"NPO|NP0|nPO|npO|npo|nP0|np0": "C0G",
"华科|华新科技|华新科": "华新",
`(欧姆|欧|O|o|R|r)`: "Ω",
`(Uf|uf|μf|uF|UF)`: "μF",
`(Uh|uh|μh|uH|UH)`: "μH",
`K`: "nF",
`v`: "V",
}
var PureNumberRegular = `(\d+(\.\d+)?)`
var PureLetterRegular = `[a-zA-Z0-9]+`
var GetAttrUnitRegular = `[\d.]|±|\+_|\+-|/|\(.*\)|\+/-|`
//属性单位对应属性
var UnitAttrMapping = map[string]string{
"r": "阻值(欧姆)|直流电阻(内阻)",
"Ω": "阻值(欧姆)|直流电阻(内阻)",
"OHM": "阻值(欧姆)|直流电阻(内阻)",
"mh": "电感",
"F": "容值",
"w": "功率",
"W": "功率",
"Ω/r ": "内阻",
"%": "精度",
"V": "额定电压",
"A": "额定电流",
}
//属性对应的基础属性
var UnitBaseMapping = map[string]string{
"μΩ": "Ω",
"mΩ": "Ω",
"Ω": "Ω",
"kΩ": "Ω",
"KΩ": "Ω",
"MΩ": "Ω",
"pF": "F",
"nF": "F",
"μF": "F",
"μf": "F",
"mF": "F",
"F": "F",
"μH": "H",
"mH": "H",
"H": "H",
"V": "V",
"kV": "V",
"mA": "A",
"A": "A",
"W": "W",
"kW": "W",
"KW": "W",
"%": "%",
}
//根据单位对值的转换,比如1kΩ=>1000Ω
var UnitValueMapping = map[string]string{
"μΩ": "0.000001",
"mΩ": "0.001",
"Ω": "1",
"kΩ": "1000",
"KΩ": "1000",
"MΩ": "1000000",
"pF": "1",
"nF": "1000",
"μF": "1000000",
"mF": "1000000000",
"F": "1000000000000",
"μH": "1",
"mH": "1000",
"H": "1000000",
"V": "1",
"kV": "1000",
"mA": "1",
"A": "1000",
"W": "1",
"kW": "1000",
"%": "0.01",
}
......@@ -4,6 +4,7 @@ import (
"crypto/md5"
"encoding/hex"
"github.com/syyongx/php2go"
"strconv"
)
// Md5 md5()
......@@ -32,4 +33,27 @@ func SubKeyWordStr(str string) string {
str = php2go.Substr(str, 0, strLen-int(num))
}
return str
}
//转成字符串的方法
func ToString(a interface{}) string {
if v, p := a.(int); p {
return strconv.Itoa(v)
}
if v, p := a.(int16); p {
return strconv.Itoa(int(v))
}
if v, p := a.(int32); p {
return strconv.Itoa(int(v))
}
if v, p := a.(uint); p {
return strconv.Itoa(int(v))
}
if v, p := a.(float32); p {
return strconv.FormatFloat(float64(v), 'f', -1, 32)
}
if v, p := a.(float64); p {
return strconv.FormatFloat(v, 'f', -1, 32)
}
return "change to String error"
}
\ No newline at end of file
......@@ -35,8 +35,11 @@ message RecommendRequest{
}
message ResponseData{
// @inject_tag: json:"total"
int64 total = 1;
// @inject_tag: json:"flag"
int32 flag = 2;
// @inject_tag: json:"data"
repeated GoodsModel data = 3;
}
......@@ -83,6 +86,7 @@ message GoodsModel {
string goods_brief = 18;
int64 moq = 19;
int64 mpq = 20;
// @inject_tag: json:"ladder_price"
repeated LADDER_PRICE ladder_price = 21;
int64 update_time = 22;
string sku_name = 23;
......@@ -93,6 +97,7 @@ message GoodsModel {
string new_cost = 28;
int64 supplier_stock = 29;
int64 self_supplier_type = 30;
// @inject_tag: json:"cn_delivery_time"
string cn_delivery_time = 31;
string brand_name = 32;
string supplier_name = 33;
......
package service
import (
"fmt"
"github.com/gomodule/redigo/redis"
"github.com/tidwall/gjson"
"gopkg.in/olivere/elastic.v5"
"regexp"
"search_server/pkg/common"
"search_server/pkg/config"
"search_server/pkg/es"
"search_server/pkg/gredis"
"strconv"
"strings"
)
//根据参数去匹配商品
func SearchAttr(attrOrigin string) (goodsName string, err error) {
//attrOrigin有可能是参数也可能是型号名称
//先去切割参数得到参数列表
attrs := splitAttrs(attrOrigin)
var attrsSlice []string
//去转换每一个参数,得到去查询es的标准格式
for _, attr := range attrs {
attr = TransformESParam(attr)
attrsSlice = append(attrsSlice, attr)
}
query := getQuery(attrsSlice)
source := elastic.NewSearchSource().Query(query)
source.Sort("brand_sort", true)
source = source.From(0).Size(1)
searchRequest := elastic.NewSearchRequest().Source(source)
body, _ := searchRequest.Body()
index := config.Get("es.attr_index").String()
result, err := es.CurlES(index, body)
goodsName = gjson.Get(result, "hits.hits.0._source.goods_name").String()
return
}
//切割参数
func splitAttrs(attrs string) (result []string) {
result = strings.Split(attrs, " ")
if len(result) > 1 {
return
}
result = strings.Split(attrs, ",")
if len(result) > 1 {
return
}
result = strings.Split(attrs, "|")
if len(result) > 1 {
return
}
result = strings.Split(attrs, ",")
if len(result) > 1 {
return
}
result = strings.Split(attrs, "/")
if len(result) > 1 {
return
}
return
}
//将写法转成正规写法,转换单位,比如有的人喜欢将Ω输成欧姆或者O,所以要统一转成正常的Ω
func changeKeyword(attr string) (result string) {
regulars := common.KeywordRegular
for regexpStr, regular := range regulars {
compile, _ := regexp.Compile(regexpStr)
attr = compile.ReplaceAllString(attr, regular)
}
return attr
}
//将属性值转成ES的标准值(例如 : 阻值(欧姆)€3000)
func TransformESParam(attr string) (result string) {
attr = changeKeyword(attr)
unitMapping := common.UnitValueMapping
//获取该属性对应的单位
for unit, _ := range unitMapping {
index := strings.Index(attr, unit)
if index > 0 {
attr = string([]rune(attr)[:index+len(unit)-1])
}
//得到截取后的参数,去得到需要用于es查询的参数
attrValue := getAttrValueByAttr(attr)
return attrValue
}
return
}
//根据参数单位或者参数值获取对应的重要属性,组成最后查询的字符串
//±
func getAttrValueByAttr(attr string) (attrValue string) {
//先找出单位
r, _ := regexp.Compile(common.GetAttrUnitRegular)
attrUnit := strings.Trim(r.ReplaceAllString(attr, ""), " ")
//如果单位是W,则要进行除法计算
if strings.ToUpper(attrUnit) == "W" {
//提取值,进行计算
attr = strings.TrimRight(attr, "W")
attr = strings.TrimRight(attr, "w")
attrSlice := strings.Split(attr, "/")
if len(attrSlice) == 2 {
var res float64
a, _ := strconv.ParseFloat(attrSlice[0], 64)
b, _ := strconv.ParseFloat(attrSlice[1], 64)
res = a / b
attr = fmt.Sprintf("%.3f", res) + "W"
}
}
//再找出纯数字
var attrNumber float64
numberR, _ := regexp.Compile(common.PureNumberRegular)
pureNumber := numberR.FindString(attr)
attrNumber, _ = strconv.ParseFloat(pureNumber, 64)
//找出对应单位需要转换的值
var attrName string
//再去找没有单位的对应属性
if attrUnit != "" {
for unit, value := range common.UnitValueMapping {
//如果不是标准最小单位,则要进行转换
if attrUnit == unit {
value64, _ := strconv.ParseFloat(value, 64)
//还要找到对应的属性,先找到基础单位
var baseUnit string
if value, exist := common.UnitBaseMapping[attrUnit]; exist {
baseUnit = value
}
if baseUnit == "" {
return attr
}
//获取重要属性名称
if value, exist := common.UnitAttrMapping[baseUnit]; exist {
attrName = value
}
attrNumberStr := common.ToString(attrNumber * value64)
attrValue = attrName + "€" + attrNumberStr
break
}
}
} else {
//再去找没有单位的对应属性
attrName, _ = redis.String(gredis.HGet("sku_map2", attr))
if attrName != "" {
attrValue = attrName + "€" + attr
} else {
attrValue = attr
}
}
return attrValue
}
//获取匹配的条件
func getQuery(attrs []string) (query *elastic.BoolQuery) {
var subQuery *elastic.TermQuery
var nestedQuery *elastic.NestedQuery
query = elastic.NewBoolQuery()
for _, attr := range attrs {
//还要判断是不是一个单位对应多个属性的
if strings.Contains(attr, "|") {
name := strings.Split(attr, "€")[0]
value := strings.Split(attr, "€")[1]
multiAttr := strings.Split(name, "|")
for _, temp := range multiAttr {
subQuery = elastic.NewTermQuery("attrs.attr_value", temp+"€"+value)
nestedQuery = elastic.NewNestedQuery("attrs", subQuery)
query.Should(nestedQuery)
}
} else {
subQuery = elastic.NewTermQuery("attrs.attr_value", attr)
nestedQuery = elastic.NewNestedQuery("attrs", subQuery)
query.Should(nestedQuery)
}
var shouldMatchNumber int
if len(attrs) > 3 {
shouldMatchNumber = 3
} else if len(attrs) >= 2 {
shouldMatchNumber = 2
} else {
shouldMatchNumber = 1
}
query.MinimumNumberShouldMatch(shouldMatchNumber)
}
return query
}
......@@ -28,7 +28,11 @@ func (bs *BomServiceImpl) Recommend(ctx context.Context, req *bom.RecommendReque
return nil
}
recommendData := Recommend(req)
rsp.Data = recommendData
if recommendData.Total == 0 {
rsp.Data = nil
} else {
rsp.Data = recommendData
}
return nil
}
......@@ -71,6 +75,11 @@ func getTermQuery(goodsName string) (query *elastic.BoolQuery) {
//推荐商品搜索
func Recommend(req *bom.RecommendRequest) (rsp *bom.ResponseData) {
//先去请求参数,看是否是参数,如果是参数的话,需要修改请求的商品名称
goodsNameByAttr, err := SearchAttr(req.GoodsName)
if goodsNameByAttr != "" {
req.GoodsName = goodsNameByAttr
}
//转换请求参数
req = changeRecommendReq(req)
//获取需要请求的索引
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment